AT91系列微处理器启动过程的分析与实现

[09-12 18:19:15]   来源:http://www.88dzw.com  单片机学习   阅读:8450

文章摘要:难点分析Remap在Remap的过程中,存储器的地址改变时,PC指针并不会自动改变,因此,要保证Remap以后程序能够继续运行下去,必须采取非正常跳转的手段,使PC指针指向Remap后的程序地址,以下是实现Remap过程的具体指令序列:ldr????? r12, PtInitRemap;得到Remap以后的跳转地址,存入r12ldmia??? r10!,{r0-r9,r11};将EBI各个寄存器的设置值存入r0到r9和r11,其中r11指向EBI寄存器的基地址stmia??? r11!, {r0-r9}; 将r0到r9寄存器中的数值存入r11指向的EBI各个寄存器,进行Remap?mov???

AT91系列微处理器启动过程的分析与实现,标签:单片机开发,单片机原理,单片机教程,http://www.88dzw.com

难点分析
Remap
  在Remap的过程中,存储器的地址改变时,PC指针并不会自动改变,因此,要保证Remap以后程序能够继续运行下去,必须采取非正常跳转的手段,使PC指针指向Remap后的程序地址,以下是实现Remap过程的具体指令序列:
ldr????? r12, PtInitRemap
;得到Remap以后的跳转地址,存入r12
ldmia??? r10!,{r0-r9,r11}
;将EBI各个寄存器的设置值存入r0到r9和r11,其中r11指向EBI寄存器的基地址
stmia??? r11!, {r0-r9}
; 将r0到r9寄存器中的数值存入r11指向的EBI各个寄存器,进行Remap
?mov???? pc, r12
;跳转到位于Flash rom中的地址继续运行
PtInitRemap
????? DCD???? InitRemap
; 定义Remap后的跳转目的地址。
InitRemap
;这里是跳转目的地址?
ldr r0, =AT91C_SRAM_AFTER _REMAP_SIZE;这里是Remap后的第一条指令
对上述指令的执行过程详细分析就会发现,由于ARM采用三级流水线的体系结构,在执行stmia??? r11!, {r0-r9}指令进行Remap时,mov?? pc,r12指令已经被读取。当Remap指令结束后,pc指针开始从重映射到地址0x00的片内RAM中预取指令,但此时片内RAM并没有有效的指令。接下来执行的mov?? pc,r12指令将标号InitRemap的地址赋值给了pc指针,实际上是使程序转移到位于Remap以后的Flash ROM中去继续执行,同时这条指令断开了流水线,使流水线从InitRemap后的指令开始重新取指。这样,就保证了Remap以后,程序能够在Flash ROM中继续执行下去,做到了“无缝连接”。

从加载时域到运行时域的转换
  一般而言,一个程序包括只读的代码段和可读写的数据段。在ARM的集成开发环境中,只读的代码段和常量被称作RO段(ReadOnly);可读写的全局变量和静态变量被称作RW段(ReadWrite);RW段中要被初始化为零的变量被称为ZI段(ZeroInit)。对于嵌入式系统而言,程序映象都是存储在Flash存储器等一些非易失性器件中的,而在运行时,程序中的RW段必须重新装载到可读写的RAM中。这就涉及到程序的加载时域和运行时域。简单来说,程序的加载时域就是指程序烧入Flash中的状态,运行时域是指程序执行时的状态。对于比较简单的情况,可以在ADS集成开发环境的ARM LINKER选项中指定RO BASE和RW BASE,告知连接器RO和RW的连接基地址。对于复杂情况,如RO段被分成几部分并映射到存储空间的多个地方时,需要创建一个称为“分布装载描述文件”的文本文件,通知连接器把程序的某一部分连接在存储器的某个地址空间。需要指出的是,分布装载描述文件中的定义要按照系统重定向后的存储器分布情况进行。

  在引导程序完成初始化的任务后,应该把主程序转移到RAM中去运行,以加快系统的运行速度。
根据以上的设想和系统的存储器分布,本系统的分布装载文件应该如下设置。
FLASH 0x01000000
; 一个称作FLASH的加载时域,起始地址0x01000000
{
??? FLASH 0x01000000
; 一个称作FLASH的运行时域,起始地址0x01000000
??? {
?????? cstartup.o (+RO,+FIRST)
; 域中包括cstartup.o的RO段,first关键字指出本部分要放在首地址
* (+RO)
; 其余RO段也放在FLASH中。
??? }
??? SRAM? 0x02000000
; 一个称作SRAM的运行时域,起始地址0x02000000
??? {?? *(+RW,+ZI)
;其余的RW和ZI段放在SRAM中运行。
main.o (+RO,+RW,+ZI)
; 域中包括主程序main.o的RO、RW、ZI段。告诉连接器:主程序在RAM中运行。
??? }
}
  连接器只是根据装载文件的描述将程序的各部分分段连接,最后生成一个可以烧入Flash的加载时域文件映象。从加载时域到运行时域的转换由系统引导程序完成,所以,启动代码必须进行数据和代码搬移工作,以完成该转换。在ADS中,系统提供了缺省的系统函数为用户进行程序和数据的搬移,不需要再由用户在自己的程序中添加数据搬移代码。这一部分是由系统函数__main完成的,__main根据分布装载文件完成代码和数据的复制,并把ZI数据区清零。接着_main跳进_rt_entry,进行STACK和HEAP等的初始化。最后_rt_entry才调用应用程序的入口main(),进入真正的用户程序中去。当应用程序执行完时,_rt_entry又将控制权交还给调试器。整个系统的初始化过程如图2所示。

  当用户使用分布装载功能时,必须重调用系统函数_user_initial_stackheap(),否则连接器会报错。C库函数部分由系统在连接时自动加入,用户代码部分的_user_initial_stackheap()和$sub$$main()在需要时可由用户改变。这时,系统的控制权已经交给用户编写的应用程序,启动过程结束。

结语
  本启动代码已经在AT91M55800A上调试通过。随着32位ARM处理器的广泛应用,越来越多的工程技术人员开始进行ARM的开发,本文介绍的一些方法和注意点有助于开发人员理解ARM的启动过程,结合自己的开发板硬件设置写出自己的启动代码。■ ( 赵鹏  蒋烈辉 )


上一页  [1] [2] 


Tag:单片机学习单片机开发,单片机原理,单片机教程单片机学习

《AT91系列微处理器启动过程的分析与实现》相关文章

分类导航
最新更新
热门排行