armV7基础概念

本文主要介绍armV7系列core(如CR5,CA7等)的一些基础知识。

一. 寄存器

armV7 core包括16个32位通用寄存器R0~R15,程序状态寄存器CPSR/SPSR。

1. R13为SP(栈指针)寄存器,存的是栈顶地址(递减栈);

2. R14为LR(连接)寄存器,存放的是bl跳转指令的返回地址,或是异常/中断发生时PC值减4(arm模式,指令长度为32位)或2(thumb模式,指令长度为16位);

3. R15为PC(程序计数)寄存器,存放的是下一条正在取值的指令的地址,由于armV7采用三级流水线:取指--译码--执行,因此指向当前执行指令后的第三条指令。一般对于arm模式来说,PC值为当前执行指令的地址+8

4. CPSR/SPSR为程序状态寄存器,其中CPSR为程序状态寄存器,包括当前处理器模式(arm/thumb),IRQ/FIQ使能,条件码等。SPSR用于在模式切换时保存CPSR,可以理解为前一模式CPSR的值。CPSR中,通常关注低8bit,其含义如下:

bit7/bit6用于控制IRQ/FIQ是否使能;bit5用于控制处理器处于arm模式还是thumb模式;bit[4:0]表示了cpu所处的模式,主要包括下列几种:

  • USER mode,处于USER mode时,CPSR[4:0]=0x10,该模式下可以访问R0~R15, CPSR寄存器。注意USER mode没有SPSR寄存器,因为它不是异常处理模式。USER mode是unprivilege mode,在USERmode下,无法访问全部系统资源,例如某些寄存器。
  • FIQ mode,处于FIQ mode时,CPSR[4:0]=0x11,该模式下可以访问R0~R17,R8_fiq~R14_fiq,R15,CPSR,SPSR_fiq寄存器。与USER mode相比,FIQ有单独的R8~R14,SPSR寄存器,用R8_fiq~R14_fiq,SPSR_fiq表示,其他模式同。当FIQ发生时,会打断当前正在执行的程序,被打断前的CPSR的值会被存入SPSR_fiq。当CPSR[5]!=1时,如果有FIQ中断到来,则会进入到该mode。也可以使用msr指令直接操作CPSR的值来切换mode,这个方式可以用在所有mode切换中,实际使用中,通过msr指令操作CPSR切换到不同mode后,设置对应mode的R13(SP)寄存器,从而可以实现不同mode使用不同的栈。
  • IRQ mode,处于IRQ mode时,CPSR[4:0]=0x12,该模式下可以访问R0~R12,R13_irq、R14_irq,R15,CPSR,SPSR_irq寄存器。与FIQ相比,IRQ mode只有单独的R13_irq、R14_irq寄存器,因此虽然FIQ/IRQ都是中断,但IRQ需要压栈保护更多的寄存器(R8~R12),因此速度上会比FIQ更慢。当CPSR[6]!=1时,如果有IRQ中断到来,则会进入到该mode。
  • SVC mode,处于SVC mode时,CPSR[4:0]=0x13,该模式可以访问R0~R12,R13_svc、R14_svc,R15,CPSR,SPSR_svc寄存器。可以使用swi #0指令进入SVC mode,另外,core reset/power on时,arm操作CPSR切换至SVC mode,这也是正常boot时的mode。
  • ABT mode,处于ABT mode时,CPSR[4:0]=0x17,该模式可以访问R0~R12,R13_abt、R14_abt,R15,CPSR,SPSR_abt寄存器。当cpu遇到prefetch abort或data abort时,会进入该模式。
  • UND mode,处于UND mode时,CPSR[4:0]=0x1B,该模式可以访问R0~R12,R13_und、R14_und,R15,CPSR,SPSR_und寄存器。当cpu遇到未定义指令时会进入该模式。
  • SYS mode,处于SYS mode时,CPSR[4:0]=0x1F,该模式可以访问R0~R15,CPSR寄存器,并且由于不是异常处理mode,也没有SPSR寄存器。SYS mode可以访问的寄存器与USER mode相同,区别是SYS mode是privilege mode,可以访问系统资源。
  • 其余还有MON mode和HYP mode,不常用,这里不展开。

5. R0~R3可以用来存放函数的前4个参数,如果参数多于4个,则需要通过栈来传递参数。因此,这四个寄存器是caller saved的,而其他的则是callee save的。举个例子,假如存在下列调用逻辑

void funA(void) {
    int a=1, b=2, c=3, d=4;
    funB(a, b, c, d);
}

void funB(int a, int b, int c, int d) {
    return;
}

其中,funB有四个参数,那么在调用时,会首先将{a, b, c, d}赋给{r0-r3},写成汇编:

mov r0, #1

mov r1, #2

mov r2, #3

mov r3, #4

而r0-r3的原始值会在调用funB之前由funA(caller)压栈保护;而其他的寄存器,如果被用到了,则由funB(callee)压栈保护。随后调用funB,写成汇编:

而r0-r3的原始值会在调用funB之前由funA(caller)压栈保护;对于其他的寄存器,如果被用到了,则由funB(callee)压栈保护。随后调用funB,写成汇编:

bl funB

这条指令后,会将该条指令的下一句指令的地址存入R14(LR)寄存器,在funB函数中,return会被编成汇编:

bx r14

随后会返回R14(LR)寄存器中存的地址继续执行,需要注意的是,当使用bx Rn指令跳转时,如Rn寄存器中存的地址最低位为1,则跳转后进入thumb模式,否则为arm模式。

二. 中断向量表

与CortexM系列(如STM32系列)相比,armV7系列的core,其中断向量表有两个主要的不同:

1. 向量表中存的不再是地址,而是一条指令,通常是一句跳转指令,主要有两种形式:

a. b <label>

其中label为真正的回调的地址。该方式最简单,但是由于b指令的寻址范围为以pc指针为基准的前后32MB空间,适用于跳转距离较近的情况。

b. ldr pc, [pc, #offset]

这种方式可以访问到完整的32位指示的内存空间,但是相较于前一种方式,可能需要额外的周期数。

2. 向量表中不再包含所有的中断,只包括下列几种:

其中IRQ/FIQ对应于一般的的中断,Software Interrupt是通过swi指令产生的软件中断,Reset是上电/复位时产生的中断,Undefined/Prefetch Abort/Data Abort均是异常产生的中断,会在下文介绍。

默认情况下,中断向量表位于0地址处。当然,也可以通过调整SCTLR寄存器的BIT_13来修改:

  • SCTLR[13]==1,向量表位于0xFFFF0000处,这也是linux采用的方式;
  • SCTLR[13]==0,向量表位于0x00000000处,这是默认情况。

三. 中断和异常

当CPU收到中断信号或在执行过程中遇到异常时,根据遇到的中断/异常的不同,CPU会中断当前正在执行的程序流,跳转到中断向量表的对应位置,执行该位置内存的指令。

对于异常,相对复杂一些。前文提到过,armV7包括三级流水线:取指—译码—执行,即单个时钟周期内会同时执行这三种操作,假如代码在内存中的分布如下(A,A+4等代表地址,instruction 1, instruction2等代表指令):

A:      instruction 1

A+4:    instruction 2

A+8:    instruction 3

A+12:   instruction 4

在单个时钟周期内,cpu可以同时执行instruction 1@A,译码instruction 2@A+4,取指instruction 3@A+8。由于PC寄存器总是指向取指指令的地址,因此pc值是正在执行指令的地址+8。在不同阶段出现问题,CPU会抛出不同的类型的异常,主要包括:

  • Prefetch Abort

在流水线的取指阶段,如果指令所在地址不可访问,则该指令被标记为无效,流水线上之前的指令继续执行。当cpu执行到该条无效指令时,cpu会抛出prefetch abort异常,此时LR寄存器中存的是异常指令地址+4;

  • Undefined Abort

在流水线的译码阶段,如果指令无法解码,cpu执行到该条指令时,会抛出undefined abort异常,此时LR寄存器中存的是异常指令地址+4;

  • Data Abort

在流水线的译码阶段,如果访问非法地址,该条指令执行完毕后则会抛出data abort异常,此时PC指针已经更新,LR寄存器中存的是异常指令地址+8;

对于普通的中断来说,如前面所述,和CortexM系列相比,由于中断向量表中只有IRQ/FIQ两项用于普通的中断响应,因此armV7系列的Core通常会外接一个ICU(Interrupt Control Unit)。响应中断时,通过外接的ICU判断中断号,对于CPU而言,所有的中断信号或在一起,统一通过IRQ/FIQ响应。此外,FIQ/IRQ中断是异步产生的,CPU无法知道何时会来中断。如CPU执行指令时中断到来,cpu不会立刻响应,而是会在当前周期完成后响应。例如,当cpu在执行instruction 1@A时产生中断,此时PC=A+8,cpu不会立刻响应中断。当instruction 1执行完毕后,PC更新为A+12,cpu响应中断,LR_irq/LR_fiq被赋为A+8。即指令instruction 2@A+8并未执行,因此当从中断返回时,需要回到LR_irq/LR_fiq-4继续执行。

然后是软件中断。过指令swi #imm主动触发,用于切换至SVC mode。该中断产生于指令的执行期间,LR_svc寄存器被更新为swi #imm指令地址+4(其中#imm为立即数,如swi #5)。#imm被存在32位swi #imm指令的低24位,如对于swi #5,32位指令的低24位即为5(swi #5的对应二进制代码是0xEF000005)。在swi的中断回调中可以通过读该值进行不同的处理。与IRQ/FIQ中断不同,软件中断从中断中返回时无需-4,只需要回到LR_svc继续执行。

最后一点,与CortexM不同,中断/异常产生时,不再有硬件自动压栈保存的寄存器,除去不同模式独有的寄存器以外,原则上其他寄存器都需要压栈保存(R13、R15除外)。如果在回调中进行了其他的调用,那么R14(LR)也需要压栈保存。以最基础的IRQ为例,汇编代码可以简化为:

IRQ_Handler:
    push {r0-r12, lr}
    bl irq_handler
    pop {r0-r12, lr}
    sub lr, #4
    bx lr

这样,一个完整的IRQ响应流程可以描述为:

a. 外部产生中断

b. core响应中断,硬件通过写CPSR的bit5禁掉IRQ,因此默认情况下不存在IRQ中断抢占,但FIQ仍然可以抢占IRQ。cpu跳转至0x18执行,0x18处的指令可以是

b IRQ_Handler

ldr pc, =IRQ_Handler

c. cpu跳转至IRQ_Handler执行

d. 返回被打断时执行的程序流

armV7在芯片中的使用非常广泛(CR5/CA7等)。在实际工程中,往往在异常函数的回调中保存各个模式下的寄存器,这样当CPU出现异常时,首先根据保存下来的CPSR判断遇到了那个种类的异常,再根据上面所述,通过LR寄存器判断异常发生的指令的位置,从而做进一步的分析。例如发现CPU发生了undefined abort,通过LR_abt定位到问题的指令,将指令的上下文的内容与正常情况下做对比,如果不一致,那么有可能是其他的线程/core踩了代码段。值得一提的是,armV7中存在异常中又触发异常的情况,比如在undefined abort中,如果恰好对应的回调的代码段也被踩了,那么就有可能出现undefined abort中又发生undefined abort,这点与CortexM系列不同,后者出现这种问题时会上访到HardFault异常。

四. boot流程

结合上面所述,armV7的基本boot流程可以表示为:

  • 上电后,cpu执行reset handler,CPSR被设置为SVC mode,FIQ/IRQ disable,arm模式;
  • 通过msr指令修改CPSR至不同的mode,设置不同mode下R13(SP)寄存器的初始值,即设置不同模式下的栈;
  • 做外设的初始化,例如ICU(中断管理模块),时钟使能,变频等操作;
  • 通过msr指令修改CPSR至USER mode(非必须,也可以默认运行在SVC mode),跳转至main函数,进入C语言的世界。

#嵌入式工程师##校招##嵌入式#
嵌入式学习 文章被收录于专栏

21届985微电子硕士,校招SSP进入紫光展锐任嵌入式工程师,8个月后跳槽至ASR工作至今。本专栏记录上学/工作时学到的一些知识,debug的一些工具使用等,希望有所帮助。

全部评论

相关推荐

许愿ssp的咸鱼很不想泡池子:import python as pyhton
点赞 评论 收藏
分享
hanliu:1. 排版与格式问题字体与对齐问题:标题和内容的字体大小差异不够明显,无法迅速吸引目光。某些文字看起来有些拥挤(比如校园经历中的“班委成员”部分)。2. 内容逻辑性模块顺序问题:实习经历放在较靠后的位置,实际上这部分内容对应聘来说更重要,建议提前突出。细节表述不够突出:比如教育背景部分的专业课程仅仅列出名字,没有说明自己在这些课程中表现如何或者掌握了什么技能,缺乏量化描述。多余内容:例如“班委成员”和“宣传委员”这类校园经历,叙述过于普通,缺乏和岗位相关的实质性贡献。,建议简写。3. 措辞专业性表达不够精准:例如“协助班长与团支书更好地为同学服务”显得较为笼统,没有实际成果的体现。用词重复:如“学习了焊接”“学习了光检”等重复词语较多,缺乏丰富的动词来展示个人能力(如“负责”“优化”“改进”等)。技能展示不足:虽然列出了UG和CAD证书,但没有明确提到这些技能如何在实际工作中发挥作用。4. 技能匹配度技能深度不足:虽然列出了掌握的软件和技术,但没有描述技能水平(如“熟练掌握”“精通”),也没有具体案例支持这些技能。缺乏岗位导向性:比如针对机械设计与制造方向,实习经历提到了“E6尾灯项目”,但没有详细说明自己在其中的技术贡献,可能会显得经验描述泛泛而谈。5. 自我评价问题表达空泛:如“具有良好的沟通协调能力”“责任心强”之类的描述太常见,没有让人眼前一亮的特点。缺乏成果支持:自我评价中的能力没有用具体项目、经历或成就来验证,可信度较弱。 兄弟加油
点赞 评论 收藏
分享
评论
点赞
3
分享

创作者周榜

更多
牛客网
牛客企业服务