OK6410开发板Uboot学习总结----(一)Uboot启动分析

OK6410开发板的Uboot是在1.1.6版本上进行移植的,为了便于分析,创建一个Source Insight工程,把源码下board目录里跟samsung相关的文件、cpu目录下s3c64xx文件夹、include目录里asm-arm和configs下的smdk6410.h文件,还有lib_arm目录下board.c文件都添加到工程中,然后就可以分析Uboot启动流程了。
Uboot启动分两个阶段
第一阶段:主要是SOC内部的初始化,板级的初始化比较少,所以移植的修改量比较小。此阶段完全由汇编语言编写,代码主体分布在/uboot1.1.6/cpu/s3c64xx/start.S和/uboot1.1.6/board/samsung/smdk6410/ lowlevel_init.S文件中。
第二阶段:主要是板级的初始化,SOC内部的初始化比较少,移植时修改量主要在此。该阶段主要由c语言编写,代码主体分布在/uboot/lib_arm/board.c中。

先来分析第一阶段
得先分析u-boot.lds链接脚本,才能知道程序入口,首先看uboot1.1.6\board\samsung\smdk6410\u-boot.lds文件:
启动入口
ENTRY定义了程序入口,指定_start为程序入口,第一段代码在start.o中,所以先看start.S文件:
跳转reset
代码很简单,直接跳转reset标签,代码如下:
reset代码
由于复位后中断向量表未初始化,所以这里先禁IRQ(普通中断)和FIQ(快速中断),然后设置SVC模式,即超级用户模式,好进行相应配置。下面进入cpu_init_crit函数:
cpu_init_crit函数
这里禁用了MMU和缓存Cache,MMU是内存管理单元,负责转换虚拟地址与物理地址的,为避免操作上麻烦,先要禁掉MMU;而禁Cache是因为上电后DDR未初始化,当CPU从cache中取数据时,可能导致数据预取异常。剩下的代码就不分析了,直接看如何到lowlevel_init.S文件的:
跳转lowlevel_init
这里直接一个长跳转搞定,来分析lowlevel_init.S文件:
lowlevel_init函数
显然lowlevel_init函数已经定义为全局的了,这个函数里初始化相关GPIO,禁止看门狗,初始化时钟,初始化串口:
uart_asm_init
这里初始化串口只是测试一下串口0,波特率都是固定的:
uart_asm_init函数
uart_asm_init函数具体代码下一篇“修改调试串口号”文章里再详细分析,串口初始化后打印字母O进行测试:
打印O字符
4F在ASCII里面对应的就是大写字母O,之后函数返回到lowlevel_init中:
打印K
uart_asm_init函数结束后,又往r1里放了4b(对应字母K),这就是为什么OK6410上电时会输出一个OK了。lowlevel_init函数结束后回到start.S中:
拷贝代码
这段代码比较重要,判断Uboot目前是从哪里启动的,然后完成自身的拷贝工作,OK6410支持从SD卡启动也是这部分处理的,关于如何完成Uboot拷贝的,后面“OK6410从SD卡启动分析”专题再解释这部分内容。这里直接看拷贝后执行的代码:
拷贝代码之后
这里使能MMU单元,继续往下看:
初始化堆栈
初始化堆栈设置,为加载C代码做好准备,终于分析到了汇编代码的尾声:
跳转C代码
代码最后,把_start_armboot赋值给pc寄存器,到这里第一阶段就完成了,开始进入第二阶段。_start_armboot指向的是C程序的start_armboot函数,代码在uboot1.1.6\lib_arm\board.c文件中:
start_armboot函数分析
开始的全局变量初始化就不说了,看底层初始化工作:
底层初始化
这里把init_fnc_ptr这个函数指针指向了init_sequence数组:
init_sequence数组
数组里初始化的内容还比较多,这部分都初始化没问题,才能进行下面的flash初始化,环境变量设置等工作,最后进入死循环,等待命令处理:
进入主循环
到这里Uboot的主体启动流程就分析完了,以后再专题介绍重要部分的分析。

猜你喜欢

转载自blog.csdn.net/xinxin_2011/article/details/85092009