DIY编程器网
标题:
u-boot启动过程分析——基于lpc2210的移植代码
[打印本页]
作者:
liyf
时间:
2012-1-27 13:59
标题:
u-boot启动过程分析——基于lpc2210的移植代码
作者:刘咖,华清远见嵌入式培训中心讲师。
?
u-boot是一种普遍用于嵌入式系统中的Bootloader。
Bootloader介绍
Bootloader是进行嵌入式开发必然会接触的一个概念,它是嵌入式学院二期课程中嵌入式linux系统开发方面的重要内容。本篇文章主要讲解Bootloader的基本概念以及内部原理,这部分内容的掌握将对嵌入式linux系统开发的学习非常有帮助!
Bootloader的定义:Bootloader是在操作系统运行之前执行的一小段程序,通过这一小段程序,我们可以初始化硬件设备、建立内存空间的映射表,从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备。意思就是说如果我们要想让一个操作系统在我们的板子上运转起来,我们就必须首先对我们的板子进行一些基本配置和初始化,然后才可以将操作系统引导进来运行。具体在Bootloader中完成了哪些操作我们会在后面分析到,这里我们先来回忆一下PC的体系结构:PC机中的引导加载程序是由BIOS和位于硬盘MBR中的OS Boot Loader(比如LILO和GRUB等)一起组成的,BIOS在完成硬件检测和资源分配后,将硬盘MBR中的Boot Loader读到系统的RAM中,然后将控制权交给OS Boot Loader。Boot Loader的主要运行任务就是将内核映象从硬盘上读到RAM中,然后跳转到内核的入口点去运行,即开始启动操作系统。在嵌入式系统中,通常并没有像BIOS那样的固件程序(注:有的嵌入式cpu也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由Boot Loader来完成。比如在一个基于ARM7TDMI core的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的Boot Loader程序。(先想一下,通用PC和嵌入式系统为何会在此处存在如此的差异呢?)
Bootloader是基于特定硬件平台来实现的,因此几乎不可能为所有的嵌入式系统建立一个通用的Bootloader,不同的处理器架构都有不同的Bootloader,Bootloader不但依赖于cpu的体系结构,还依赖于嵌入式系统板级设备的配置。对于2块不同的板子而言,即使他们使用的是相同的处理器,要想让运行在一块板子上的Bootloader程序也能运行在另一块板子上,一般也需要修改Bootloader的源程序。
Bootloader的启动方式
Bootloader的启动方式主要有网络启动方式、磁盘启动方式和Flash启动方式。
1、网络启动方式
图2? Start.s程序流程
代码真正开始是在_start,设置异常向量表,这样在cpu发生异常时就跳转到/cpu/arm7tdmi/interrupts中去执行相应得中断代码。在interrupts文件中大部分的异常代码都没有实现具体的功能,只是打印一些异常消息,其中关键的是reset中断代码,跳到reset入口地址。
reset复位入口之前有一些段的声明。在reset中,首先是将cpu设置为svc32模式下,并屏蔽所有irq和fiq。在u-boot中除了定时器使用了中断外,其他的基本上都不需要使用中断,比如串口通信和网络等通信等,在u-boot中只要完成一些简单的通信就可以了,所以在这里屏蔽掉了所有的中断响应。
初始化外部总线。这部分首先设置了I/O口功能,包括串口、网络接口等的设置,其他I/O口都设置为GPIO。然后设置BCFG0"BCFG3,即外部总线控制器。这里bank0对应Flash,设置为16位宽度,总线速度设为最慢,以实现稳定的操作;Bank1对应DRAM,设置和Flash相同;Bank2对应RTL8019。
接下来是cpu关键设置,包括系统重映射(告诉处理器在系统发生中断的时候到外部存储器中去读取中断向量表)和系统频率。
lowlevel_init,设定RAM的时序,并将中断控制器清零。这些部分和特定的平台有关,但大致的流程都是一样的。
下面就是代码的搬移阶段了。为了获得更快的执行速度,通常把stage2加载到RAM空间中来执行,因此必须为加载Boot Loader的stage2准备好一段可用的RAM空间范围。空间大小最好是memory page大小(通常是4KB)的倍数,一般而言,1M的RAM空间已经足够了。flash中存储的u-boot可执行文件中,代码段、数据段以及BSS段都是首尾相连存储的,所以在计算搬移大小的时候就是利用了用BSS段的首地址减去代码的首地址,这样算出来的就是实际使用的空间。程序用一个循环将代码搬移到0x81180000,即RAM底端1M空间用来存储代码。然后程序继续将中断向量表搬到RAM的顶端。由于stage2通常是C语言执行代码,所以还要建立堆栈去。在堆栈区之前还要将malloc分配的空间以及全局数据所需的空间空下来,他们的大小是由宏定义给出的,可以在相应位置修改。基本内存分布图:
图3? 搬移后内存分布情况图
接下来是u-boot启动的第二个阶段,是用c代码写的,这部分是一些相对变化不大的部分,我们针对不同的板子改变它调用的一些初始化函数,并且通过设置一些宏定义来改变初始化的流程,所以这些代码在移植的过程中并不需要修改,也是错误相对较少出现的文件。在文件的开始先是定义了一个函数指针数组,通过这个数组,程序通过一个循环来按顺序进行常规的初始化,并在其后通过一些宏定义来初始化一些特定的设备。在最后程序进入一个循环,main_loop。这个循环接收用户输入的命令,以设置参数或者进行启动引导。
本篇文章将分析重点放在了前面的start.s上,是因为这部分无论在移植还是在调试过程中都是最容易出问题的地方,要解决问题就需要程序员对代码进行修改,所以在这里简单介绍了一下start.s的基本流程,希望能对大家有所帮助。
“本文由华清远见http://www.embedu.org/index.htm提供”
欢迎光临 DIY编程器网 (http://diybcq.com/)
Powered by Discuz! X3.2