分享

ARM9启动程序分析

 岁月楼 2011-11-23

ARM9启动程序分析  

2010-10-07 13:45:48|  分类: 嵌入式 |  标签: |字号 订阅

本文以S3C2410X 的实际应用为例介绍了ARM9处理器的初始化过程,重点分析了ARM9芯片的中断处理机制和MMU机制,其原理和方法同样适用于ARM720T、ARM9、ARM10E、ARM11、Xscale 系列等处理器。

        ARM处理器的软件系统一般包括启动程序、操作系统、驱动程序及应用程序,其中启动程序最先执行,完成一些必要的系统级的初始化操作,因此写好启动程序是顺利完成系统开发的前提,也是调试和开发ARM处理器的关键。本文针对ARM处理器的特点,以含MMU功能的ARM芯片为例对启动程序的特点及实现方法进行了解释,并在S3C2410X芯片上进行了具体实现。

1.基本原理

1.1 异常中断处理机制

         ARM 处理器对异常中断的响应过程如下:①将CPSR寄存器内容保存到SPSR 寄存器,保存当前状态 ②设置当前程序状态寄存器CPSR中的相应位 ③寄存器lr_mode设置成返回地址 ④将程序计数器PC值设置成该异常中断向量地址。

         ARM 体系的异常中断如下表所示,内核在接受到中断请求后,总是跳转到表中的固定地址。

ARM9处理器S3C2410X启动程序分析 - 老K - 老K的博客

        从表中可以看出,地址0x20之前,都为CPU硬件异常处理向量所使用,每个中断对应4bytes 空间,一般0X0处为ROM时,用来存放一条数据读取指令直接向程序计数器赋值,或者存放一条跳转指令跳到异常中断处理程序。而实际中为了程序的易读性和可移植性,通常按图一的中断流程处理。

ARM9处理器S3C2410X启动程序分析 - 老K - 老K的博客

        异常中断发生后,系统首先跳转到相应的异常中断向量地址,该地址存放了一条跳转指令,系统跳到相应的中断函数地址解析程序,在解析程序中读取中断向量表,得到目标地址,跳转到该目标地址,执行中断服务函数。一般中断服务处理分两级结构,第一级中断处理程序读取中断源,然后调用第二级中断处理程序,第二级中断处理程序实现功能调用。由于使用了中断向量表,用户在开发时就完全避免了中断跳转地址的计算,可以方便的指定不同的函数为该中断服务,只需把中断处理程序的起始地址填入中断向量表中的对应地址即可。异常中断处理程序返回时首先恢复被中断程序的处理器状态,然后返回到发生中断指令的下一条指令开始执行。复位异常中断处理程序不需要返回。

1.2 存储器管理单元(MMU)

        基于ARM7TDMI内核的处理器可以通过对存储器控制模块的配置寄存器编程来初始化存储器系统,基于ARM720T、ARM9、ARM10E、ARM11等内核的处理器集成有存储器管理单元管理内存空间,支持基于段和页的地址变换,在不需要复杂的文件系统时,只需用基于段的一级地址变换过程。

        通过写系统控制协处理器的寄存器1的第0位可以允许和禁止MMU。复位后这位为0,MMU被禁止。允许MMU之前必须在内存中建立适当的转换表,且所有相关的CP15寄存器要正确初始化。建立转换表之前存储器访问将按如下处理:

        1)由具体的芯片设计确定 MMU 禁止时是否能够允许高速缓存和写缓存。

        2)没有存储器访问权限的检查,MMU 也不产生异常信号。

        3)物理地址与虚拟地址相同,即使用平坦地址映射模式。

        禁止和允许MMU改变了虚拟地址到物理地址的映射,故允许MMU时所有的高速缓存要被刷新,另外允许MMU的指令的物理地址和虚拟地址不同,取指令将变得复杂化,所以,建议允许MMU的指令具有相同的物理地址和虚拟地址。MMU支持段和页的存储器访问,段构成1MB的存储器块,支持允许只用一个 TLB 入口去映射大的存储器区间。转换表分一级页表和二级页表。一级页表存储段转换表和指向二级页表的指针,二级页表存储大页和小页的转换表。

ARM9处理器S3C2410X启动程序分析 - 老K - 老K的博客

 

        以段为单位的地址变换过程只需要一级页表,而以页为单位的地址变换过程还需要二级页表。当片上的TLB中不包括要求的虚拟地址入口时,转换过程被启动。转换表基址寄存器(CP15的C2寄存器)保存着第一级转换表基址的物理地址,Bit[31:14]有效,bit[13:0]为0,故一级页表必须是16KB对齐的。

2. 软件实现

        启动代码主要完成建立异常中断处理向量表,堆栈初始化,MMU初始化,进入主函数。启动程序一般分两段,第一段完成系统最初的初始化,并把第二段启动程序、操作系统、驱动程序及应用程序完全搬运到SDRAM中,最后将 PC 值设为第二段程序入口地址。第二段开始部分与第一段初始化部分相同,但并不是初始化操作,只是重复执行一遍代码,然后初始化MMU,最终调用操作系统。

        S3C2410X有4KB内部RAM,调试时可直接将第一段启动程序映象下载到内部RAM的初始处,其它所有程序下载到SDRAM 中。调试完成后将所有程序下载入FLASH,系统由FLASH启动,完成部分初始化和程序搬运工作,在SDRAM 中完成剩余初始化任务。

2.1 设置入口指针

        启动程序必须定义入口指针,而且整个应用程序只有一个入口指针。编译前要设置好相关的编译选项,包括程序入口所在的目标文件和文件中具体的模块区域。入口指针定义如下:


AREA boot,CODE,READONLY

ENTRY


2.2 设置中断向量

         由地址0X0开始存入下面程序,其中保留中断指向一个只含返回指令的哑函数,用来防止错误中断引起系统的混乱。


B  ResetHandler

B  HandlerUndef

B  HandlerSWI

B  HandlerPabort

B  HandlerDabort

B  .

B  HandlerIRQ

B  HandlerFIQ


        异常中断地址解析程序每一个中断源都要使用,采用了宏定义,若采用子程序可以节约存储空间,但要保存和恢复相关寄存器和子程序现场,这增加了额外的开销,故此处采用宏汇编技术。主要作用是读中断向量表,并使 PC 跳转到向量表中的目标地址。


MACRO

$HandlerLabel HANDLER $HandleLabel

$HandlerLabel

sub     sp,sp,#4

stmfd  sp!,{r0}

ldr       r0,=$HandleLabel       //读中断向量表

ldr       r0,[r0]                                  

str       r0,[sp,#4]

ldmfd   sp!,{r0,pc}                 //至目标地址

MEND


       下面是宏定义的展开,使各中断与向量表的地址对应起来。


HandlerFIQ      HANDLER    HandleFIQ

HandlerIRQ      HANDLER    HandleIRQ


        复位中断的服务程序总在最初的启动程序里面,系统复位后从地址0跳到地址ResetHandler,开始系统初始化,包括使无效快表和cache,并把第二段程序代码完整拷贝到SDRAM的指定空间中,代码如下面所示。复位中断服务程序结束时使PC值指向该指定空间的起始位置,按照下面代码,该位置地址为0X31000000。


ldr      r1,=PHYBASE                 //将要拷贝代码的物理地址

ldr      r2, = 0x31000000         //拷贝代码在SDRAM 的目的地址
ldr      r3, =0x40000               // 要拷贝的代码数
13      ldr  r4, [r1], #4                        

str      r4, [r2], #4

subs   r3, r3, #1

bne    %B13


        其它中断服务的初始化,即把它们的中断服务程序起始地址填入中断向量表的操作,既可在第一段启动程序中进行,也可在后继程序中进行。在FIQ和IRQ中断服务程序中首先要判断中断请求状态寄存器,根据状态位决定中断类型,启动该类型的服务任务。

2.3 初始化堆栈

        系统堆栈初始化取决于用户使用了哪些处理器模式,以及系统需要处理哪些错误类型。对于将要用到的每一种模式,都应该定义好堆栈指针。此步骤和下面的一些操作可在第一段启动程序中进行,也可在第二段启动程序中进行,这依赖程序员的设计,没有固定的格式。为了减小初始化时间,我把尽可能多的程序放在了第二段启动代码中。

2.4 MMU初始化

        在MMU初始化之前应先建立数据缓冲池,一般把数据缓冲池放在程序的末尾,程序如下,第一列为虚拟地址,第二列为物理地址,第三列为段大小。


      OEMAddressTable

      DCD 0x8C000000, 0x08000000, 32      //32 MB SROM(SRAM/ROM) BANK 1

      DCD 0x84000000, 0x10000000, 32      //32 MB SROM(SRAM/ROM) BANK 2


      下面是基于一级页表的MMU初始化程序。


       PTs       EQU      0x31010000      //一级页表基地址  ,必须是 16KB 对齐的

       ldr     r0,=OEMAddressTable

       mov r11,r0                                   //r0 为物理地址到虚拟地址的映射表

       ldr  r10, =PTs                              //r10 装入页表基地址

       mov r0, #0x02 

       orr r0, r0, #0x400                      //设置读写位

20   mov r1, r11                                //(r1) = 存储阵列指针

25   ldr  r2, [r1], #4                          //(r2) = 虚拟地址

       ldr  r3, [r1], #4                          //(r3) = 物理地址

       ldr  r4, [r1], #4                          //(r4) = 对应块的大小

       cmp r4, #0                                //判断是否结束

       beq %F29

       ldr r5, =0xFFF00000

      and  r2, r2, r5                          

      and  r3, r3, r5                            

      Add r2, r10, r2, LSR #18           //虚拟地址右移18 位,在加上页表基地址,作为一级描述符地址,这个地址用于索引页表中的页表项

      Add r0, r0, r3                            //r0 为页表项内容(实际物理地址的高 12 位加上访问控制属性)

28  str  r0, [r2], #4                         //把页表项内容存储到对应的页表项地址中

      add r0, r0, #0x00100000         //因为是一级地址变换,所以进行下一个条目变换要把内容加1M

      sub  r4, r4, #1                            

      cmp r4, #0

      bne  %B28                               //建立下 1MB 的地址对应关系

      bic r0, r0, #0xF0000000    

      bic  r0, r0, #0x0FF00000    

      b     %B25                                //配置下一段


        在建立地址映射关系时,一般使允许MMU的指令的物理地址和虚拟地址相同,完成MMU初始化后使能MMU和Caches。

2.5 初始化必要的I/O状态

        某些要求严格的 I/O 和用户需要在调用主程序前完成的状态控制,需要在启动程序里面完成初始化,特别是一些输出设备,上电后往往呈现出一种随机态,需要及时加以控制。

2.6 调用主程序

        初始化程序结束时调用主程序,把系统控制权移交给操作系统。


    ldr r0,=0x31000000

    mov pc,r0


       上面各步操作顺序并非固定不变,可以由程序员适当调整。

3.总结

        本文主要介绍了ARM9处理器S3C2410X 的初始化过程,重点讲述ARM9芯片的中断处理机制和MMU机制,虽然以S3C2410X 为例,但对ARM720T、ARM9、ARM10E、Xscale等处理器同样适用。本文涉及的程序都经作者实际使用,没有出现问题。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多