UCOS学习笔记——堆栈

举报
万里羊 发表于 2021/08/24 23:47:04 2021/08/24
【摘要】 堆栈 Cortex-M3堆栈操作 Cortex-M3使用的是“向下生长的满栈”模型。堆栈指针SP指向最后一个被压入堆栈的32位数值。在下一-次压栈时,SP先自减4,再存入新的数值,如图2.3.1所示。...

堆栈

Cortex-M3堆栈操作

Cortex-M3使用的是“向下生长的满栈”模型。堆栈指针SP指向最后一个被压入堆栈的32位数值。在下一-次压栈时,SP先自减4,再存入新的数值,如图2.3.1所示。在这里插入图片描述
POP操作刚好相反:先从SP指针处读出,上一次被压入的值,再把SP指针自增4。如图2.3.2所示。
在这里插入图片描述
在进入ISR时,CM3会自动把一些寄存器压栈,这里使用的是进入ISR之前使用的SP指针(MSP或者是PSP)。离开ISR后,只要ISR没有更改过CONTROL[1],就依然使用先前的SP指针来执行出栈操作。

双堆栈机制

我们已经知道了CM3的堆栈是分为两个:主堆栈和进程堆栈, CONTROL[1]决定如何选择。当CONTROL[1]=0时,只使用MSP, 此时用户程序和异常handler 共享同一个堆栈。这也是复位后的缺省使用方式,如图2.3.3所示。
在这里插入图片描述
当CONTROL[1]=1时,线程模式将不再使用PSP,而改用MSP(handler模式永远使用MSP)。此时,进入异常时的自动压栈使用的是进程堆栈,进入异常handler后才自动改为MSP,退出异常时切换同psp,并日从讲程堆栈十弹出数据,如图2.3.4所示:
在这里插入图片描述
在特权级下,可以指定具体的堆栈指针,而不受当前使用堆栈的限制,示例代码如下:

MRS  RO,MSP ; 读取主堆栈指针到RO
MSR MSP,RO ; 写入RO的值到主堆栈中
MRS RO,PSP ;读取进程堆栈指针到RO
MSR RO ;写入RO的值到进程堆栈中

  

通过读取PSP的值,OS就能够获取用户应用程序使用的堆栈,进一一步地就知道了在发生异常时,被压入寄存器的内容,而且还可以把其它寄存器进一步压栈的书写形式)。OS还可以修改PSP,用于实现多任务中的任务上下文切换。

Stack frames

在进入异常服务程序的时候会将一些数据压入堆栈中,这些数据所占用的数据块被称为Stack frames,由于M3没有FPU所以其Stack frames总是8个字(一个字32bit)如图2.3.5所示。
在这里插入图片描述
在符合AAPCS的应用程序中,对于响应异常时的堆栈操作是要进行双字对齐的在M3处理器中如果堆栈指针SP未双字对齐的话,那么就会在堆栈中自动的增加一个填充位使其双字对齐。双字对齐是一一个可选项,欲使能此特性,需要把NVIC配置控制寄存器的STKALIGN置位,如下面汇编代码所演示:

LDR RO,=0xE0O0ED1 4; R0=NVIC CCR的基址
LDR R1,[R0]
ORR.W R1,R1, #0x200;设置STKALIGN位
STR R1,[R0];更新NVIC CCR

  

如果用C语言:

#define NVIC_ CCR ((volatile unsigned long *)(0xE000ED14))
*NVIC_ CCR= *NVIC_ CCR | 0x200; //设置 STKALIGN位

  

xPSP寄存器的bit9 被用来指示SP是否需要对齐,bit9 如果为1的话就需要双字对齐,如果为0的话就不需要双字对齐,未使用FPU时采用双字对齐的Stack frame如图2.3.6所示。
我们可以看到这里只是将xPSR、PC、LR、R12、R0-R3这8个寄存器自动入栈,其余的8个寄存器R4-R11就需要我们自己手动入栈了,入栈顺序不能乱了。
Alt
我们可以看出还有R4-R11这些寄存器没有做处理,那么我们就要手动对这些寄存器做入栈和出栈处理。

文章来源: wlybsy.blog.csdn.net,作者:万里羊,版权归原作者所有,如需转载,请联系作者。

原文链接:wlybsy.blog.csdn.net/article/details/103464192

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。