当前位置: 首页 > backend >正文

uCOS3实时操作系统(任务切换和任务API函数)

文章目录

  • 任务切换
  • 任务API函数

任务切换

  • µC/OS-III 将 PendSV 的中断优先级配置为最低的中断优先级,这么一来, PendSV 异常的中断服务函数就会在其他所有中断处理完成后才被执行。µC/OS-III 就是将任务切换的过程放到 PendSV 异常的中断服务函数中处理的。
  • 要挂起 PendSV 异常(触发 PendSV 异常)也非常简单, 只需将 ICSR 寄存器(中断控制状态寄存器)中断的 PENDSVSET 为置 1,即可挂起 PendSV 异常, 再挂起 PendSV 异常后, PendSV的中断服务函数并不会立马被执行,但也不会被忽略,而是会等 CPU 处理完所有中断优先级不小于 PendSV 异常中断优先级的中断后,在再处理 PendSV 异常的中断处理函数。
  • 发生任务切换的几种情况如下:在这里插入图片描述
    在这里插入图片描述
  • 在 µC/OS-III 中有两个用于触发任务切换的函数,分别为函数 OSSched() 和函数 OSIntExit() ,这两个函数的不同在于,函数 OSSched() 是在任务中使用的,而函数 OSIntExit() 是用于中断中的。函数 OSSched() 和函数 OSIntExit() 的分析,知道了函数 OSSched() 和函数 OSIntExit() 分别调用了函数 OS_TASK_SW() 和函数 OSIntCtxSw() 挂起 PendSV 异常,以触发任务切换。
    NVIC_INT_CTRL EQU 0xE000ED04 ; 中断控制状态寄存器的地址
    NVIC_PENDSVSET EQU 0x10000000 ; PENDSVSET 位掩码
    OSCtxSw
    OSIntCtxSw
    ; 将 ICSR 寄存器中的 PENDSVSET 位置 1
    ; 挂起 PendSV 异常
    LDR R0, =NVIC_INT_CTRL
    LDR R1, =NVIC_PENDSVSET
    STR R1, [R0]
    BX LR
    
    以上代码即为函数 OSCtxSw() 与函数 OSIntCtxSw() 就用于挂起 PendSV 异常的。
  • 在函数 OSSched()和函数 OSIntExit()中会挂起 PendSV 异常,那么 PendSV 异常就能够在所有中断的中断服务函数处理完成后,执行任务切换的操作。
    µC/OS-III 提供了 PendSV 异常的中断服务函数,以完成任务切换的操作,该函数为定义在文件 os_cpu_a.asm 中的标号 OS_CPU_PendSVHandler,具体的代码如下所示:
    OS_CPU_PendSVHandler
    ; 屏蔽受 uC/OS-III 管理的中断
    ; 此处加上开关中断的操作,是为了解决 Cortex-M7,写入 BASEPRI 后不能即时生效的 Bug
    CPSID I
    MOV32 R2, OS_KA_BASEPRI_Boundary
    LDR R1, [R2]
    MSR BASEPRI, R1
    DSB
    ISB
    CPSIE I
    ; 获取此时的 PSP,此时 PSP 为当前任务的任务的栈顶指针,R0 = PSP
    MRS R0, PSP
    ; 判断是否使能 FPU; 如果使能了 FPU; 还需要判断 R14 的 bit4 是否为 1; 若是,则需要将浮点寄存器中的数据保存到任务栈中
    IF {FPU} != "SoftVFP"
    TST R14, #0x10
    IT EQ
    VSTMDBEQ R0!, {S16-S31}
    ENDIF
    ; 将部分 CPU 寄存器的值模拟入栈到当前任务栈中; 另外,部分的 CPU 寄存器的值会在进入中断之前,自动入栈到任务栈中,; 其中就包含了进入中断前,任务执行到的位置(PC 值)
    STMFD R0!, {R4-R11, R14}
    ; 更新当前任务的任务栈顶指针
    ; OSTCBCurPtr->StkPtr = R0
    MOV32 R5, OSTCBCurPtr
    LDR R1, [R5]
    STR R0, [R1]
    ; 调用任务切换钩子函数,; 在调用之前保存 LR 寄存器的值
    ; R4 = LR
    ; OSTaskSwHook()
    MOV R4, LR
    BL OSTaskSwHook
    ; 设置 OSPrioCur 为最高就绪态任务优先级; OSPrioCur = OSPrioHighRdy
    MOV32 R0, OSPrioCur
    MOV32 R1, OSPrioHighRdy
    LDRB R2, [R1]
    STRB R2, [R0]
    ; 设置 OSTCBCurPtr 为最高就绪态任务; OSTCBCurPtr = OSTCBHighRdyPtr
    MOV32 R1, OSTCBHighRdyPtr
    LDR R2, [R1]
    STR R2, [R5]
    ; 参考《The Definitive Guide to ARM Cortex-M3 and ARM Cortex-M4 Processors》第8.1.4 小节的 EXC_RETURN 章节; LR |= 0x2 ; 确保返回任务后使用 PSP
    ORR LR, R4, #0x04
    ; 获取任务切换后任务的栈顶
    ; R0 = OSTCBHighRdyPtr->StkPtr
    LDR R0, [R2]
    ; 从任务栈中模拟出栈 CPU 寄存器的值到 CPU 寄存器中; 另外,部分的 CPU 寄存器的值会在退出中断之后,自动从任务栈中出栈到 CPU 寄存器中; 其中就包含了任务上次被切换时,执行到的位置(PC 值)
    LDMFD R0!, {R4-R11, R14}
    ; 判断是否使能 FPU; 如果使能了 FPU; 还需要判断 R14 的 bit4 是否为 1; 若是,则需要从任务栈中恢复初浮点寄存器中的数据
    IF {FPU} != "SoftVFP"
    TST R14, #0x10
    IT EQ
    VLDMIAEQ R0!, {S16-S31}
    ENDIF
    ; 更新 PSP 指针为此时任务切换后任务的任务栈顶; 这个 PSP 为任务栈,在退出中断后,会自动从这个栈中出栈 CPU 寄存器的值,其中就包含了任务在上次被切换时,执行到的位置(PC 值)
    ; 那么在退出中断后,任务就可以从上次被切换时执行到的位置继续执行 PSP = R0
    MSR PSP, R0
    ; 取消中断屏蔽,此处加上开关中断的操作,是为了解决 Cortex-M7,写入 BASEPRI 后不能即时生效的 Bug
    MOV32 R2, #0
    CPSID I
    MSR BASEPRI, R2
    DSB
    ISB
    CPSIE I
    ; 退出中断,此时就会根据 PC 指针的值跳转到任务切换后的任务中去执行
    BX LR
    
  • 需要注意的是,在上面这个代码中,一直都是通过PSP堆栈指针进行操作的,但是由于其是在中断中发生的,大部分寄存器在中断发生后会自动出入栈。

任务API函数

  • 任务的API函数整体如下所示:具体细节不再分析,把前三个博客写的底层裸机搞清楚后面的API函数都是水到渠成的事情。
    在这里插入图片描述
http://www.xdnf.cn/news/1006.html

相关文章:

  • MD5和sha1绕过方式总结
  • 第六章.java集合与泛型
  • 街景主观感知全流程(自建数据集+两两对比程序+Trueskill计算评分代码+训练模型+大规模预测)17
  • 冒泡排序详解
  • 使用若依二次开发商城系统-1
  • vue项目通过GetCapabilities获取wmts服务元数据信息并在openlayers进行叠加显示
  • 配置管理CM
  • 衡石chatbi如何通过 iframe 集成
  • 制作一款打飞机游戏14:资源优化
  • Nginx下搭建rtmp流媒体服务 并使用HLS或者OBS测试
  • 性能比拼: Nginx vs Caddy
  • NHANES指标推荐:PhenoAge
  • Ldap高效数据同步- Delta-Syncrepl复制模式配置实战手册(上)
  • 极验4滑块笔记:整理思路--填坑各种问题
  • 傲来云分享,负载均衡:提升网站性能与稳定性
  • 无人机飞控运行在stm32上的RTOS实时操作系统上,而不是linux这种非实时操作系统的必要性
  • 【前端】【面试】【业务场景】前端如何获取并生成设备唯一标识
  • 报错 | 配置 postcss 出现 报错:A `require()` style import is forbidden.
  • C++中的算术转换、其他隐式类型转换和显示转换详解
  • 开发指南:构建结合数字孪生、大语言模型与知识图谱的智能设备日志分析及生产异常预警系统
  • ByteTrack自定义数据集训练指南
  • 如何将SpringBoot前后端项目制作成windows运行的exe文件
  • 【python实用小脚本系列】用Python让鼠标“动起来”:光标自动移动、自动点击、自动图象识别的小技巧
  • 【教程】Digispark实现串口通信
  • 计算机是如何工作的
  • 使用Python可视化偶极子的电场
  • 2025年一站式AI创作平台主要功能介绍及使用教程
  • rac防火墙未禁用服务器重启导致二节点启动异常
  • Unity 场景管理核心教程:从 LoadScene 到 Loading Screen 实战 (Day 35)
  • 简单了解一下Unity Shader中的Swizzle操作