Unix Linux 2016-11-19
Hi,大家好!我是CrazyCatJack,你们可以叫我CCJ或者疯猫。今天我给大家带来的是u-boot的源代码汇编段分析,以后还会给大家讲解后续的C代码,请持续关注哦^_^
先简单说一下u-boot,在嵌入式开发中,u-boot起着至关重要的作用:读出嵌入式系统内核并启动内核。因此非常有必要对u-boot进行理解,了解其是如何启动内核的,这样我们才能随心所欲地初始化系统,无论基于什么架构,什么开发板,都能够轻松的去启动内核。这一点难道不是最有吸引力的吗?
如果大家有看到我的前一篇博客,就会对u-boot的启动有一定程度的了解了。执行u-boot,首先是从启动文件start.S开始的。它位于你所用CPU的文件下。比如我的路径就是:“uboot-1.1.6/cpu/arm920t/start.S”。这基于你具体使用的CPU架构。打开它:
首先看第一条语句,跳转到reset语句执行。那我们来看reset。
根据注释,我们知道是要先让CPU进入SVC32模式,也就是管理模式。具体的汇编代码不再分析,需要大家自己去学习。若是你已经掌握了一定的汇编,则完全可以阅读本篇博客,不然还是建议先学习一下汇编。u-boot代码量还是很大的,再接着往下来看:
根据注释,我们要关闭看门狗,否则此时CPU会不断地重启重启。。。很明显,在定义了具体的SOC型号后,define寄存器地址。包括看门狗控制寄存器、中断屏蔽寄存器、还有时钟分频。关闭看门狗,关闭所有的中断。
这里如果你是从NOR Flash启动的,这里的r0就是0。如果你是从下载器或者调试器直接将代码下载到SDRAM的,r0就为你自己设置的SDRAM代码段的启动地址(详情看我的上一篇博客)。这里会比较一下这两个地址是否相同,就可以知道你是从哪里启动的了,是从NOR Flash还是直接从SDRAM。如果你从SDRAM启动,则说明你已经初始化了SDRAM。如果你是从FLASH启动,则这里跳转到 cpu_init_crit函数执行。
这里是关caches,关MMU,然后跳转到lowlevel_init函数执行开发板相关的配置。
这一部分程序博主开始很不理解,因为这里涉及到了一个链接地址的概念。博主分不清此刻程序到底是在FLASH还是在RAM上。但是后来在论坛提问,大神给予了解答,博主终于懂了。这里的SMRDATA是即将在SDRAM存储的13个寄存器的链接地址,也就是说此刻这13个寄存器的值并未真正存储到SDRAM,而是在NOR FLASH中。但是我们用这个SDRAM上的寄存器链接地址减去SDRAM代码段开始地址(_TEXT_BASE),就得出了相对地址。又因为NOR FLASH的起始地址是0,所以起始地址+相对地址就是这13个寄存器在NOR FLASH上真正存储的开始地址。这段代码就是因为上述原因而进行的地址转换。目的是得到13个寄存器在NOR FLASH上存储的开始地址。
我们接着分析,下一步根据注释是设置堆栈,将代码段地址给r0,这里我们设置的是0x33F80000.然后设置MALLOC段:分配空间,r0减去此段大小。再设置CFG_GBL_DATA段,同理r0减去此段大小,分配空间。再设置IRQ段、FIQ段。最后r0减去12,留出3个字节的空间。下一步是跳转到clock_init设置时钟。
relocate这段代码是要将u-boot从FLASH复制到RAM。_start是当前代码的开始地址,_TEXT_BASE是代码段的链接地址,如果二者相等则证明是从RAM启动,无需复制代码。转去执行清BSS段代码。_armboot_start是在当前文件即start.S中定义的第一条指令的运行地址,_bss_start是在board/开发板型号/u-boot.lds中定义的代码段结束地址。结束地址减去开始地址等于代码段长度,赋值给r2。然后就是如果你是从FLASH启动则需进行代码赋值,这里是用C函数实现。
这里我们设置的是USB48MHZ,总时钟400MHZ.根据代码,再接下来是清BSS段。
所谓的BSS段就是未初始化的静态变量和全局变量,或者初始化为0的静态变量和全局变量。将他们存入只会浪费空间。所以用到他们的时候再去初始化。这里的清BSS段就是这样的作用。
清完BSS段就是要复制代码到RAM。这里韦东山老师是自己用C语言实现的从FLASH到RAM程序的复制。因为版权原因,我们不便贴出。其实也是很容易的内存块复制。
最后是进入到了_start_armboot。这是一个C函数,从这里开始就是用C来实现读出内核,启动内核了。硬件相关的汇编程序讲解结束!
版权声明:
本博客未经允许,禁止转载。
我尊重DENX Software Engineering为开源代码做出的贡献,他们做出u-boot,并将其开源供全世界的人们下载、学习和使用。
博主是跟随韦东山老师学习的嵌入式Linux开发,其中的CopyCode2Ram函数为韦东山老师编写。本文源于对学习成果的总结。
CCJ
2016-11-19 11:14:00