文章目录

  • 1 任务切换的基础:模拟任务切换时寄存器的保存与恢复

1 任务切换的基础:模拟任务切换时寄存器的保存与恢复

需求说明:使用PendSVC触发异常,在异常处理函数中,保存R4-R11寄存器到缓冲区,再恢复R4-R11寄存器,以模拟任务切换时的寄存器保存与恢复。

文件组织结构如下图:

main.c:

#define NVIC_INT_CTRL       0xE000ED04      // 中断控制及状态寄存器
#define NVIC_PENDSVSET      0x10000000      // 触发软件中断的值
#define NVIC_SYSPRI2        0xE000ED22      // 系统优先级寄存器
#define NVIC_PENDSV_PRI     0x000000FF      // 配置优先级#define MEM32(addr)         *(volatile unsigned long *)(addr)
#define MEM8(addr)          *(volatile unsigned char *)(addr)void triggerPendSVC (void)
{MEM8(NVIC_SYSPRI2) = NVIC_PENDSV_PRI;   // 向NVIC_SYSPRI2写NVIC_PENDSV_PRI,设置其为最低优先级MEM32(NVIC_INT_CTRL) = NVIC_PENDSVSET;    // 向NVIC_INT_CTRL写NVIC_PENDSVSET,用于PendSV
}typedef struct _BlockType_t
{unsigned long * stackPtr;
}BlockType_t;BlockType_t * blockPtr;void delay (int count)
{while (--count > 0);
}int flag;unsigned long stackBuffer[1024];
BlockType_t block;int main ()
{block.stackPtr = &stackBuffer[1024];blockPtr = █for (;;) {flag = 0;delay(100);flag = 1;delay(100);triggerPendSVC();}return 0;
}

switch.c:

__asm void PendSV_Handler ()
{// blockPtr在main.c中定义,定义为:BlockType_t * blockPtr。// 在汇编代码中,如要引用C中的符号,必  须先用IMPORT导入。有些类似于在C语言中的externIMPORT  blockPtr// 加载寄存器存储地址// LDR R0, =blockPtr ; 将blockPtr变量的地址加载到R0中// LDR R0, [R0] ; 再从该地址加载32位数据值,也就是将blockPtr的值加载到R0中。在main()中,我们已经设置:// BlockType_t block;// block.stackPtr = &stackBuffer[1024];// blockPtr = █// 所以,此时R0的值将会是block结构的起始地址。// LDR R0, [R0]  ; 再次加载32位数据,显示此次就是从block结构开始处加载32位值,根据block结构的定义:// typedef struct _BlockType_t {//    unsigned long * stackPtr;// }BlockType_t// 显然,此时R0的值就是stackPtr的值,也就是&stackBuffer[1024];LDR     R0, =blockPtrLDR     R0, [R0]LDR     R0, [R0]// 保存寄存器// 此时R0的值就是&stackBuffer[1024]。然后,将R4, R5, .. R11写入到stackBuff缓冲区中,顺序不重要,你只需知道其与下面LDMIA的加载次序正好相反即可。写入前,以R0中地址为基准,每写入一个寄存器前,先对地址减去4,然后再写入寄存器值。完成所有写入之后,将最后的地址覆盖到R0寄存器中STMDB   R0!, {R4-R11}// 将最后的地址写入到blockPtr中// LDR R1, =blockPtr ; 将blockPtr变量的地址加载到R1中// LDR R1, [R1] ; 再从该地址加载32位数据值,也就是将blockPtr的值加载到R1中。在main()中,我们已经设置:// BlockType_t block;// block.stackPtr = &stackBuffer[1024];// blockPtr = █// 所以,此时R1的值将会是block结构的起始地址。// STR R0, [R1]  ; 将前面执行STM执行后,R0的值也就是最后写入的地址写入R1中地址指向的位置。// typedef struct _BlockType_t {//    unsigned long * stackPtr;// }BlockType_t// 显然,此时R1的值就是block结构的地址,也就是向将R0的值写入到stackPtr。最终实现将最后的写stackBuff的 地址保存到block.stackPtrLDR     R1, =blockPtrLDR     R1, [R1]STR     R0, [R1]// 修改部分寄存器,用于测试// 测试代码。用于检查前面的保存(STMDB),以及后面的恢复(LDMIA)是否正确。如果保存和恢复正确,那么执行LDMIA后,R4,R5的值应为恢复之前的值。// 如果需要,可在此添加对其它寄存器的修改测试代码。ADD R4, R4, #1ADD R5, R5, #1// 恢复寄存器// 与STMDB正好相反,从R0地址对应的存储单元中读取多个32位的单元,恢复到R4~R11寄存器。// 注意到,此时,R0为之前向存储单元写R4~R11的最后单元的地址,所以此时可以正确恢复。// 具体执行时,首先从当前地址对应的单元处加载数据恢复到寄存器,再将地址+4,如此反复,直到所有寄存器恢复完毕。LDMIA   R0!, {R4-R11}// 异常返回// 异常返回指令,不同于从函数调用。此时LR的值不是函数的返回地址,而是一串特定的值,如0xFFFF_FFFxBX      LR
}

参考资料:

  1. 【李述铜】从0到1自己动手写嵌入式操作系统

任务切换的基础:模拟任务切换时寄存器的保存与恢复相关推荐

  1. [ATF]-TEE/REE系统切换时ATF的寄存器的保存和恢复

    ATF点滴 1.设置运行时栈SP 2.寄存器的保存和恢复的实现 3.寄存器的保存和恢复的使用场景 ★★★ 友情链接 : 个人博客导读首页-点击此处 ★★★ 1.设置运行时栈SP bl31_entryp ...

  2. [architecture]-ARMV7架构下SecureMonitor双系统切换时保存和恢复哪些寄存

    ★★★ 个人博客导读首页-点击此处 ★★★ . 文章目录 1.armv7的通用寄存器简介 2.寄存器的保存和恢复 3.参考代码: 1.armv7的通用寄存器简介 ARMV7处理器有40个32位寄存器, ...

  3. [architecture]-ARMV7架构下Linux Kernel的Userspace进程切换时保存和恢复哪些寄存器

    ★★★ 个人博客导读首页-点击此处 ★★★ . 文章目录 1.armv7的通用寄存器简介 2.寄存器的保存和恢复 3.Linux Kernel参考代码 1.armv7的通用寄存器简介 ARMV7处理器 ...

  4. (57)模拟线程切换

    一.回顾 在之前的课程中,我们学习了 EPROCESS, ETHREAD, KPCR 等重要的内核结构体,学习了存储等待线程的等待链表和调度线程的调度链表,这些知识都是为了后面学习线程切换打的基础. ...

  5. (58)模拟线程切换——添加挂起、恢复线程功能

    一.回顾 我们在上一篇博客分析了模拟线程切换的源码. <模拟线程切换> 我们着重分析了 Scheduling 和 SwitchContext 这两个函数,对线程切换的过程有了新的认识: 线 ...

  6. Windows进程与线程学习笔记(五)—— 模拟线程切换

    Windows进程与线程学习笔记(五)-- 模拟线程切换 ThreadSwitch代码分析 ThreadSwitch.cpp ThreadCore.h ThreadCore.cpp 总结 Thread ...

  7. Ubuntu:成功解决ubuntu使用su切换root出现Authentication failure用户时认证失败

    Ubuntu:成功解决ubuntu使用su切换root出现Authentication failure用户时认证失败 导读 最讨厌网上回答的啰嗦和不清晰!本人最讨厌啰嗦,直接上来,图文表达,简单明了, ...

  8. 进程线程003 模拟线程切换

    文章目录 示例代码 关键结构体 调度链表 初始化线程堆栈 线程切换 被动切换 主动切换 线程调度 总结 之前我们已经了解过线程的等待链表和调度链表,为了更好的学习Windows的线程切换,我们要先读一 ...

  9. Compose 横竖屏切换时状态如何保存?rememberSaveable 实现原理分析

    前言 在这篇文章中提到了 Navigation 的状态保存实际是由 rememberSaveable 实现的,有同学反馈希望单独介绍一下 rememberSaveable 的功能及实现原理.我们都知道 ...

最新文章

  1. python26 调用mysql 5.1
  2. C#之获取mp3文件信息
  3. Mina airQQ聊天 client篇(三)
  4. 【视频】云信CTO阙杭宁:IM云开发经验分享
  5. 微信小程序 html modal,微信小程序参考微信设计规范做的modal模态框
  6. preg_match进行正则表达式匹配
  7. SAP License:SAP项目文档的考核标准
  8. Android中Activity的四大启动模式实验简述
  9. L3G4200D + ADXL345 卡尔曼滤波
  10. c# 超时时间已到.在操作完成之前超时时间已过或服务器未响应,超时过期了。在操作完成或服务器没有响应之前经过的超时时间。声明已被终止...
  11. AEC产业未来发展的三大趋势,数字化只是其中之一
  12. php滚动播报,卫星云图滚动播放(实时更新)
  13. 计算机主机显卡装在哪,电脑显卡在主板上的哪个位置?怎么查看显卡的信息和更新驱动程序?...
  14. 《赖氏经典英语语法》第四集
  15. python图片保存pdf_python将JPG图片转换为PDF
  16. 【计算机组成原理】 数据的表示和运算
  17. 研究生必备的文献翻译软件知云文献翻译替代品--Mac monterey
  18. AUTOSAR CanNm Nm Configuration
  19. 极简浏览器主页网址导航自定义网址壁纸云端同步简洁清爽
  20. mysql 、pg 查询日期处理

热门文章

  1. 远程恢复服务器,Hyper-V主机启用“远程桌面”功能
  2. 基于单片机的c语言倒计时程序,30秒倒计时c语言51单片机实现.doc
  3. 【控制】《自动控制原理》胡寿松老师-第5章-线性系统的频域分析法
  4. 【arduino】继续蜂鸣器音乐播放,arduinoIDE里调用音乐播放库
  5. CYPRESS USB芯片win10驱动
  6. 第二十四章:页面导航(五)
  7. redis集群部署一直卡在Waiting for the cluster to join ......
  8. HTML5 元素选择流程图
  9. ASP.NET Core 中文文档 第四章 MVC(4.2)控制器操作的路由
  10. 升级OS10.11系统后 Xcode6.4的变化少了个按钮 could not launch “Xcode” Xcode 插件安装...