小谈一下Bootloader的原理与实现

2746阅读 0评论2007-11-06 yunyuaner
分类:

三星s3c2410支持Nand Flash启动,但这并不意味着程序能够在Nand Flash中运行,这点与Nor Flash中不同。原因在于,Nand Flash不支持按字节寻址,它的最小寻址单位是页(512+16bytes,其中可用容量为512bytes,后16bytes一般用于存放校验信息。所以,Nand Flash启动仅仅是在系统上电后,cpu拷贝Nand Flash的前4K内容到stepping stone中运行,后者是cpu中一个高速缓存。这么以来有两个问题:其一,bootloader代码如果大于4K,就必须做程序代码段,数据段的搬运工作,后面具体谈;其二,代码搬运后,要重定向pc,使其指向SDRAM所对应的内存。

典型的bootloader设计,将代码分成两个阶段,这主要是为了在代码的可移植性和效率上做一个折中。因为bootloader是高度硬件相关的,不同体系结构的cpu初始化等操作截然不同。代码的第一阶段主要任务的是初始化硬件设备,为bootloader第二阶段准备好RAM空间并初始化堆栈。这部分内容一般由汇编实现。第二阶段的主要工作是设置系统时钟,设置Translation Table并初始化MMU,设置内核启动参数并将内核映像由Nand Flash拷贝到相应的SDRAM中,最后跳转到内核的入口点。

值得一提的是,为什么bootloader的初始部分要用汇编?一种解释是有些操作必须用汇编实现,如协处理器寄存器的操作。更重要的问题在于,c程序需要一个具体的运行环境,如代码段,初始化的数据段,BSS段,栈,堆等。尤其是栈,它承担着C函数调用参数传递,局部变量的存储等工作(虽然C89中并没有迹象显示栈对于C程序是必须的)。再者,启动时仅有Nand Flash的前4K内容在stepping stone中运行,这如何能保证C程序的完整性呢?因此,通常的做法是将第一阶段的汇编代码在单独的模块实现,并链接到程序的开始处。然后有它将完整的bootloader程序映像文件从Nand Flash中搬运至SDRAM中,并设置好上面谈到的各个段。这么以来,第二阶段的代码就会在SDRAM中运行。

第一阶段汇编代码的入口处,一般首先放置的是cpu异常的跳转代码,如IRQFIQSWIUndef等。中断源将中断请求送至cpu的中断控制器,通过中断控制器仲裁,决定被响应与否或响应的顺序。例如IRQ异常,cpu会跳转到IRQ异常跳转指令处,该指令修改pc地址使其指向IRQ异常处理例程。在处理历程中,程序通过判断中断源的偏移量,确定该IRQ异常的具体类型,计算出这种IRQ异常的中断响应函数,这个过程是通过查阅IRQ中断向量表来实现的。IRQ中断向量表中定义了具体IRQ中断响应函数的地址,这些地址可以在第二阶段根据需要而设置,例如Timer的中断响应函数等等。

第二阶段首先做的是设置时钟。s3c2410手册中明确指出,复位后,cpu使用外部时钟源,而非MPLL。通过设置MPLL,从而初始化HCLKFCLKPCLK,后者给cpu和外设提供稳定的时钟。接着可以对中断控制器和串口进行初始化,这样就可以通过串口向PC终端输出一些交互信息了。

接着打开MMU,指令缓存和数据缓存。这里可以设置协处理器CP15Register 13ProcID)为0,并建立从虚地址到物理地址的直接映射关系。

以上工作完成后,将存放于Nand Flash中的kernel和启动参数搬运到内存中的特定区域,重新设置好时钟(与内核中的保持一致), 关闭MMU,指令缓存和数据缓存,跳转到内核的起始地址就可以运行了。

至此,bootloader就完成了它的历史使命,如果人品好的话,kernel就会乖乖的运行了。当然,这里假定的是手头上已经有一份移植并裁剪好的内核。

上一篇:一个关于ProcID的问题
下一篇:描述符传递探讨