【UCOSIII源码阅读笔记】第三篇——PendSV异常处理分析

一步步写STM32 OS【三】PendSV与堆栈操作 一、什么是PendSV PendSV是可悬起异常,如果我们把它配置最低优先级,那么如果同时有多个异常被触发,它会在其他异常执行完毕后再执行,而且任何异常都可以中断它。更详细的内容在《Cortex-M3 权威指南》里有介绍,下面我摘抄了一段。 OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动 作。悬起 PendSV 的方法是:手工往 NVIC的 PendSV悬起寄存器... 阅读详情

前言

本文对ucos中为什么使用PendSV,以及如何使用PendSV进行分析。

正文

ucos任务切换的核心工作是在PendSV异常服务函数中完成的。
如果通过SysTick中断进行上下文切换,理想情况如下:
在这里插入图片描述
现实情况是SysTick中断被触发时,系统有可能正在处理另一个中断请求。此时SysTick中断打断了正在处理的中断请求,情况如下:
在这里插入图片描述
IRQ正在执行时,如果SysTick完成了上下文切换,并且要回到线程模式,这是CPU会触发用法fault异常。
所以完成上下文切换并回到线程模式这件事,需要一个优先级很低的中断完成,低到不会打断其他任何中断,这就用到了PendSV中断。
首先需要把PendSV编程为最低优先级异常,如果某IRQ被SysTick抢占,SysTick只是会悬起一个PendSV中断,然后继续执行IRQ,等IRQ执行完毕再执行PendSV进行任务切换,如下:
在这里插入图片描述
这样就解决了会有在IRQ中返回线程模式的情况。

从以上分析可以看出,PendSV要保证中断优先级最低。
系统异常优先级寄存器如下:
在这里插入图片描述
可以看到设置PendSV优先级的寄存器为0xE000ED22。
中断控制及状态寄存器如下:
在这里插入图片描述
可以看到对寄存器0xE000ED04的第28位写入1可以悬起PendSV。
对应ucos代码在os_cpu_a.s文件中,起始位置有一段宏定义如下:

在这里插入图片描述
对NVIC_SYSPRI14写入NVIC_PENDSV_PRI可以设置PendSV中断优先级为0xff(最低)。
对NVIC_INT_CTRL写入0x10000000可以悬起PendSV。
之后有如下一段代码:

OSStartHighRdy
    LDR     R0, =NVIC_SYSPRI14                                  ; 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]
    
    CPSIE   I                                                   ; Enable interrupts at processor level

OSStartHang
    B       OSStartHang                                         ; Should never get here

其中的
在这里插入图片描述
用于设置0xE000ED22寄存器内容为0xFF。

在这里插入图片描述
用于设置PSP的值为0。
在这里插入图片描述
用于设置MSP的值为OS_CPU_ExceptStkBase。

  • MSP为主堆栈指针:复位后缺省使用的堆栈指针,用于操作系统内核以及异常处理例程(包
    括中断服务例程)。
  • PSP为进程堆栈指针:由用户的应用程序代码使用。
    在这里插入图片描述
    用于将0xE000ED04寄存器赋值为0x10000000,即悬起PendSV中断。

OSStartHighRdy由OSStart()函数调用。

接下来是PendSV中断服务函数的内容,如下:

OS_CPU_PendSVHandler
    CPSID   I                                                   ; Prevent interruption during context switch
    MRS     R0, PSP                                             ; PSP is process stack pointer
    CBZ     R0, OS_CPU_PendSVHandler_nosave                     ; Skip register save the first time

    SUBS    R0, R0, #0x20                                       ; Save remaining regs r4-11 on process stack
    STM     R0, {R4-R11}

    LDR     R1, =OSTCBCurPtr                                    ; OSTCBCurPtr->OSTCBStkPtr = SP;
    LDR     R1, [R1]
    STR     R0, [R1]                                            ; R0 is SP of process being switched out

                                                                ; At this point, entire context of process has been saved
OS_CPU_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]

    LDR     R0, [R2]                                            ; R0 is new process SP; SP = OSTCBHighRdyPtr->StkPtr;
    LDM     R0, {R4-R11}                                        ; Restore r4-11 from new process stack
    ADDS    R0, R0, #0x20
    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

其中的
在这里插入图片描述
用于判断PSP的值是否为0,如果是0说明是系统刚启动,不用保存就得任务信息,直接跳转到OS_CPU_PendSVHandler_nosave执行,nosave意思是不进行压栈保存数据的处理。

在这里插入图片描述
用于将R4-R11寄存器的内容压栈保护起来,R4-R11被称为“被调用者保护寄存器”,R0-R3、R12、LR和xPSR被称为“调用者保护寄存器”,调用者保护寄存器在触发中断时,CPU就会自动压栈,所以ucos只负责将被调用者保护寄存器内容压栈,这部分内容在【Cortex-M3】中断处理时栈空间操作过程分析一文中有详细讲解。
在这里插入图片描述
用于将OSPrioCur赋值为OSPrioHighRdy。
在这里插入图片描述
用于将OSTCBCurPtr赋值为OSTCBHighRdyPtr。
OSTCBCurPtr指向的一个os_tcb的结构体的第一项为该任务的栈指针:
在这里插入图片描述
接下来的
在这里插入图片描述
用于将新的任务的R4-R11出栈。
在这里插入图片描述
用于打开中断,跳转到新的任务开始执行代码。

uCOS-III阅读,第一天,也就瞎看看 写在前面的注释 本文是作者自己阅读uCOS的笔记,刚刚开始,逻辑混乱,以后可能会修改,不过以我的性格,难!!! 传到晚上只是想借用网络资源储存,谢谢 网上搞的材料 下载了stm32f103的固件库 寻找一个stm32f107的ucos III的移植好的例子1.2x版本的 移植 移植方面因为抄的是别人的例子,所以比较简单。主要是构建一个自己习惯的文件夹目录。 初探Main函数 Main函数中的主要函 阅读详情

相关推荐

uC/OS-III 学习笔记(一)——uC/OS-III移植

uC/OS-III 学习笔记(一)uC/OS-III移植前言  最近毕设要做一个嵌入式设备,需要用到操作系统。本人只会制板和写ARM裸机程序,OS方面是一个小白,只对uC/OS和Linux两种系统略有了解。鉴于嵌入式Linux学习周期较长,有可能在毕设结束之前都不能学到能够开发项目的地步。故选择uC/OS作为设备的操作系统。   之所以选择uC/OS-III,是本着“要学就学最新”的想法来的。uC

lingsuifenfei123的博客 7575

面向UCOS系统,PENDSV异常服务程序OS_CPU_PendSVHandler详细分析

老羊独家

yangkuiwu的博客 8819

四阶龙格库塔法求解一次常微分方程组(python实现)

之前在博客发布了关于使用四阶龙格库塔方法求解一次常微分方程组的文章,由于代码缺少具体的验证,部分朋友可能存在疑问,因此这里打算再重新写一篇博客来验证一下程序的正确性,另外,这里是使用python语言来实现的。

HelloWorldTM的博客 8543

os_cpu.h

定位到源码的uCOS-II/Ports/ARM-Cortex-M3/Generic/IAR/os_cpu.h:1. 全局变量OS_CPU_GLOBALS 和OS_CPU_EXT 允许我们是否使用全局变量。#ifdef OS_CPU_GLOBALS #define OS_CPU_EXT #else #define OS_CPU_EXT extern #endif若没有定义OS_CPU_GLO

echo_bright_的博客 1092

嵌入式设备的switch 以及PHY 芯片调试和选型 (1)

越来越的设备需要多网口的需求,于是需求搭配一个交换机实现网口的扩展。但是很多软件或是硬件工程师在实际选型和应用中经常会遇到一些问题。这里总结一下,避免大家采坑。 几个概念: MAC(介质访问控制),可以理解成数据链路层即可 PHY(物理性),简单理解层转成物理层的连接组件即可 控制接口(MDC/DMIO,I2C,...

睿峰的博客 1万+

【Rcode】生存分析: KM & COX回归& 随机森林& nomogram

本文使用了R——survival包下的lung数据进行方法测试: 1)KM 2) Cox回归:多因素 3)随机森林因子(根据cox回归结果) 4)nomogram ( 根据cox回归结果,建立了中位生存时间,1年5年生存率的概率计算) -------------------????????‍♀️本文只有干货,非常干!????----------------------------- 一、数据加载 #生存分析 library("survival") library("survminer") data("

weixin_43172152的博客 9273

UCOSIII钩子函数

OSIdleTaskHook 空闲任务调用这个函数,可以用来让CPU进入低功耗模式void OSIdleTaskHook (void) { #if OS_CFG_APP_HOOKS_EN > 0u if (OS_AppIdleTaskHookPtr != (OS_APP_HOOK_VOID)0) { (*OS_AppIdleTaskHookPtr)(); } #e

超哥的专栏 4642

MATLAB新手必看:SVPWM七段式算法仿真全流程解析(附完整代码)

本文为MATLAB新手和电机控制初学者提供了SVPWM七段式算法的完整仿真与代码实现指南。文章详细解析了从扇区判断、矢量作用时间计算到PWM波形生成的全流程,并附带了可直接运行的MATLAB代码,帮助读者在理解FOC控制核心算法的基础上,快速掌握工程仿真与调试技巧。

weixin_29074295的博客 281

UCOSiii--源码阅读

我在阅读ucos源码过程遇到的一写小问题 1.OSTaskDel()任务删除函数 在任务函数中,调用次函数传入空指针,将会删除本任务(一直以为要传入任务控制块才行,原来还可以传入空指针) 2.钩子函数 以空闲任务的钩子函数来说, 在OSIdleTaskHook() (在os_cpu_c.c)中调用 最终调用的是函数App_OS_IdleTaskHook(),也就是说如果我们想要在空闲任务的钩子函数中做其他处理就需要将代码写在App_OS_IdleTaskHook() 如下:空闲任务钩子函数相应的处理

风间琉璃的博客 1456

Allegro模块复用:从原理图到PCB的完整流程与关键细节

本文详细介绍了Allegro模块复用从原理图到PCB的完整流程与关键细节,包括DSN和MDD文件的创建、模块调用的实战技巧以及双向同步与版本控制方法。通过标准化处理和高级复用技巧,能显著提升PCB设计效率,减少重复工作时间。适用于智能硬件和工业控制等领域的工程师。

weixin_30252709的博客 332

给跨代引用记一本账:Java GC 的分配路径、卡表写屏障与收集器版图快速回顾

本文把 Java GC 的零散名词串成一条推理链路:从 TLAB 指针碰撞分配、逃逸分析,到 Eden、Survivor 与晋升的四条路,重点拆解卡表与写屏障如何为老年代指向新生代的引用记账,及 Minor GC 如何只扫脏卡。基于 JDK 8 实测:分散写使 Young GC 停顿涨 10~15 倍,条件卡标记消除卡表伪共享,计数循环让 System.gc 等待 2.7 秒,Survivor 过小使晋升量增加约 400 倍。文末梳理 JDK 8 到 27 的收集器演进、选型路径与排查顺序。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 17万+

02_Free RTOS源码获取+移植

本文介绍基于 HAL 库在 STM32 开发板手动移植 FreeRTOS 的完整流程。文章解析 FreeRTOS 源码架构,讲解 Source 目录下核心文件的移植用途,结合 MDK 环境筛选所需工程文件。教程以 STM32F429 为例,配套源码与教学视频,重点说明 portable 文件夹是软硬件适配桥梁,需按编译器选用 RVDS 适配文件。掌握通用移植思路,完成一两次实操后,就能适配 STM32F103 等其他芯片,适合嵌入式入门学习者。

m0_65234512的博客 421

数据服务:数据服务框架Magic-API 介绍及实践

接口快速开发框架 基于Java的接口快速开发框架,编写接口将通过magic-api提供的UI界面完成,自动映射为HTTP接口,无需定义Controller、Service、Dao、Mapper、XML、VO等Java对象即可完成常见的HTTP API接口开发 。在线页面快速开发平台 基于 vue 的在线页面快速开发平台,主要把所有的 vue 代码都改为在线配置,最终获得一个 json 格式的页面新一代爬虫平台 基于Java实现的新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。今天给大家安利一

GIS摆渡人 2063

uCOS-II 的任务上下文切换流程

uCOS-II 的任务上下文切换流程

坚韧与专注 1930

【24E】SWT6652 wifi驱动加载失败问题分析及解决方案

修改驱动配置Kconfig。是由于内存分配失败导致。

wgl307293845的博客 219

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

RTOS系列(12):使用SVC或PendSV启动OS流程详细分析

RTOS系列(1):基础知识——中断嵌套 RTOS系列文章(2):PendSV功能,为什么需要PendSV RTOS系列文章(3): 为什么将SysTick和PendSV的优先级设置为最低 RTOS系列文章(4): MDK软件仿真 + Debug-(printf)-Viewer使用方法 RTOS系列文章(5):C语言程序运行原理分析:汇编、栈、栈帧、进栈、出栈、保存现场、恢复现场、返回 RTOS系列文章(6):Cortex-M3/4之SP,MSP,PSP,Thread模式、Handler模式、内核态、用户态

猪哥的专栏 4536

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

uCOS-Ⅲ中PendSV任务切换详细分析(运行模式切换会自动加载的内容)

当调用OSStartHighRdy()函数,会触发PendSV异常后,就需要编写PendSV异常(可以手动触发,也叫软中断)服务函数,然后在里面进行任务的切换。 PendSV异常服务中主要完成两个工作,一是保存上文,即保存当前正在运行的任务的环境参数;二是切换下文,即把下一个需要运行的任务的环境参数从任务栈中加载到CPU寄存器,从而实现任务的切换。 PendSV异常服务中用到了OSTCBCurPtr和OSTCBHighRdyPtr这两个全局变量,这两个全局变量在os....

biao2488890051的博客 1001

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【STM32 UCOSIII】UCOSIII中断原理、以及相关指令LDR、STRB解析

SHPR1寄存器:0xE000_ED18SHPR2寄存器:0xE000_ED1CPendsv:实现任务切换;SysTick:提供UcosIII的系统节拍。

dagengen12138的博客 2369

uCOS上下文切换,PendSV中断函数

摘自:http://www.stmcu.org/module/forum/thread-384142-1-1.html 介绍一: 移植详解1和2中主要讲了移植需要用到的基础知识,本文则对具体的移植过程进行介绍。    首先从micrium网站上下载官方移植版本(编译器使用ARM/Keil的,V2.86版本,V2.85有问题)。    下载地址:http://micrium.com/pag

wg_hou的博客 2339

ucos移植中断部分

在stm32启动代码中有如下向量表:

qq_39203898的博客 292

UCOS-III 系统启动接口OSStart详解

UCOS内核启动流程 第一个就绪任务是如何启动的? 为什么设置PendSV异常优先级为最低优先级?

TechIoT - 探索物联网与嵌入式系统 1374

uc-os 任务切换汇编部分详细解析

废话不多,直接上干活 1、任务切换会通过调用OSCtxSw这个函数 OSCtxSw LDR R0, =NVIC_INT_CTRL LDR R1, =NVIC_PENDSVSET STR R1, [R0] BX LR ;这段代码是跳转倒pendSV的中断函数中运行。 2、中断函数内容如下 OS_CPU_P

a1039012273的博客 328

uCOS3实时操作系统(系统初始化和任务启动)

需要注意的是,在我们使用裸机进行中断任务切换的时候不管主程序还是中断都是使用的是MSP堆栈指针,而在ucos操作系统中我们在主程序的任务切换上使用的是PSP堆栈指针,在中断系统调度上中我们使用的是MSP堆栈指针,此外,在中断进行时,系统会自动出入栈R4-R11以及LR寄存器。开始 µC/OS-III 任务调度是 µC/OS-III 内核开始运行前的最后一步,在此之前需要先调用函数 OSInit()对 µC/OS-III 内核进行初始化,并至少创建一个应用任务。控制寄存器选择当前使用哪个堆栈指针。

嵌入(师) 1371

UCOSIII移植问题说明

在进行UCOSIII一致的过程中 在进入Systick中断的过程中一定要确保系统已经开始运行才能够进入中断,否则容易出错void SysTick_Handler(void) { if(delay_osrunning == 1) //一定要确保系统已经开始运行才能够开始进入 { OSIntEnter(); OSTimeTicK();

andrewbytecoder 2280

(学习日记)2024.03.03:UCOSIII第五节:常用汇编指令+OS初始化+启动任务+任务切换

2024.03.03 十、UCOSIII:常用汇编指令 十一、UCOSIII:OS系统初始化 十二、UCOSIII:启动系统 十三、UCOSIII:任务切换 1、PendSV异常 2、PendSV异常服务函数

一个放笔记的小书架 1643

cortex-M3 的SVC、PendSV异常,与操作系统(ucos实时系统)

SVC异常是? PendSV异常是? ucos 任务切换时机? ucos 如何满足实时性(实现)? ucos中,systick的优先级? SVC和PendSV SVC(系统服务调用,亦简称系统调用)和PendSV(可悬起系统调用),它们多用于在操作系统之上的软件开发中。 SVC: SVC 用于产生系统函数的调用请求。 例如,操作系统不让用户程序直接访问硬件,而是通过提供一些系...

@角色扮演# 3万+
上一篇: Xilinx SDK创建项目时报错“Error generating bsp sources. Please check the SDK Log view for further details.”
下一篇: 【UCOSIII源码阅读笔记】第四篇——临界区
inputA
博客等级 码龄7年 297粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值