分类: LINUX
2012-11-10 16:55:14
Uboot启动过程
1 入口:_start_e500
Mpc8548 复位后,只映射了最后的4K有效地址空间。Bootpg 区域被定位到LAST PAGE。该区域中的代码主要做三件事情,
清零一些寄存器;
设置exception table;
添加TLB项,映射更大的区域。
复位入口代码在文件resetvec.s中,只有一条跳转命令,将位于flash的0xfffffffc处,见uboot根目录\ board\xyt_cct_8548_1\u-boot.lds。
.section .resetvec,"ax"
b _start_e500
下面的代码位于u-boot-1.3.0\cpu\mpc85xx\start.s中
.section .bootpg,"ax"
.globl _start_e500
_start_e500: 上电复位后默认映射的最后页,即LAST ,位于0xfffff000,见uboot根目录\ board\cds\mpc8548cds\u-boot.lds。
1.1 使能L1 cache
1.2 设置异常向量表
1.3 配置MMU单元,即TLB0和TLB1 条目,此时虚实地址相同。默认只映射flash的最后的4KB空间,所以此空间也叫bootpg。配置MMU之后,可以访问所有flash。
1.4 重定位CCSRBAR,即cpu的寄存器映射区域,control config status registers
1.5 配置Local Access Window
1.6 设置L1 data cache 作为INIT_RAM使用
1.7 跳到_start_cont 处开始执行
1.8 设置堆栈到INIT_RAM中(L1 data cache),此时ddr尚未规划。
1.9 调用cpu_init_f() 设置全局变量gd空间,并清零。bank空间
1.10 调用board_init_f()调用板级初始化函数,逐个调用[]中的板级初始化函数,初始化console interface。分配从0—256MB的RAM空间。初始化bd_t *bd 板级数据结构信息。调用函数relocate_code () 把代码从flash中load到RAM中并从RAM中继续运行!
其中:addr_sp指向栈顶(最大地址)。id指向gd_t,即全局数据结构。 Addr指向代码搬移的目的地址。
2 relocate_code
relocate_code ( ) 把代码从flash中load到RAM中
并从RAM中继续运行!
2.1将栈由内部RAM(cache)空间重新定位到外部DDR内
2.2中拷贝代码到DDR RAM中,在RAM中的高端,具体地址根据RAM大小确定。
2.3重定位中断向量到DDR RAM中
2.4 计算in_ram函数在RAM中的地址,并跳转到该函数继续执行。
2.5 调整GOT表中函数的地址,并清零bss段。
2.6 调用board_init_r()函数
2.6.1 更新uboot命令函数地址,因为代码已拷贝到RAM中。
2.6.2 调用函数trap_init () copy exception 代码到RAM低地址处
2.6.3 调用flash_init()获取flash校验等,并填写flash信息到bd中。
2.6.4 调用cpu_init_r()初始化L2 cache。
2.6.5调用mem_malloc_init()初始化uboot阶段的,可以allocate的memory,我们板卡定义了128KB空间。
2.6.6 调用env_relocate(),如果enviroment 包含在编译的镜像中,则修改其地址。否则,申请空间,并拷贝默认的environment。
2.6.7 获取ethernet mac地址,并保存到bd中。
2.6.8 调用getenv_IPaddr()从environment 信息中获取ip地址,保存到bd中。
2.6.9 devices_init(),根据板卡头文件定义,注册必要的设备,
2.6.10 jumptable_init()初始化gd中的jump table中的函数,如get_version,malloc,getenv
2.6.11调用console_init_r()把串口设备设置为标准的输入、输出、错误控制终端。
2.6.12 调用interrupt_init()使能中断。
2.6.13 获取uImage 在RAM中的地址
注:在板卡头文件中定义了uImage(kernel),ramdisk和flat device tree 在RAM中的地址,在调试过程中需要把他们分别下载到对应的地址,即可调用bootm命令启动linux。
如:ramdiskaddr=2000000,fdtaddr=400000,uImage在1000000。
2.6.14 调用 初始化以太网接口(ethernet)。在mpc8548 平台上,调用了相应的函数tsec_initialize()注册tsec以太网控制器设备。在板级头文件中有如下宏定义,
#define "TSEC2"
函数中出现了环境变量“ethact”,不知“act”代表啥意思?在default_environment没找到。
2.6.15 调用main_loop()函数,进入主循环。
3. main_loop()函数
参考:E:\data sheet\网络下载\王兴伟-uboot命令-20120906\UbootCommands.pdf
Uboot运行稳定后,可以用它的内部命令来查看目标系统的信息,设置环境变量等。Uboot在硬件初始化完成后将进入main_loop()函数,main_loop()函数将进入一个无限循环,当用户输入命令后,首先将调用run_command()命令进行处理,在run_command()函数中,将调用find_cmd()函数把用户从终端输入的命令进行比较,当find_cmd()返回值不为0时证明系统支持用户输入的命令,在对命令进行检验后最后将调用命令处理函数。
Find_cmd()函数将从系统默认的命令表中查询一个匹配的命令,查看源代码发现,find_cmd()将把__u_boot_cmd_start开始到__u_boot_cmd_end结束的所有命令一一和用户输入的命令进行比较。而关于__u_boot_cmd_start和__u_boot_cmd_end的定义是在板级相关的链接文件中,比如board\xyt_cct_8548_1\u-boot.lds中有以下定义
的基础上的
3.1 install_auto_complete() 安装自动补全的函数
3.2 s = getenv ("bootcmd") 获取引导命令。
3.3 run_command (s, 0) 在规定的时间内没有任何按键,运行引导内核的命令。这个命令是在板卡配置头文件中定义的。
3.4 len = readline (CFG_PROMPT); 输出uboot的命令行提示符,读取从串口输入的字符并保存到全局数组console_buffer[]中,遇到回车字符则返回。此时尚未判断命令有效性。
3.5 rc = run_command (lastcommand, flag) 匹配并运行命令。