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

news2025/4/22 8:37:03

文章目录

  • 任务切换
  • 任务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.coloradmin.cn/o/2339976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科学养生指南:解锁健康生活新方式

在快节奏的现代生活中,健康养生已成为人们关注的焦点。科学合理的养生方式,能帮助我们增强体质、预防疾病,享受更优质的生活。​ 饮食是健康养生的基石。遵循 “均衡饮食” 原则,每日饮食需包含谷类、蔬菜水果、优质蛋白质和健康…

第十四届蓝桥杯 2023 C/C++组 有奖问答

目录 题目: 题目描述: 题目链接: 思路: 核心思路: 思路详解: 代码: 代码详解: 题目: 题目描述: 题目链接: 蓝桥云课 有奖问答 思路&…

transformer注意力机制

单头注意力机制 import torch import torch.nn.functional as Fdef scaled_dot_product_attention(Q, K, V):# Q: (batch_size, seq_len, d_k)# K: (batch_size, seq_len, d_k)# V: (batch_size, seq_len, d_v)batch_size: 一次输入的句子数。 seq_len: 每个句子的词数。 d_mo…

QT 5.15 程序打包

说明: windeployqt 是 Qt 提供的一个工具,用于自动收集并复制运行 Qt 应用程序所需的动态链接库(.dll 文件)及其他资源(如插件、QML 模块等)到可执行文件所在的目录。这样你就可以将应用程序和这些依赖项一…

【路由交换方向IE认证】BGP选路原则之AS-Path属性

文章目录 一、路由器BGP路由的处理过程控制平面和转发平面选路工具 二、BGP的选路顺序选路的前提选路顺序 三、AS-Path属性选路原则AS-Path属性特性AS-Path管进还是管出呢?使用AS-Path对进本AS的路由进行选路验证AS-Path不接收带本AS号的路由 四、BGP邻居建立配置 一…

Linux系统下docker 安装 redis

docker安装最新版的redis 一、docker拉取最新版redis镜像 拉取镜像若没有指定版本,代表拉取最新版本 二、查询redis镜像 三、挂载配置文件 在docker容器内修改redis配置文件不方便,所以挂载配置文件,这样可以在外边修改redis配置 3.1 创建…

深度学习框架PyTorch——从入门到精通(3.3)YouTube系列——自动求导基础

这部分是 PyTorch介绍——YouTube系列的内容,每一节都对应一个youtube视频。(可能跟之前的有一定的重复) 我们需要Autograd做什么?一个简单示例训练中的自动求导开启和关闭自动求导自动求导与原地操作 自动求导分析器高级主题&…

【基础算法】二分算法详解

🎯 前言:二分不是找某个数,而是找一个满足条件的位置/值 所以最关键的是:找到单调性,写好 check() 函数,剩下交给模板! 什么是二分算法 二分算法是一种在有序区间中查找答案的方法,时间复杂度:O(log n)。核心思想是: 每次把搜索区间分成两半,只保留可能存在答案的…

mysql——基础知识

关键字大小写不敏感 查看表结构中的 desc describe 描述 降序中的 desc descend 1. 数据库的操作 1. 创建数据库 create database 数据库名;为防止创建的数据库重复 CREATE DATABASE IF NOT EXISTS 数据库名;手动设置数据库采用的字符集 character set 字符集名;chars…

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比

OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比 目录 OOA-CNN-LSTM-Attention、CNN-LSTM-Attention、OOA-CNN-LSTM、CNN-LSTM四模型多变量时序预测一键对比预测效果基本介绍程序设计参考资料 预测效果 基本介绍 基于OOA-CN…

PCIE Spec ---Base Address Registers

7.5.1.2.1 Base Address Registers (Offset 10h - 24h) 在 boot 到操作系统之前,系统软件需要生产一个内存映射的 address map ,用于告诉系统有多少内存资源,以及相应功能需要的内存空间,所以在设备的 PCI 内存空间中就有了这个 …

Spring如何通过XML注册Bean

在上一篇当中我们完成了对三种资源文件的读写 上篇内容:Spring是如何实现资源文件的加载 Test public void testClassPathResource() throws IOException { DefaultResourceLoader defaultResourceLoader new DefaultResourceLoader(); Resource resource …

基于Java的不固定长度字符集在指定宽度和自适应模型下图片绘制生成实战

目录 前言 一、需求介绍 1、指定宽度生成 2、指定列自适应生成 二、Java生成实现 1、公共方法 2、指定宽度生成 3、指定列自适应生成 三、总结 前言 在当今数字化与信息化飞速发展的时代,图像的生成与处理技术正日益成为众多领域关注的焦点。从创意设计到数…

【版本控制】idea中使用git

大家好,我是jstart千语。接下来继续对git的内容进行讲解。也是在开发中最常使用,最重要的部分,在idea中操作git。目录在右侧哦。 如果需要git命令的详解: 【版本控制】git命令使用大全-CSDN博客 一、配置git 要先关闭项目&#xf…

Linux——入门常用基础指令

文章目录 Linux入门常用基础指令使用工具介绍基础指令clear指令pwd指令ls指令cd指令Linux系统下的文件路径及文件存储结构文件结构家目录绝对路径和相对路径tree工具 stat指令which指令alias指令touch指令mkdir指令cat指令rm指令man指令cp指令通配符 * Linux入门常用基础指令 …

【技术追踪】Differential Transformer(ICLR-2025)

Differential Transformer:大语言模型新架构, 提出了 differential attention mechanism,Transformer 又多了一个小 trick~ 论文:Differential Transformer 代码:https://github.com/microsoft/unilm/tree/master/Diff…

【Linux网络】应用层自定义协议与序列化

🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12891150.html 目录 应用层 再谈 "协议" 网络版计算器 序列化 和 反序列化 重新理解…

Vue接口平台学习十——接口用例页面2

效果图及简单说明 左边选择用例,右侧就显示该用例的详细信息。 使用el-collapse折叠组件,将请求到的用例详情数据展示到页面中。 所有数据内容,绑定到caseData中 // 页面绑定的用例编辑数据 const caseData reactive({title: "",…

目标检测中的损失函数(二) | BIoU RIoU α-IoU

BIoU来自发表在2018年CVPR上的文章:《Improving Object Localization With Fitness NMS and Bounded IoU Loss》 论文针对现有目标检测方法只关注“足够好”的定位,而非“最优”的框,提出了一种考虑定位质量的NMS策略和BIoU loss。 这里不赘…

Linux 入门十一:Linux 网络编程

一、概述 1. 网络编程基础 网络编程是通过网络应用编程接口(API)编写程序,实现不同主机上进程间的信息交互。它解决的核心问题是:如何让不同主机上的程序进行通信。 2. 网络模型:从 OSI 到 TCP/IP OSI 七层模型&…