首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

cortex-m3 栈的8字节对齐(2)

cortex-m3 栈的8字节对齐(2)

五. CORTEX-M3 中断控制器的栈对齐调整功能(该功能在r2p0版本以后的内核中均默认开启,STKALIGN位默认为1)   Cortex M3 NVIC CCR寄存器(控制与配置寄存器)的STKALIGN位置1,那么在发生中断时,进入中断响应函数前,内核会首先检查当前正在使用的栈指针是否8字节对齐,如果是,则正常将xPSR,PC,LR,SP,R0-R3入栈,如果不是,则先把SP-4,调整为8字节对齐,然后将xPSR第九位置1,接着把xPSR,PC,LR,SP,R0-R3入栈,再然后才进入中断响应函数。这样可以保证程序在运行过程中,如果在栈没有发生4字节对齐的地方发生中断了,进入到中断响应函数的时候也是遵守AAPCS栈使用约定的。如果中断服务程序是做任务切换的,那么前面的情况就是将任务栈调整为对齐,然后进入异常服务程序后使用系统栈,那如果系统栈本来就是不对齐的呢?通过中断来做任务切换的情况下,中断控制器并不会对系统栈进行调整,怎么办?其实这也不用担心,以μC/OS-II为例,在cortex-m3上通常使用PendSV异常来做任务切换,即将OSCtxSw以及OSIntCtxSw都设为仅完成PendSV异常触发功能,然后在PendSV异常服务程序中进行任务切换。由于上电时刻系统处于特权级模式,只要我们保证从上电开始到第一次系统调用,使用的栈都是系统栈MSP就可以了,这样即使第一次要进入任务切换时MSP不对齐,中断向量控制器也会给调整为8字节对齐状态,虽然这个第一次任务切换后除了中断再也不会使用MSP,但只要我们同时保证所有汇编部分都不会破坏8字节对齐规约,那么从此以后MSP都会是8字节对齐的。
  六、关于ALIGN属性 与 PRESERVE8伪指令  在CORTEX M3芯片的启动代码中,这两个伪指令并非必不可少,可以不要这两个伪指令。但是有了这两个伪指令,可以在确保遵守AAPCS的道路上加一道保险,使得AAPCS栈使用约定的遵守在实际编程时变得稍微容易点。
  当在段定义头(即AREA伪指令的相关代码)当中使用ALIGN=?时,ALIGN属性的作用为设定该代码段或数据段的首址的对齐位置,例如ALIGN=3就表示,该段首址将被安排在2^3=8字节对齐处。需要注意的是,除了AREA的ALIGN属性,还有一个同名的ALIGN指令,ALIGN指令使用在段内部的,用来调整ALIGN指令下一条命令或数据的对齐位置。
  而PRESERVE8伪指令并不会对栈进行任何修改。PRESERVE8伪指令的使用有四种方法,分别如下,其中1、2的用法是等价的:
  1.        PRESERVE8
  2.        PRESERVE8 {TRUE}
  3.        PRESERVE8 {FALSE}   
  如果不写,那么由编译器来决定在编译过程中将汇编文件标识为PRES8属性还是~PRES8属性(也即加还是不加该伪指令),但经过实验,发现编译器在加不加这条伪指令上表现的并不完全可靠。。。所以最好明确的加上是 PRESERVE8 {TRUE}还是PRESERVE8 {FALSE}。那么这条伪指令起什么作用呢?
  如果你想要告诉汇编器说:“在我这个汇编文件中保证栈的8字节对齐,我这个文件对栈的任何时刻的任何操作都是8字节对齐的”,那么你就把PRESERVE8伪指令用在汇编文件中,用以向汇编器通知前面你的保证内容。汇编器就知道你这个汇编文件是8字节对齐靠谱选手,将该文件标识为PRES8属性,然后如果在你这个汇编中调用了标示了需要8字节对齐属性的文件中的函数,连接的时候就不会报错。但是假如你把这个汇编文件标示为PRESERVE8 {FALSE},然后你又在这个文件中调用了标示了需要8字节对齐属性的文件中的函数,连接时就会给出错误信息。
  那么什么是标示了需要8字节对齐属性的文件呢?如果你的某个汇编文件,某些操作一定要栈8字节对齐才行,那么你就需要使用REQUIRE8伪指令来通知汇编器将该文件标识为REQ8属性,然后这个文件就是所谓的“标示了需要8字节对齐属性的文件”。
  在文件较多,文件之间调用由繁多的情况下,通过PRESERVE8和REQUIRE8的配合,就能够在连接期间由编译器检查出我们写代码时不小心造成的破坏8字节对齐模块对需要8字节对齐模块的调用(经过实验发现,汇编之间是给出警告,汇编调用C则是给出错误,由于C文件中并不能直接用REQUIRE8,所以我猜编译器将C文件都通通标识为REQ8属性了,所以才会出错)。
  REQUIRE8的用法同PRESERVE8。
继承事业,薪火相传
返回列表