您的位置 首页 传感器

ARM的发动代码(3):反常向量

ARM的启动代码是非常重要的代码,直接关系到系统的稳定性和可靠性(这里主要讨论arm7,arm9;cortex系列的会在后续的文章中讨论)。上次我们通…

ARM发动代码是非常重要的代码,直接关系到体系的稳定性和可靠性(这儿首要评论arm7,arm9;cortex系列的会在后续的文章中评论)。前次咱们经过两则文章评论了ARM发动代码的进程,

ARM的发动代码(1):介绍

ARM的发动代码(2):AT91SAM9260发动详解

这次咱们聊聊ARM的代码的详细编写。那么什么样的代码会涉及到这些问题呢?

1.Bootloader或许坐落发动序列上进行加载其他应用程序的程序;

2.独自的二进制镜像,直接能够在ARM处理器上直接履行。

这两种代码都需求对ARM的发动进程有深化了解。说深化了解,其实只要一条,闹闹记住,ARM7,ARM9的反常向量表从地址0开端。这是铁打不能改动的现实。这样一来,全部的程序都要用0地址存储自己的向量表,这岂不是成了稀缺资源。所以不同家的ARM芯片都供给了一些办法处理这种问题。

关于arm7,许多芯片运用片内的flash。如at91sam7x256。为了便利,常常需求bootloader+应用程序的办法。At91sam7x256供给了一个叫bootMemory的地址,1Mbytes,从0x0~0x000FFFFF。能够映射成为内部的Flash和内部的SRAM。这个映射是:

BootMemory:0x0~0x000FFFFF,1Mbytes

InternalFlash:0x00100000~0x001FFFFF,1Mbytes

InternalSRAM:0x00200000~0x002FFFFF,1Mbytes

当BootMemory映射成InternalFlash,flash的地址仍然从0x00100000开端,可是从0x0拜访,等同于拜访0x00100000;当映射成为InternalSRAM,SRAM地址不变,拜访0x0地址,等同于拜访0x00200000。其实硬件做起来很简略,便是将地址线用逻辑电路略微处理一下。

因为代码都要存放在FLASH里,不然,没电今后,啥都没有了,也无法再次发动。所以,反常向量要从0x0开端,那么天然也要把向量放在这个方位,7×256上电今后默许bootmemory映射从flash开端。也便是说,把向量放在0x00100000即可处理这样的问题。

当0x00100000被占用今后,bootloader的向量问题处理了,那用户代码的中止向量怎么办呢?不行能把bootloader的向量擦了,把用户自己的向量写入,那岂不是bootloader也完了?这儿有个小技巧,假如用户程序从0x00101000开端,向量仍然从这个方位开端。只不过,在翻开中止,向量真实起作用前,将0x00101000这个当地向量到SRAM的首地址上,然后切换BootMemory映射SRAM。那么向量仍然从0x0开端。这样的话,不论多少级boot代码,都能够完美的处理该问题。

ARM9除了以上的办法,还有个终极的利器,那便是MMU,你快乐放哪就放哪,在向量起作用之前,用MMU将其地址变换为0即可。一点技术含量都没有。

道理总是简略的,完成起来总是有点点弯弯绕。咱们看看实践的完成吧。这是7×256的向量代码:

__vector:

LDR PC,[PC,#24];Absolutejumpcanreach4GByte

LDRPC,[PC,#24];Branchtoundef_handler

LDRPC,[PC,#24];Branchtoswi_handler

LDRPC,[PC,#24];Branchtoprefetch_handler

LDRPC,[PC,#24];Branchtodata_handler

DC320;Reserved

LDR PC,[PC,#24] ;Branchtoirq_handler

LDR PC,[PC,#24] ;Branchtofiq_handler

DC32_program_start

DC32ARM_ExceptUndefInstrHndlr

DC32ARM_ExceptSwiHndlr

DC32ARM_ExceptPrefetchAbortHndlr

DC32ARM_ExceptDataAbortHndlr

DC320

DC32ARM_ExceptIrqHndlr

DC32ARM_ExceptFiqHndlr

这儿相对比较简略,对这个指令做一下解说。LDR PC,[PC,#24]是将当时PC+24的地址的值载入到PC寄存器中。因为ARM流水线的问题,当时履行的指令,地址现已是后边两条了。所以,是+24并不是+32。也便是把_program_start加载入PC指针里。这段代码现已消除了指令当时方位对跳转方位的影响,能够随意的拷贝到恣意的当地去履行。这段代码放在0x200000当地,能够正常履行;放在0x100000当地也能够正常履行。

RTEMS的ARM9(CSB337)发动向量:

vector_block:

ldrpc,Reset_Handler

ldrpc,Undefined_Handler

ldrpc,SWI_Handler

ldrpc,Prefetch_Handler

ldrpc,Abort_Handler

nop

ldrpc,IRQ_Handler

ldrpc,FIQ_Handler

Reset_Handler:bbsp_reset

Undefined_Handler:bUndefined_Handler

SWI_Handler:bSWI_Handler

Prefetch_Handler:bPrefetch_Handler

Abort_Handler:bAbort_Handler

nop

IRQ_Handler:bIRQ_Handler

FIQ_Handler:bFIQ_Handler

Rtems是个杂乱的操作体系,在汇编代码里装置的仅仅一个简略的复位向量。其它向量都仅仅简略的死循环。操作体系运转起来今后,还要再次装置向量的。向量指向操作体系的杂乱的处理函数。但不论这些,向量存储的地址是没有改动的。Link脚本上能够看到向量被放在内部的SRAM的首地址上。(CSB337)

SECTIONS

{

.base:

{

_sram_base=.;

/*reserveroomforthevectorsandfunctionpointers*/

arm_exception_table=.;

.+=64;

连接器尽管把方位空出来了,但连接器仍然不知道将vector_block放到什么方位。怎么办?这儿的代码解说了全部。

/*

*InitializetheMMU.Afterwereturn,theMMUisenabled,

*andmemorymayberemapped.Ihopewedontremapthis

*memoryaway.

*/

ldrr0,=mem_map

blmmu_init

/*

*Initializetheexceptionvectors.Thisincludesthe

*exceptionsvectors(0x00000000-0x0000001c),andthe

*pointerstotheexceptionhandlers(0x00000020-0x0000003c).

*/

movr0,#0

adrr1,vector_block

ldmiar1!,{r2-r9}

stmiar0!,{r2-r9}

ldmiar1!,{r2-r9}

stmiar0!,{r2-r9}

Gnu的东西链并不针对某一个详细的渠道。所以处理方案从某种意义上说,更具有普遍意义。先调用mmu_init,这是干什么,实践上是将MMU初始化,将咱们界说的.base地址放到0x0方位去。然后紧接着下面的几行代码,是将上面的中止向量到0x0方位去。总共64个字节,完成4GB内的地址肯定跳转。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/chuanganqi/276405.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部