首发:嵌入式客栈
作者:逸珺
导读:前文对U-Boot架构设计做了分析,本文来梳理一下U-Boot在具体板子上的移植工作,主要记录整体思路、要点,以触类旁通而记之。
1.收集Boot相关信息
NanoPC-T3 是友善之臂为企业用户设计的主板,采用三星八核Cortex -A53架构的S5P6818处理器。其主要技术参数:
需要将采用该SOC的方式以U-Boot引导,那么首先应该将Boot的相关信息进行收集分析。
支持的Boot模式:
外部静态存储器ExternalStatic Memory Boot
复位首条指令直接从外部静态存储器引导。
自< SEC/_S5P6818X/_Users/_Manual/_preliminary/_Ver/_0.00.pdf>
SOC内置了20KB的iROMBOOT,这是一段固化的boot程序,通过识别外部Boot配置进入相应的Boot模式,完成内部boot到用户boot程序的第一阶段Boot。
从datasheet 看见该SOC内部实现了iROMBOOT,而SPL(Secondaryprogramloader)是u-boot第一阶段执行的代码。主要负责搬移u-boot第二阶段的代码到。iROMBOOT已经实现了这一功能,故不需要用户实现SPL了。
1.2 NanoPC-T3 板级信息
由于boot一般与板子的设计配置相关,大多由IO口配置进行选择,既然支持上述如何之多的Boot模式,那么拿到的板子又支持哪些引导模式呢?
可见nanoPC T3仅支持SDMMC Boot模式,进入对应的章节,可看出支持三个SD通道。通过从SD存储卡,MMC存储卡和eMMC中读取iROMBOOT并通过使用SDHC模块将其加载到内存中,iROMBOOT执行用户启动代码。此方法称为SDHCBOOT。SDCLK输出400 kHz用于识别,输出24 MHz用于数据传输。
SD3已经电路下拉为低:
SD卡是(secure digital memory card)安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备,是在MMC基础上发展起来的,其内部存储介质大都为NAND Flash增加了两个主要特色:
可以设置所存储的使用权限,防止数据被他人复制;第二是传输速度比2.11版mmc卡快。
特性:
1)可选通信协议:SD模式和SPI模式
2)可变时钟频率:0~25MHz
3)通信电压范围:2.0~3.6V
4)数据寿命:10万次编程/擦除
5)正向兼容MMC卡;
6)运行在25M的频率上,数据带宽是4位,因此最大传输速率是12.5MHz(12.5兆字节每秒) <自百度知道>
eMMC (Embedded Multi Media Card)是MMC协会订立、主要针对手机或平板电脑等产品的内嵌式存储器标准规格。eMMC在封装中集成了一个控制器,提供标准接口并管理闪存,使得手机厂商就能专注于产品开发的其它部分,并缩短向市场推出产品的时间。其内部存储介质大都为NAND Flash。
硬件地址空间:
该SOC具有两个内存控制器:
板上网口采用什么芯片需要,RTL8211E-VB-CG 集成 10/100/1000M 以太网收发器,显示接口:RGB LCD接口/HDMI
至此,第一阶段收集了那些为移植需要准备的信息?
2.移植
2.1 明确移植内容
在具体实施之前,首先须总体上明确How to do:
2.2明确Boot流程
明确Boot流程,需要明确有哪些地方需要根据所选SOC,板级硬件设计做出移植:
如前文分析,u-boot的启动流程主要分亮部分。
第一阶段:芯片复位,执行复位跳转,从自各自芯片的start.S开始执行汇编代码
一般而言,start.S 位于- arch/ic/_xxx/cpu/start.S
如:
- arch/arm/cpu/armv7/start.S
- arch/powerpc/cpu/mpc83xx/start.S
-arch/mips/cpu/start.S
为什么这是复位入口呢?这取决于如何链接,由u-boot.lds指定:
链接文件位于./arch/arm/cpu/armv8/u-boot.lds
注:因为nanoPC-T3 S5P6818的SOC是一颗8核A53核,A53是armv8架构。
第二阶段:lowlevel/_init(),board/_init/_f(),board/_init/_r():
lowlevel/_init():
board/_init/_f():
此处清除了BSS。对于SPL,如果定义了CONFIG/_SPL/_STACK/_R,则此时将堆栈和global/_data重定位到CONFIG/_SPL/_STACK/_R/_ADDR之下。 对于非SPL,U-Boot被重定位以在内存顶部运行。
board/_init/_r():
CONFIG/_SPL/_STACK/_R/_ADDR指向SDRAM,则堆栈可选地位于SDRAM中
以上关于lowlevel/_init(),board/_init/_f(),board/_init/_r()翻译自./README
这里有几个概念需要进一步解析,方便下面理解:
堆/栈的大小由下面的宏定义:
Stack size= CONFIG/_SYS/_RESERVE/_MEM/_SIZE-
CONFIG/_SYS/_MALLOC/_LEN
这几个宏定义了内存上界、堆上下界、栈的上下界有编译器、C库实现越界保护机制。
global/_data:
该结构体收集板子的基本信息,内存,名称,CPU时钟,环境变量,标准IO,设备驱动句柄等等。
红色部分信息将堆分配情况与U-Boot全局数据结构关联。
一个程序本质上由这三个段由链接器链接而成。
2.3 创建板子文件
位置board/my/_vendor/my/_board/my/_board.c, 对于nanoPC-T3而言
./board/s5p6818/nanopi3/ board.c
需声明DECLARE/_GLOBAL/_DATA/_PTR指针,因为本模块需要对gd成员进行初始化,ARM32等价于r9寄存器,ARM64等价于寄存器x18
位于./arch/arm/include/asm/global/_data.h
2.4 创建Kconfig配置文件
board/my/_vendor/my/_board/Kconfig
需定义Kconfig对于board需要的相关变量SYS/_BOARD,SYS/_VENDOR,SYS/_CONFIG/_NAME。
由于S5P6818是一颗64位芯片,那么32位/64位将变成可选配置。故这里新创建了S5P6818/_FEATURES用以配置32位/64位,当取值为no表示为32位配置。
include/configs/SYS/_CONFIG/_NAME.h
2.6 创建板子Makefile
board/my/_vendor/my/_board/Makefile 对nanoPC-T3而言:
obj-y:=board.o hwrev.o onewire.o lcds.o
由于需要实现LCD以及单线触摸控制器,则需要将上述文件编译。
2.7 创建板子defconfig
configs/my/_board/_defconfig, 对nanoPC-T3而言:
s5p6818/_nanopi3
/_defconfig
对于新版的U-boot已支持make menuconfig,可以运行该命令进行其他配置,然后将生成的.config文件拷贝至此。
mv .config ./configs/s5p6818/_nanopi3/_defconfig
主要裁剪支持的驱动,以及shell命令等
注:旧版本的U-Boot使用boards.cfg添加板子。
2.8 创建板子头文件
include/confi gs/my/_board.h,对nanoPC-T3而言:
include/confi gs/ s5p6818/_nanopi3.h
环境变量:
这些定义由./common下环境变量管理模块负责维护,其结构体定义如下,主要为字符串常量。
2.8 引导分析
为了能够重新映射内存,U-Boot随后跳至其链接地址。为了能够在C中实现初始化代码,在内部双端RAM中设置了一个(很小的)初始堆栈(如果CPU提供了诸如MPC8xx或MPC8260之类的功能),或者在数据的锁定部分中缓存。之后,U-Boot初始化CPU内核,缓存和SIU。
接下来,使用初步映射来映射所有可用的存储体。例如,将它们放在512 MB边界上(0x20000000的倍数:0x00000000和0x20000000上的SDRAM,0x40000000和0x60000000上的Flash,0x80000000上的SRAM)。然后,将UPMA编程用于SDRAM访问。使用临时配置,将运行简单的内存测试,以确定SDRAM存储区的大小。
如果有多个SDRAM存储区,并且存储区的大小不同,则首先映射最大的存储区。对于相等的大小,将首先映射第一个存储区(CS2#)。第一个映射始终是针对地址0x00000000的,后面紧跟着任何其他存储区以创建从0开始的连续存储器。
然后,监视器将自身安装在SDRAM区域的高端,并分配内存供malloc()和全局Board Info数据使用;同样,将异常矢量代码复制到低RAM页面中,并建立最终堆栈。
只有在此重定位之后,才能拥有“正常”的C环境。由于受到多种方式的限制,主要是因为从ROM运行,并且必须将代码重定位到RAM中的新地址运行。
至于上述过程重定向,主要利用链接绑定以实现符号表位置可知,从将u-boot映象拷贝到内存可实现运行切换。
/*指定输出格式elf64-littleaarch64*/
而在./arch/arm/lib/sections.c 定义了对应的全局符号,这样就实现了链接地址绑定:
char __bss_start[0] __attribute__((section(".__bss_start")));
下面对crt0/_64.S 汇编代码做简要注释帮助理解重定向过程:
ENTRY(_main) /*声明入口*/
总结:
_—END_—
审核编辑 黄昊宇全部0条评论
快来发表一下你的评论吧 !