s3c2410与LPC系列的启动的差异
在s3c2410中,加电启动后,从0地址开始执行程序,(这个是ARM核的特性),那么可以将内部ROM,FLASH中的内容映射到0地址,因此一般来说bootloader是要在这个地址上跑的。然而LPC系列板子有一定区别,他们自己在板子加电启动后首先运行自己的bootblock,这个bootblock是位于片内flash尾部的程序,他被映射到0地址,这是一个厂商提供的程序,他可以根据需要在执行完成后再从新映射0地址到其他位置去,即进行重映射,那么如果我们重映射0地址到flash开头,就可以像s3c2410那样跑我们的bootloader了。 关键原因是LPC采用了内存映射和重映射的机制,不同的映射可以将各自不同的中断向量(还有些文字池,共64字节)映射到0地址。
详细的内容可以参考如下文档,转载自: http://shellstudio.spaces.live.com/Blog/cns!E9A9BE440E1B00B6!163.entry 《LPC2200系列ARM的Bootloader设计》
Bootloader对于ARM系统来说是很有用的,它可以使应用程序的设计和固化变得简单明了。如果你的应用程序被编译在RAM空间运行,也需要Bootloader把它从诸如SD卡等存储介质加载到RAM并启动它。所以,除了不提供有关BIOS调用接口之外,Bootloader就相当于PC的BIAS。 设计LPC2200系列ARM的Bootloader程序有其特殊性,这是因为该系列ARM有64字节的异常向量可以灵活映射,不同于S3C44B0X等ARM。 首先讲解LPC2200系列ARM的异常向量映射是什么意思吧。 一般情况下,没有MMU的ARM内核所使用的任何数据地址或指令地址都是实际的物理地址,也就是内核所能访问的4GB空间就是实际的物理空间。但是,如果有MMU的情况下,地址就要区分逻辑地址和物理地址了。此时,ARM内核使用的任何数据地址或指令地址都是逻辑地址,对它来说,4GB的逻辑空间就是它能访问的全部。但是实际上,内核所使用的逻辑地址被送往“存储器控制器”或“映射到内存的I/O模块”之前,会被MMU单元“偷梁换柱”,形成实际的物理地址再继续送到“存储器控制器”或“映射到内存的I/O模块”。有了MMU,实际很有限的RAM就可以虚拟出完整的4GB空间,而且操作系统中每个进程也都各自拥有4GB空间,互不干扰!这是因为,通过合理的管理MMU,每个进程都有它自己的MMU页表等必备资源,操作系统作进程切换时会同时设置该进程的MMU配置。这样,相当于每个进程都独立拥有自己的MMU管理单元一样。 LPC2200系列ARM没有强悍的MMU,但是它有简单的映射管理单元,这已经很不错了!我暂且叫该单元为LPC-MMU吧。对于LPC2200系列ARM处理器,LPC-MMU是极其简化的MMU。1、LPC-MMU只能映射64字节;2、LPC-MMU所映射的起始物理地址固定为4组,即0x00000000,0x7FFFE000,0x40000000,0x80000000;3、LPC-MMU所映射的逻辑地址只有0x00000000~0x0000003F;当芯片复位后,ARM内核的PC寄存器被复位成0,该值就是内核去指令所需的逻辑地址。复位后,LPC-MMU首先把逻辑地址0x00000000映射到物理地址0x7FFFE000,从而启动芯片内部固化的BootBlock代码。BootBlock代码再检查有关引脚的高低电平来决定将逻辑地址映射到物理地址0x00000000还是物理地址0x80000000。 从这里可以看出,当逻辑地址0x00000000映射到物理地址0x00000000,相当于没有LPC-MMU单元!这就是说,如果你设计的Bootloader是从LPC2200系列ARM的内部FLASH启动的,那么就没有什么特殊性,和其他ARM一样就是了! 如果你的Bootloader是从外部FLASH启动的(也就是物理地址0x80000000开始的空间),那么就需要我这里所说的内容了。 很简单,你只要把异常向量代码和常量池(共64字节)写成如下形式即可!不过这样的话该Bootloader只能在0x80000000的地址启动了。此外,Bootloader需要把自己的RO段、RW段拷贝到RAM,并设置ZI段。而这些代码都不在其编译时设置的空间运行,所以都需要使用相对当前PC寻址的指令来实现,有一定的技巧性。最后,Bootloader还需要把自己的PC以及返回地址LR都转移到正确的运行时地址去,Bootloader从此走上阳关大道。 ;//***************************************************************************** ;//64字节的映射空间开始 ResetEntry ;//32字节异常向量 LDR PC, Reset_Addr ;//复位异常入口(进入SVR32模式) LDR PC, Undefined_Addr ;//未定义指令异常入口(进入UNDF32模式) LDR PC, SWI_Addr ;//软件中断异常入口(进入SVR32模式) LDR PC, Prefetch_Addr ;//预取中止异常入口(进入ABT32模式) LDR PC, DataAbort_Addr ;//数据中止异常入口(进入ABT32模式) DCD 0xb9205f80 ;//保留的矢量,对于LPC系列ARM的内部FLASH有特殊作用 LDR PC, [PC, #-0xff0] ;//中断异常入口(进入IRQ32模式) LDR PC, FIQ_Addr ;//快中断异常入口(进入FIQ32模式) ;//32字节常量池 Reset_Addr DCD 0x80000040 ;//注意这里原来是Reset_Handler Undefined_Addr DCD Undefined_Handler SWI_Addr DCD SWI_Handler Prefetch_Addr DCD Prefetch_Handler DataAbort_Addr DCD DataAbort_Handler Reserve_Addr DCD 0 IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler ;//64字节的映射空间结束 ;//***************************************************************************** ;//以下开始是系统复位处理程序 Reset_Handler ... ... ;//***************************************************************************** ;//启动代码结束 END |