ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:25.04KB ,
资源ID:17347470      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/17347470.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(关于ARM loader的一些心得Word格式文档下载.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

关于ARM loader的一些心得Word格式文档下载.docx

1、变量的初始化.变量的初始化是个什么样的概念呢?举个简单的例子,如果你程序里有个变量这样定义(这是不可能避免的吧):uchar i=5;main()就是说,i这个变量,初始值是5,具体反映到硬件上面,就是说,i这个变量所对应的内存单元,它在相应程序要执行之前,这个内存单元里保存的数值应该是5.否则,这个内存单元保存的是上电时硬件随机产生的不确定数值.自己来做变量初始化的工作,其实不是必要的,而仅仅是当使用的编译器是ADS,才是必要的.如果使用的是其他编译器,有可能不用做这步.譬如Keil的编译器在链接成最终代码时,会自动添加一段变量初始化的代码,而GCC编译器记得也是这样.现在用的编译器是ADS

2、。因此,很遗憾,loader又得复杂一点点了,新的列表如下:3.在内存里建立异常中断向量表,并在loader实现查表功能4.初始化变量这四步做完,确实可以一马平川了,但如果你想独步天下,还需要做得更好.作为一个编程人员,通常都是完美主义者,偏执狂,所追求的是无止境的效率和自由,我想很少有人会拒绝耍一些提高程序效率的手段吧?于是下面可以再多了一个步骤,但这个功能对KS8695来说其实不是必需的(因为KS8695用的是NOR flash,允许单字节随机访问,代码可以在NOR flash里执行,但对于别的ARM芯片,如果用的是NAND flash,由于不支持单字节读以及随机地址访问,则必须把代码拷贝

3、到RAM里,从RAM里执行),只是让我们的代码跑得更快.这个功能是:把代码在放在RAM里执行.对于51核这些微控制器(题外话,广义嵌入式有两种,一种是MCU,Micro control unit,叫微控制器,特点是运算速度比较慢,偏重于对运算速度要求不高而用于逻辑控制的场合,另外的就是MPU,Micro process unit,叫微处理器,特点是处理数据能力非常强,专用于对数据处理要求较高的场合)来说,由于它的应用场合往往对速度要求不高,因此,并没有设计成代码可以在RAM执行的结构,也就是说,对标准的51核来说,它的代码全部都是存放在ROM里,每个指令要执行时,先从ROM里取指(读取指令),

4、然后解释执行.而ARM是微处理器,往往用于数据处理场合,对程序效率要求很敏感,因此ARM核都设计成可以从ROM里读取指令运行也可以从RAM里读取指令运行的结构,它的PC指针如果指向的地址是ROM范围内的地址,那么读取的指令就是ROM里的指令,如果指向的是RAM范围,那么读取的指令就是存放在RAM里的.众所周知,RAM的读取速度比FLASH快很多。KS8695包括很多ARM核的MPU,他们的中断入口都是放在前端靠近0地址的地方,而中断处理往往是非常频繁的,这里的代码被访问率非常高,因此,如果能把中断处理甚至整个执行程序的代码都拷贝到RAM里并在RAM里执行,无疑会大大提高代码的执行效率.在通常的

5、loader设计里,强烈建议至少把中断向量表相关拷贝到内存里,然后使用MMU或其他类型的映射功能,把内存里的中断向量表映射到0地址开头的地址。ARM里要完成这项工作通常有两个步骤:第一,把ROM里的代码拷贝到RAM里去,第二,把PC指针指向RAM里的相应地址,让代码从RAM里读取执行.第一步几乎所有的ARM loader都差不多,但读取的是nor flash还是nand flash,还是有分别的,如果存放代码的是NOR FLASH,可以以字节为单位拷贝代码放到RAM里,如果是nand flash,就要按flash的参数,以block为单位读取放到ram里去.而对于第二步,在上述做完拷贝后,直接

6、把PC置成RAM里存放执行代码的所在地址就OK了。最后步骤归纳如下:5.拷贝代码到RAM里,让代码在RAM里执行下面是loader的代码,已经包括了上面提到的步骤,另外还掺加了一些额外的硬件初始化步骤,注释已经够详细,不想再多说:;*Entry: 0x0000,0000*INCLUDE mem.incINCLUDE casia.incIMPORT MainIMPORT |Image$RO$Base| ;/* RO代码段起始地址 */IMPORT |Image$RO$Limit| ;/* RO 代码段结束地址 */IMPORT |Image$RW$Base| ;/* RW代码段起始地址 */IM

7、PORT |Image$RW$Limit| ;/* RW 代码段结束地址 */IMPORT |Image$ZI$Base| ;/* ZI 代码段起始地址 */IMPORT |Image$ZI$Limit| ;/* ZI 代码段结束地址 */关于各种模式处理的宏定义,因为进入各种模式时必须保存原现场(pc值及会被影响的寄存器),这保护工作对于所有模式都是一样的代码,因此用一宏定义代替。 MACRO$HandlerLabel HANDLER $HandleLabel$HandlerLabelsub sp,sp,#4 ;decrement sp(to store jump address)stmfd

8、 sp!,r0 ;PUSH the work register to stack(lr does not push because it return to original address)ldr r0,=$HandleLabel;load the address of HandleXXX to r0ldr r0,r0 ;load the contents(service routine start address) of HandleXXXstr r0,sp,#4 ;store the contents(ISR) of HandleXXX to stackldmfd sp!,r0,pc ;

9、POP the work register and pc(jump to ISR)MENDAREA Init,CODE,READONLYENTRYImage$RO$Base DCD |Image$RO$Base|Image$RO$Limit DCD |Image$RO$Limit|Image$RW$Base DCD |Image$RW$Base|Image$RW$Limit DCD |Image$RW$Limit|Image$ZI$Base DCD |Image$ZI$Base|Image$ZI$Limit DCD |Image$ZI$Limit|= ENTRY 0地址开始的执行代码,应该是各

10、种模式的跳转代码,包括中断跳转b ResetHandlerb HandlerUndef ;handler for Undefined modeb HandlerSWI ;handler for SWI interruptb HandlerPabort ;handler for PAbortb HandlerDabort ;handler for DAbortb . ;reservedb HandlerIRQ ;handler for IRQ interruptb HandlerFIQ ;handler for FIQ interruptHandlerFIQ HANDLER HandleFIQ

11、;这里的HANDLER为前面的MICRO宏定义HandlerIRQ HANDLER HandleIRQHandlerUndef HANDLER HandleUndefHandlerSWI HANDLER HandleSWIHandlerDabort HANDLER HandleDabortHandlerPabort HANDLER HandlePabort 中断向量表查表程序,下面的中断服务里会调用到。ARM922T核的不是向量中断,也无法设置成向量中断模式,只能自己建立中断向量表,自己处理中断跳转IsrIRQ reserved for PC,r8-r9 ldr r9,=REG_IRQ_PEN

12、D_PRIORITYldr r9,r9 ;读取优先级最高的中断标志,看现在最需要处理的中断是哪个ldr r8,=REG_INT_STATUS ;ldr r8,r8 ;读取所有的中断标志and r9,r8,r9 ;相与,结果存放在r9ldr r8,=HandleCCR ;最开始的中断服务程序入口存放变量,其他的中断服务程序入口存放变量都是以这个为开始递增的isrloop ;通过中断标志,计算该中断的服务程序入口cmp r9,#0beq isrquit ;如果为零表示中断已经撤销,退出cmp r9,#1 ;是否为1beq isrcontinue ;是1则退出循环右移mov r9,r9,lsr #1

13、 ;r9右移1add r8,r8,#4 ;r8+4,每个中断服务程序入口地址占4个字节,因此每次要递增4个b isrloopisrcontinue获取相应的中断程序入口地址str r8,sp,#8,r8-r9,pc ;把中断程序入口地址置入pc,程序跳入对应的中断服务程序isrquit,r8-r9 ;恢复r8跟r9add sp,sp,#4 ;恢复sp指针subs pc,r14,#4 ;读取原先的pc值(保存在此模式下的r14)并返回,包括返回原先模式,这里必须要用subs指令,否则不能返回原工作模式ResetHandler第一步,最初的初始化程序开始,首先应该是关中断,关看门狗,因为看门狗跟中

14、断在现阶段会给你带来不可预知的错误,完全没必要打开特别留意的是,某些ARM核默认是开看门狗的,下面提到的上电后默认情况仅指KS8695这个CPUks8695的所有系统寄存器,都是位于0x03ffxxxx地址LDR R1,=0x3ffe408 ;关闭看门狗,默认已经关闭,可不做此步LDR R0,=0xffffff00STR R0,R1LDR R1,=0x3ffe200 ;定义中断模式,所有中断为IRQ中断,非FIQ类型,上电后默认为全IRQ,可不做此步LDR R0,=0x00000000LDR R1,=0x3ffe204 ;禁止所有中断,免得中断对初始化工作造成影响,此步不做也行,默认上电后是禁

15、止所有中断的LDR R1,=0x3ff4000;LDR R0,=0xD7F20008LDR R1,=0x3ff4008;LDR R0,=0x0第二步初始化,先把flash映射到00x001fffff,初始化SDRAM,把SDRAM映射到0x02000000到0x027fffffks8695上电后默认仅有flash地址,无SDRAM,也没有给SDRAM分配地址,因此必须得初始化SDRAM并映射好,否则就没有RAM用映射时映射的地址别覆盖掉系统寄存器区,也就是0x03ffxxxx区LDR R1,=0x3ff4010 ;FLASH BANK0控制寄存器,映射FLASH地址为0X00000000到0X

16、001fffff,共2M大小,普通ROM模式LDR R0,=(0x1f:SHL:22)+(0:12)+0x70) ;末地址10位首地址10位其他参数LDR R1,=0x3ff4038 ;SDRAM RAS CAS参数LDR R0,=0x0000000aLDR R1,=0x3ff403c ;SDRAM 缓冲控制寄存器LDR R0,=0x20033LDR R1,=0x3ff4040 ;SDRAM 刷新参数LDR R0,=0x00000168LDR R1,=0x3ff4030 ;SDRAM BANK0控制器寄存器,映射RAM地址为0x02000000到0x027fffff,2 banks,32BIT

17、,8MLDR R0,=(0x27f:22)+(0x200:12)+0x0e);第三步,把所有代码拷贝到SDRAM里去,注意,现阶段的SDRAM的访问地址是从0x02000000开始的r0 = source addressr1 = target addressr2 = source end addressldr r1, =0x02000000ldr r0, =0x00000000ldr r2, =|Image$ZI$Base| ;计算flash区里需要拷贝到RAM的0地址开始的代码长度,也就是ro+rw那段ldr r3,=|Image$RW$Base|sub r2,r2,r3 ;rw段长度=zi

18、 base-rw baseldr r3,=|Image$RO$Limit|add r2,r2,r3copy_ro_loopldmia r0!, r3-r10 ;每次拷贝8个byte,依次放入r3到r10寄存器stmia r1!每次依次写入8个byte到目的地址cmp r0, r2ble copy_ro_loop ;少于或等于时都跳,大于时继续第四步,下面准备重新把SDRAM映射到00x007f,ffff,8m,把flash映射到0x010000000x011f,ffff,2m这步工作的好处是,映射内存到0地址后,这样无需使用MMU的映射因为整个代码已经拷贝到SDRAM里,即使是发生中断,中断入

19、口也是在SDRAM里,直接从SDRAM里执行代码,执行效率非常高先把各个入口地址保存好,必须先把地址先存好在寄存器里,由于remap容易造成地址失效,如果不预先保存在寄存器而是保存在flash存储或者sdram存储里,remap后地址变了,从存储器读取到的返回地址就不是计划中的地址了ldr r3,=(remap_rom+0x02000000)ldr r4,=(remap_ram+0x01000000)ldr r2,=continue把pc指向高端地址,也就是现在的SDRAM内存,跳到内存里,由于内存里已经有一份FLASH的完整拷贝,因此得以继续执行程序这是因为下面要做flash的remap,必

20、须先跳到内存里执行后面的代码,否则一remap,pc指向的下一指令就不存在,跑飞了mov pc,r3下面这段代码其实已经是在SDRAM里执行,把FLASH地址映射到高端上去,好把低端地址腾出来给SDRAM用remap_romFLASH BANK0控制寄存器,映射FLASH地址为0x0100,0000到0x011f,ffff,共2M大小,普通ROM模式LDR R0,=(0x11f:22)+(0x100:12)+0x70)同理,必须跳回刚remap好的flash里继续执行代码,然后才能对SDRAM进行remapmov pc,r4 ;这指令还是在SDRAM里执行,这指令的后面指令,已经是在FLASH

21、里了下面这段代码其实已经是在FLASH里执行remap_ramSDRAM BANK0控制器寄存器,映射RAM地址为0x0000,0000到0x007f,ffff,2 banks,32BIT,8MLDR R0,=(0x7f:22)+(0x0:12)+0x0e)STR R0,R1做完SDRAM remap后,就直接跳回低端地址执行,低端地址现在已经是SDRAM区了mov pc,r2 ;这指令还是在flash里执行,这指令的后一指令,已经是在SDRAM里了上面代码执行完后,下面的代码已经在RAM里执行了因为上面的代码已经把SDRAM映射到0地址开始的地方,而此时的PC指针还是指向偏移0地址不远的地方,因此下一执行的指令地址还是在0地址不远的一个地方此时,要执行的指令已经是在SDRAM的区域里了continue第五步,初始化各种模式所需要的堆栈,别忘了,经过上面几步映射后,我们的SDRAM有效范围是00x007f,ffff,定义的堆栈指针可不能超过这范围而且也不能占据低地址0开始的一

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1