UCOSIII(1)——SVC与PenSV实现任务切换

2023-05-16

本文基于STM32F407ZGT6
——————————————

SVC异常:

SVC(系统服务调用,亦简称系统调用)用于产生系统函数的调用请求。
SVC 异常是必须立即得到响应的应用程序执行 SVC 时都是希望所需的请求立即得到响应。
在这里插入图片描述
在 UCOS 中并未使用 SVC 这个功能,了解一下即可。
在 UCOS 中并未使用 SVC 这个功能,了解一下即可。
在 UCOS 中并未使用 SVC 这个功能,了解一下即可。

PendSv异常:

  • 由于SVC异常是必须立即得到响应的(若因优先级不比当前正处理的高,或是其它原因使之无法立即响应,将上访成硬 fault),应用程序执行SVC 时都是希望所需的请求立即得到响应。
  • PendSV 则不同,它是可以像普通的中断一样被悬起的(不像 SVC 那样会上访)。OS
    可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动作。

1、悬 起 PendSV 的方法是:手工往 NVIC 的 PendSV 悬起寄存器中写 1。悬起后,如果优先级不够高,则将缓期等待执行。
2、PendSV 的典型使用场合是在上下文切换时(在不同任务之间切换)。异常会自动延迟上下文切换的请求,直到其它的 ISR 都完成了处理后才放行。为实现这个机制,需要把 PendSV 编程为最低优先级的异常。如果 OS 检测到某 IRQ 正在活动并且被 SysTick 抢占,它将悬起一个 PendSV异常,以便缓期执行上下文切换。
在这里插入图片描述

可以看到uCOS操作系统里(其实实时操作系统都一样)各类异常/中断的优先级关系:
SYSTICK异常>中断>PendSv异常
PendSV 异常会自动延迟上下文切换的请求,直到其它的 ISR 都完成了处理后才放行。这样保证了中断的快速响应性又保证了操作系统的正常轮转。

一、将PendSV 异常设置为最低优先级(这两段代码在os_cpu_a.asm中定义)。

NVIC_INT_CTRL   EQU     0xE000ED04    ; 中断控制寄存器   ; Interrupt control state register.
NVIC_SYSPRI14   EQU     0xE000ED22    ; 系统优先级寄存器(2)  ; System priority register (priority 14).
NVIC_PENDSV_PRI EQU         0xFFFF    ; PendSV 中断优先级为最低  ; PendSV priority value (lowest).
NVIC_PENDSVSET  EQU     0x10000000    ; 触发软件中断的值   ; Value to trigger PendSV exception.

NVIC_PENDSV_PRI EQU 0xFFFF ;这个语句把PendSV 中断优先级为了最低0xFFFF 。

OSStartHighRdy汇编函数:

OSStartHighRdy
    LDR     R0, =NVIC_SYSPRI14   ; 设置 PendSV 的优先级为最低    ; Set the PendSV exception priority
    LDR     R1, =NVIC_PENDSV_PRI
    STRB    R1, [R0]

    MOVS    R0, #0               ; Set the PSP to 0 for initial context switch call
    MSR     PSP, R0

    LDR     R0, =OS_CPU_ExceptStkBase    ; Initialize the MSP to the OS_CPU_ExceptStkBase
    LDR     R1, [R0]
    MSR     MSP, R1    

    LDR     R0, =NVIC_INT_CTRL    ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET
    STR     R1, [R0]              ;触发PenSv中断

    CPSIE   I                     ;开中断   ; Enable interrupts at processor level

OSStartHang
    B       OSStartHang          ;死循环,应该不会到这里的    ; Should never get here
  • LDR R1, =NVIC_PENDSV_PRI;这个语句把PendSV 中断优先级设置位0xFFFF,也就是最低。
  • LDR R1, =NVIC_PENDSVSET
    STR R1, [R0]
    ;这两个语句实现了触发PendSv异常,也就是说进入OSStartHighRdy函数会触发PendSv异常,然后会进入PendSv异常服务函数进行任务切换。

OSStartHighRdy 是由 OSStart()调用,OSStart()用来开启多任务的,如果多任务开启正常则进入OSStartHighRdy 函数触发PendSv异常并马上进行任务切换;如果多任务开启失败的话就会进 入 OSStartHang函数(这里没有贴出来)。

二、OSStart()函数:

OSStart()函数在我们的main函数里创建第一个任务的时候发生调用。(好像也只是调用一次,用于启动系统)

void  OSStart (OS_ERR  *p_err)
{
#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

    if (OSRunning == OS_STATE_OS_STOPPED) {
        OSPrioHighRdy   = OS_PrioGetHighest();    //找出目前最高优先级的函数    /* Find the highest priority                              */
        OSPrioCur       = OSPrioHighRdy;
        OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
        OSTCBCurPtr     = OSTCBHighRdyPtr;
        OSRunning       = OS_STATE_OS_RUNNING;    /*OSRunning变为1所以退出OSStart函数以后,系统开始跑*/
        OSStartHighRdy();                         //调用 OSStartHighRdy汇编函数  /* Execute target specific code to start task             */
       *p_err           = OS_ERR_FATAL_RETURN;   /* OSStart() is not supposed to return                    */
    } else {
       *p_err           = OS_ERR_OS_RUNNING;     /* OS is already running                                  */
    }
}

调用这个函数一般是在创建第一个任务时,那时系统还没开始跑;在程序里面OSRunning = OS_STATE_OS_RUNNING;把系统开始的标志位OSRunning设置为1。这个函数正常运行结束以后代表着操作系统真正开始跑起来了。
三、PendSV 异常服务函数:
PendSV 异常服务要完成两个工作:1、保存上文;2、切换下文
任务之间的切换就是发生在PendSV 异常服务函数里面。
可以理解为——触发了PendSV 异常->函数自动跳转到PendSV 异常服务函数->执行异常服务函数->实现任务的切换。
触发PendSV 异常的函数:(在os_cpu_a.asm中定义)

  • OSStartHighRdy :用得很少,只是在任务开启时在OSStart()函数里调用
  • OSCtxSw :实现任务级的任务切换
  • OSIntCtxSw :实现中断级的任务切换
PendSV_Handler
    CPSID   I        ;关中断    ; Prevent interruption during context switch
    MRS     R0, PSP   ; 将 psp 的值加载到 R0    ; PSP is process stack pointer
	
	 ; CBZ判0转移,判断 R0如果值为 0 ,则跳转到 OS_CPU_PendSVHandler_nosave
	 ; 进行第一次任务切换的时候,R0 肯定为 0
    CBZ     R0, PendSVHandler_nosave    ; Skip register save the first time

    ;判读是否使用FPU
	;Is the task using the FPU context? If so, push high vfp registers.
	TST		R14, #0X10
	IT		EQ
	VSTMDBEQ R0!,{S16-S31}
	
    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
  ;————————————保存上下文————————————————————
  ; 手动存储 CPU 寄存器 R4-R11 的值到当前任务的堆栈
	STM     R0, {R4-R11}

 ; 加载 OSTCBCurPtr 指针的地址到 R1
    LDR     R1, =OSTCBCurPtr                                    ; OSTCBCurPtr->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out

 ;—————————切换上下文—————————————
 ; 实现 OSTCBCurPtr = OSTCBHighRdyPtr
 ; 把下一个要运行的任务的堆栈OSPrioHighRdy加载到 CPU 寄存器中                                                               ; At this point, entire context of process has been saved
PendSVHandler_nosave
    PUSH    {R14}                  ; Save LR exc_return value
    LDR     R0, =OSTaskSwHook      ; OSTaskSwHook();
    BLX     R0
    POP     {R14}

    LDR     R0, =OSPrioCur         ; OSPrioCur   = OSPrioHighRdy;
    LDR     R1, =OSPrioHighRdy
    LDRB    R2, [R1]
    STRB    R2, [R0]

    LDR     R0, =OSTCBCurPtr     ; OSTCBCurPtr = OSTCBHighRdyPtr;
    LDR     R1, =OSTCBHighRdyPtr
    LDR     R2, [R1]
    STR     R2, [R0]
                                ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
    LDM     R0, {R4-R11}        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
   
   ;Is the task using the FPU context? If so, push high vfp registers.
	TST 	R14, #0x10
	IT 		EQ
	VLDMIAEQ R0!, {S16-S31} 
	
	MSR     PSP, R0            ; Load PSP with new process SP
    ORR     LR, LR, #0x04      ; Ensure exception return uses process stack
    CPSIE   I
    BX      LR                 ; Exception return will restore remaining context
    END
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UCOSIII(1)——SVC与PenSV实现任务切换 的相关文章

  • 关于博士招生“申请-考核制”,教育部这样说!

    转载于 青塔 近日 xff0c 教育部在官网上就十三届全国人大二次会议 关于改进博士生招生 申请 考核制 的建议 进行答复 答复中称 xff1a 教育部在着力探索建立博士生招生质量第三方评价机制 xff0c 推动招生单位建立健全以自我评价为
  • Keil5.26、Keil5.27、Keil5.30下载地址

    亲测有效 xff0c 速速下载 mdk5 26下载地址 http www keil com fid vquv2wwtdy9j1w9xagw1om5eu9xbkks1e66vd1 files eval mdk526 exe mdk5 27下载
  • EEPROM和flash的区别

    之前对各种存储器一直不太清楚 xff0c 今天总结一下 存储器分为两大类 xff1a ram和rom ram就不讲了 xff0c 今天主要讨论rom rom最初不能编程 xff0c 出厂什么内容就永远什么内容 xff0c 不灵活 后来出现了
  • git merge最简洁用法

    一 开发分支 xff08 dev xff09 上的代码达到上线的标准后 xff0c 要合并到 master 分支 git checkout dev git pull git checkout master git merge dev git
  • 汇编cmp比较指令详解

    刚刚看到了cmp指令 xff0c 一开始有点晕 后来上网找了些资料 xff0c 终于看明白了 xff0c 为了方便初学者 xff0c 我就简单写下我的思路吧 高手绕过 xff0c 谢谢 xff01 cmp compare 指令进行比较两个操
  • vim中复制粘贴

    在vim中要进行复制粘贴 需要使用yy和p指令 但是会发现当我们想讲从vim外面复制的内容粘贴进文本中时 光使用p达不到效果 原因是 在vim中维护者许多的clipboard 而不是只有一个 我们从vim外部 如浏览器 复制的文本所在的cl
  • NP问题真的很难理解

    希望通过这篇文章可以不仅让计算机相关专业的人可以看懂和区分什么是P类问题什么是NP类问题 xff0c 更希望达到的效果是非专业人士比如学文科的朋友也可以有一定程度的理解 有一则程序员界的笑话 xff0c 就是有一哥们去google面试的时候
  • USB转TTL、USB转串口、USB转232的区别

    PO主作为一个没有专业背景的小白 xff0c 在初玩单片机时曾被上面的几个名词所混淆 xff0c 不过后来终于大彻大悟 xff0c 现在把自己的理解写在这里 xff0c 同样准备入门单片机的小白可以看看 xff0c 或许对你有所帮助 首先
  • STM32的时钟系统RCC详细整理

    一 综述 xff1a 1 时钟源 在 STM32 中 xff0c 一共有 5 个时钟源 xff0c 分别是 HSI HSE LSI LSE PLL HSI 是高速内部时钟 xff0c RC 振荡器 xff0c 频率为 8MHz xff1b
  • 第一章 PX4程序编译过程解析

    版权声明 xff1a 本文为博主原创文章 xff0c 未经博主允许不得转载 第一章 PX4程序编译过程解析 PX4是一款软硬件开源的项目 xff0c 目的在于学习和研究 其中也有比较好的编程习惯 xff0c 大家不妨可以学习一下国外牛人的编
  • 第二章 PX4-RCS启动文件解析

    版权声明 xff1a 本文为博主原创文章 xff0c 未经博主允许不得转载 第二章 PX4 RCS启动文件解析 RCS的启动类似于linux的shell文件 xff0c 如果不知道shell文件是什么东西可以理解成是为程序的流程框 xff0
  • pixhawk position_estimator_inav.cpp思路整理及数据流

    写在前面 xff1a 这篇blog主要参考pixhawk的高度解算算法解读 xff0c 并且加以扩展 xff0c 扩展到其他传感器 xff0c 其实里面处理好多只是记录了流程 xff0c 至于里面实际物理意义并不是很清楚 xff0c 也希望
  • git创建新分支

    1 创建本地分支 git branch 分支名 xff0c 例如 xff1a git branch 2 0 1 20120806 注 xff1a 2 0 1 20120806是分支名称 xff0c 可以随便定义 2 切换本地分支 git c
  • 第一章 PX4-Pixhawk-程序编译过程解析

    第一章 PX4程序编译过程解析 PX4是一款软硬件开源的项目 xff0c 目的在于学习和研究 其中也有比较好的编程习惯 xff0c 大家不妨可以学习一下国外牛人的编程习惯 这个项目是苏黎世联邦理工大学的一个实验室搞出来的 该方案是基于NUT
  • 详解几种飞控的姿态解算算法

    姿态解算是飞控的一个基础 重要部分 xff0c 估计出来的姿态会发布给姿态控制器 xff0c 控制飞行平稳 xff0c 是飞行稳定 的最重要保障 有关姿态解算的基础知识 xff0c 这里笔者不会细细描述 xff0c 有关这方面的资料 xff
  • 陀螺仪的数据处理

    1 陀螺仪数据校准 1 1 原理 一款飞控上的传感器是需要进行校准的 xff0c 比如这里讲的陀螺仪 目前大多数的陀螺校准其实就是去掉零点偏移量 xff0c 采集一定的数据 xff0c 求平均 xff0c 这个平均值就是零点偏移 xff0c
  • LevelDB源码分析之从Put说起

    之前分享的文章leveldb实现原理分析详细描述了LevelDB的实现原理 xff0c 本文从Put接口来看下leveldb数据写流程的源码实现 LevelDB的读写接口在类DB中定义 xff08 leveldb db h xff09 xf
  • 大神浅谈无人机飞控软件设计 系统性总结

    写在前面 深感自己对飞控软件 算法的知识点过于杂乱 xff0c 很久没有进行系统的总结了 xff0c 因此决定写几篇文章记录一些飞控开发过程的知识点 主要是针对一些软件 算法部分进行讨论 xff0c 如内容有错误 xff0c 欢迎指出 1
  • 作为资深的无人机从业者,卡尔曼滤波你不能不知道 通俗易懂的来说卡尔曼滤波

    旋翼无人机的两类主要算法 先说一个旋翼类无人机系统的算法主要有两类 xff1a 姿态检测算法 姿态控制算法 姿态控制 被控对象 xff08 即四旋翼无人机 xff09 姿态检测三个部分构成一个闭环控制系统 被控对象的模型是由其物理系统决定
  • pixhawk commander.cpp的飞行模式切换解读

    commander cpp逻辑性太强了 xff0c 涉及整个系统的运作 xff0c 所以分别拆分成小块看 另此篇blog大部分是参考 xff08 Pixhawk原生固件解读 xff09 飞行模式 xff0c 控制模式的思路 xff0c 笔者

随机推荐

  • Pixhawk代码分析-源码框架

    源码框架 pixhawk代码框架 xff1a pixhawk代码框架基础分析 xff1a 阅读下面内容时请结合源码阅读 xff0c 便于理解 The basic structure of ArduPilot is broken up int
  • Pixhawk代码分析-姿态解算篇A

    姿态解算篇A 基本知识 1 如何实现控制 一个无人机系统的算法主要有两类 xff1a 姿态检测算法 姿态控制算法 姿态控制 被控对象 姿态检测三个部分构成一个闭环控制系统 被控对象的模型是由其物理系统决定 xff0c 设计无人机的算法就是设
  • 电路知识--认识原理图(一)

    开源硬件 xff0c 一个很重要的的一点就是有开放的原理图 xff0c 通过原理图 xff0c 我们可以了解一个模块的输入输出 xff0c 以及使用的芯片类型从而知道使用方法等几乎一切信息 原理图上有很多信息 xff0c 到底怎么看呢 xf
  • 初学PX4之飞控算法

    通知 xff1a 如果你对本站无人机文章不熟悉 xff0c 建议查看无人机学习概览 xff01 xff01 xff01 注意 xff1a 基于参考原因 xff0c 本文参杂了APM的算法分析 本篇文章首先简述了下px4和apm调用姿态相关应
  • Pixhawk之姿态控制篇

    一 开篇 姿态控制篇终于来了 来了 来了 心情爽不爽 xff1f 愉悦不愉悦 xff1f 开心不开心 xff1f 喜欢的话就请我吃顿饭吧 xff0c 哈哈 其实这篇blog一周前就应该写的 xff0c 可惜被上一篇blog霸占了 但是也不算
  • PX4原生固件SPI驱动动编写与IMU传感器替换

    适用于PX4原生固件 核心目标 xff1a 完成XSENS的MTI3 xff0c IMU替换 MTI3是一款航姿参考系统 xff0c 可以独立的输出四元数 xff0c 加速度 xff0c 磁力计等 xff0c 角速度等航姿信息 里面有完整的
  • C语言指针详解----指针声明定义赋值

    C语言的指针是让新手很头疼的事情 xff0c 但是由于其太过于灵活 xff0c 以至于可以很好得的解决一些复杂的问题 xff0c 因此不得不掌握 我最近正在学习指针相关的内容 xff0c 因此在这里做一个小的总结 本篇是不涉及到函数以及结构
  • 【slam-2020-01-02】扩展应用

    一篇比较全面的slam博客 一 VR 43 AR 1 VR和AR的关系 AR MR是平台 xff0c 覆盖面比VR更广 xff0c VR是一种媒体形式 xff0c 任何用得到媒体的场景 xff0c 如娱乐 教育等 xff0c 都会有VR的影
  • nvidia-smi卡顿详解

    如果显卡数量在4张以上 xff0c 在nvidia smi信息后会非常的慢 xff0c 非常的卡 尤其在只在乎计算量服务器的时候 我试过把8张卡 tesla K80 显卡一个个拆下来 8张 7张 6 5 4 3 2 1 试试nvidia s
  • c语言将十进制数转换为16进制的函数

    有3种方式实现 xff0c 其中两种是使用系统函数 xff0c 另一种是直接自己编写 使用系统函数实现要加入 include lt stdlib h gt xff0c 自己编写则不需要这个头文件 下面的代码就是3种方式的实现 xff0c 包
  • go-gl搭建开发环境(一)

    1 简介 Go语言 xff08 Golang xff09 是Google在2009年推出的一种编程语言 Golang是一门开源的语言 xff0c 可以从github上找到它的源码 Golang也是一门跨平台的语言 xff0c 可以运行在Wi
  • 串口UART透传WiFi模块常见的几种参数配置方法含web网页配置

    串口透传WiFi参数配置方法 目前 xff0c 在嵌入式领域 xff0c 智能家居 智能工业 智能公交等等控制中 xff0c WiFi 已经成为了一种普遍被采用的技术 笔者常年在嵌入式 WiFi 行业做一线技术开发 本文我们将介绍串口 wi
  • DockerHub基于Github自动化构建

    Docker Hub上的自动化构建 关于自动化构建 自动化构建是一个特殊的功能 xff0c 它允许您在 Docker Hub 上使用构建集群 xff0c 根据指定的 Dockerfile 或者 GitHub BitBucket 仓库 xff
  • 机器人三维视觉引导系统

    基于结构光测量技术和3D物体识别技术开发的机器人3D视觉引导系统 xff0c 可对较大测量深度范围内散乱堆放的零件进行全自由的定位和拾取 相比传统的2D视觉定位方式只能对固定深度零件进行识别且只能获取零件的部分自由度的位置信息 xff0c
  • rviz 官网

    rviz使用教程 官网 http wiki ros org rviz UserGuide Install or build rviz
  • Robocup2D入门笔记(4)——常见模型

    Robocup2D中有几个常见的模型 xff0c 例如听觉 视觉 移动 踢球等 xff0c 这篇博客主要介绍这几个常见的模型 xff0c 这些模型也都可以在官方发布的说明书中找到 xff08 懒得找可以点这里 xff09 一 球场模型 Ro
  • 2020电赛小记

    64 2020电赛总结 xff08 吐槽 xff09 2020电赛小记 本篇全为吐槽 xff0c 不是经验贴 坐标青岛某双非 说不上最恶心不过够恶心 20年参加电赛 xff0c 和一个大三的师哥组队 xff0c 在组期间任劳任怨 xff0c
  • 如何通过nodejs快速搭建一个服务器

    在前端开发过程中 xff0c 可能某些时候需要自己搭建一台服务器用于一些文件图片请求或者进行后端相关知识的学习 本文主要讲解如何通过nodejs进行一个基础服务器的搭建 xff0c 包括如何将文件布置的服务器 xff0c 以及基础接口的开发
  • import 一些已有的模块,会出现红色下划线

    导入tensorflow 以及使用print xff0c 都会出现红色下划线 xff0c 然而程序是没有错误的 这种情况其实可以不用管 xff0c 是可以正常运行的 xff1b 但是 xff0c 如果看着不舒服 xff0c 可以进行以下过程
  • UCOSIII(1)——SVC与PenSV实现任务切换

    本文基于STM32F407ZGT6 SVC异常 xff1a SVC 系统服务调用 xff0c 亦简称系统调用 用于产生系统函数的调用请求 SVC 异常是必须立即得到响应的应用程序执行 SVC 时都是希望所需的请求立即得到响应 在 UCOS