【FreeRTOS】3. PendSV异常

2023-05-16

PendSV异常

问题:

  1. 怎么触发PendSV异常?
  2. 何时使用MSP何时切换PSP?
  3. PendSV如何实现上下文切换?

1. 触发PendSV异常

在RTOS内核中,任务切换的原理是:手动触发PendSV异常,在PendSV异常服务函数中实现任务切换。

freeRTOS有两种方式触发PendSV异常,一种是通过调用portYIELD(), 另一种是在Systick_Handler()中时基增加出现上下文切换请求。

触发PendSV异常的方法在task.h中的

#define portYIELD()										\
{														\
    /*触发PendSV,产生上下文切换*/						    \
    portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;		\
}

以及port.c中的

void xPortSysTickHandler( void )
{
    /* 设置中断掩码,关中断 */
	portDISABLE_INTERRUPTS();
	{
		/* Increment the RTOS tick. */
		if( xTaskIncrementTick() != pdFALSE )	/* 检查就绪列表出现更高优先级的任务 */
		{
			/* 需要任务切换,产生PendSV中断 */
			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
		}
	}
	portENABLE_INTERRUPTS();
}

portmacro.h中定义了中断控制状态寄存器:portNVIC_INT_CTRL_REG = 0xe000ed04。

其Bit 28 为PENDSVSET: portNVIC_PENDSVSET_BIT:PendSV悬起位

image-20211112215504221

因此,只要在portYIELD()或者xPortSysTickHandler()中调用了:

portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;

执行后就会进入PendSV异常,在PendSV中断服务函数中实现上下文切换。

2. 堆栈指针的切换

异常(PendSV异常)发生时,R14保存异常返回标志,包括返回后进入任务模式还是处理模式、使用PSP还是MSP。

在PendSV异常保存上文时,通过向 R14 寄存器最后 4 位按位或上 0x0D,使得硬件在退出时使用进程堆栈指针 PSP 完成出栈操作,并在异常返回后进入任务模式、返回 Thumb 状态。然后将R14压入任务堆栈,一遍下次切换回该任务时获取R14的内容。

PendSV异常切换到下文时会将新任务堆栈中的R14读取出来,由于上文将R14做了保存,此时R14=0xFFFFFFFD,表示异常返回后进入任务模式,使用PSP作为堆栈指针出栈,出栈完毕后PSP指向任务栈栈顶。

3. PendSV中断实现上下文切换

在 stm32 中 PendSV 的异常服务函数名为 PendSV_Handler,在stm32xxxx_it.c中为弱定义,直接重定义函数即可。

在PendSV异常中执行四个步骤:

  1. 关闭中断
  2. 保存上文
  3. 加载下文
  4. 打开中断
__asm volatile void xPortPendSVHandler( void )
{
	extern pxCurrentTCB;
    extern vTaskSwitchContext;
    PRESERVE8
	mrs r0, psp		//R0=PSP
	isb									
	ldr	r3, =pxCurrentTCB /* Get the location of the current TCB. */
	ldr	r2, [r3]		//R2=pxCurrentTCB
	stmdb r0!, {r4-r11}	/* Save the remaining registers. */
	str r0, [r2]	 /* Save the new top of stack into the first member of the TCB. */
	stmdb sp!, {r3, r14}	//入栈保存R3(即&pxCurrentTCB)和 R14			
	mov r0, %0							
	msr basepri, r0		//关闭中断		
	bl vTaskSwitchContext	//在临界段切换就绪队列中优先级最高的任务,更新pxCurrentTCB
	mov r0, #0							
	msr basepri, r0		//开启中断
	ldmia sp!, {r3, r14}	//从主堆栈中恢复寄存器R3和R14的值,此时SP使用的是MSP
	ldr r1, [r3]	//将R3存放的pxCurrentTCB的地址赋予R1	
	ldr r0, [r1]	/* The first item in pxCurrentTCB is the task top of stack. */
	ldmia r0!, {r4-r11}		 /* Pop the registers. */
	msr psp, r0		//PSP=R0,更新PSP使异常退出时PSP为基地址进行其他寄存器的自动出栈,如下图1
	isb									
	bx r14	//系统以PSP作为SP指针出栈,把新任务的任务堆栈中剩下的内容加载到CPU寄存器:R0(任务形参)、R1、R2、R3、R12、R14(LR)、R15(PC)和xPSR,切换到新任务,如图2			
	nop
}

汇编代码流程如下:

CSDN图片

图1:
图1

图2:
图2

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【FreeRTOS】3. PendSV异常 的相关文章

  • FreeRTOS 软件定时器的使用

    FreeRTOS中加入了软件定时器这个功能组件 是一个可选的 不属于freeRTOS内核的功能 由定时器服务任务 其实就是一个定时器任务 来提供 软件定时器是当设定一个定时时间 当达到设定的时间之后就会执行指定的功能函数 而这个功能函数就叫
  • FreeRTOS-内核控制函数

    FreeRTOS 内核控制函数 FreeRTOS中有一些内核函数 一般来说这些内核函数在应用层不会使用 但是内核控制函数是理解FreeRTOS中断的基础 接下来我们逐一分析这些内核函数 taskYIELD 该函数的作用是进行任务切换 这是一
  • FreeRTOS软件定时器创建、复位、开始和停止(备忘)

    目录 一 简介 1 1 开发环境 1 2 摘要 二 STM32CubeIDE配置 三 创建定时器 3 1 头文件声明 3 2 工程文件定义 3 3 创建定时器 3 4 开启 复位 和关闭定时器 四 定时器回调函数 一 简介 1 1 开发环境
  • Freertos中vTaskDelay()是怎么用的

    1 常见的使用场景 void vLED Task void pvParameters while 1 Heartbeat LED vTaskDelay 1000 portTICK RATE MS 说明 上面这段代码的意思是 led翻转后经过
  • FreeRTOS系列

    1 RTOS简介 RTOS全称为 Real Time Operation System 即实时操作系统 RTOS强调的是实时性 又分为硬实时和软实时 硬实时要求在规定的时间内必须完成操作 不允许超时 而软实时里对处理过程超时的要求则没有很严
  • 基于HAL库的FREERTOS----------一.任务

    FreeROTS 就是一个免费的 RTOS 类系统 这里要注意 RTOS 不是指某一个确定的系统 而是指一类系统 比如 UCOS FreeRTOS RTX RT Thread 等这些都是 RTOS 类操作系统 FreeRTOS 是 RTOS
  • freeRTOS使用uxTaskGetStackHighWaterMark函数查看任务堆栈空间的使用情况

    摘要 每个任务都有自己的堆栈 堆栈的总大小在创建任务的时候就确定了 此函数用于检查任务从创建好到现在的历史剩余最小值 这个值越小说明任务堆栈溢出的可能性就越大 FreeRTOS 把这个历史剩余最小值叫做 高水位线 此函数相对来说会多耗费一点
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • 【FreeRTOS】任务通知的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • FreeRTOS笔记(一)简介

    这个笔记主要依据韦东山freertos快速入门系列记录 感谢韦东山老师的总结 什么是实时操作系统 操作系统是一个控制程序 负责协调分配计算资源和内存资源给不同的应用程序使用 并防止系统出现故障 操作系统通过一个调度算法和内存管理算法尽可能把
  • 13-FreeRTOS任务创建与删除

    任务创建和删除API函数位于文件task c中 需要包含task h头文件 task h里面包函数任务的类型函数 例如 对xTaskCreate的调用 通过指针方式 返回一个TaskHandle t 变量 然后可将该变量用vTaskDele
  • FreeRTOS实时操作系统(三)任务挂起与恢复

    系列文章 FreeRTOS实时操作系统 一 RTOS的基本概念 FreeRTOS实时操作系统 二 任务创建与任务删除 HAL库 FreeRTOS实时操作系统 三 任务挂起与恢复 FreeRTOS实时操作系统 四 中断任务管理 FreeRTO
  • 再论FreeRTOS中的configTOTAL_HEAP_SIZE

    关于任务栈和系统栈的基础知识 可以参考之前的随笔 FreeRTOS 任务栈大小确定及其溢出检测 这里再次说明 define configTOTAL HEAP SIZE size t 17 1024 这个宏 官方文档解释 configTOTA
  • 如何更改 FreeRTOS 中任务的最大可用堆大小?

    我通过以下方式在任务中创建元素列表 l dllist pvPortMalloc sizeof dllist dlllist 有 32 字节大 我的嵌入式系统有 60kB SRAM 所以我希望系统可以轻松处理我的 200 个元素列表 我发现在
  • 有可用的 FreeRTOS 解释语言库吗?

    我在一家公司工作 该公司使用 FreeRTOS 为多个设备创建固件 最近 我们对新功能的要求已经超出了我们固件工程师的工作能力 但我们现在也无力雇用任何新人 即使进行微小的更改 也需要固件人员在非常低的级别上进行修改 我一直在为 FreeR
  • 小型 ARM 微控制器的 RTOS 内核之间的可量化差异 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 有许多不同的 RTOS 可用于微控制器 我专门寻找支持 ARM Cortex M 处理器的 RTOS 另外 我对闭源解决方案不感兴趣 试图从网站
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 当 Cortex-M3 出现硬故障时如何保留堆栈跟踪?

    使用以下设置 基于 Cortex M3 的 C gcc arm 交叉工具链 https launchpad net gcc arm embedded 使用 C 和 C FreeRtos 7 5 3 日食月神 Segger Jlink 与 J

随机推荐

  • Linux常用命令详解 xfs文件系统的备份与还原 xfsdump和xfsrestore命令详解

    Linux常用命令详解 xfs文件系统的备份与还原 xfsdump和xfsrestore命令详解 一 引言 1 xfsdump xff1a xfs文件系统的备份 2 xfsstore xff1a xfs文件系统的还原 二 命令具体介绍与用法
  • 小白入门gitee(码云)

    文章目录 一 介绍二 注册账户三 本地环境的配置1 如果是在linux系统2 如果是windows系统 四 本地代码库的操作1 基本概念2 命令操作 五 远程代码库的操作1 下载远程代码库的代码2 同步远程仓库 xff08 上传代码 xff
  • ubuntu:安装cmake后查看版本报错:CMake Error: Could not find CMAKE_ROOT !!!

    问题描述 xff1a ubuntu18原来安装过cmake xff0c 想升级下版本 xff0c 在安装新版本的cmake完成后 xff0c 输入指令 xff1a cmake version 查看版本号时出现以下错误 xff1a CMake
  • g++ 编译选项

    返回主页 lsgxeva MyGitee https gitee com lsgx MyGithub https github com lsgxeva 博客园首页新随笔联系订阅管理 随笔 437 文章 0 评论 1 GCC 警告 优化以及调
  • STM32CubMx+FreeRTOS互斥锁和递归互斥锁(五)

    文章目录 FreeRTOS系统一 简绍二 STM32CubMx配置1 准备2 添加互斥锁2添加递归互斥锁 三 互斥锁1 代码2 测试 四 递归互斥锁1 代码2 测试 FreeRTOS系统 一 简绍 互斥锁 xff0c 谁获得的消息谁来释放
  • ESP8266-12F最小系统板程序烧录

    文章目录 ESP8266一 简介二 准备1 ESP8266 12F系统板2 转接板3 USB转串口模块4 烧录软件 三 连接烧录四 下载 ESP8266 一 简介 前一段时间一直用ESP8266 12F开发板来学习开发 xff0c 但是最近
  • ESP8266+0.96OLED驱动显示(I2C)

    文章目录 ESP8266一 简介二 管脚定义三 代码 ESP8266 一 简介 这篇我们说一下ESP8266来驱动OLED显示屏显示 xff0c 这里使用的是I2C的屏幕 xff0c 像Arduino中有好几个库可以驱动屏幕 xff0c 但
  • Node.js超详细指南(一)

    文章目录 一 概述二 Node js的特点1 异步I O2 事件驱动3 单线程4 支持微服务 三 Node js下载与安装安装步骤验证安装是否正确 一 概述 Node js的官方开发语言是JavaScript JavaScript是前端开发
  • Linux未设置root初始密码怎么办?

    问题描述 xff1a Linux未设置初始密码 xff0c 无法从用户状态切换到root状态怎么办 xff1f 是不是遇上下面的情况 xff1a 解决方案 xff1a 使用下列命令进行修改root密码 sudo passwd root
  • 计算机体系结构——功能部件

    一 功能部件 加法器 1 全加器 全加器 将两位本地二进制数和1位低位进位的数进行相加 xff0c 求的1位本地结果以及1位向高位进位的结果 简单来说就是3个input xff0c 2个output xff0c 这里的逻辑比较简单 xff0
  • Mac M1遇到更换清华源不成功问题解决办法(实测有效)

    遇到的问题 在使用如下命令更换为清华源后 xff0c update时出现了错误 xff1a bash span class token operator span c 39 echo span class token string 34 d
  • Ubuntu安装gcc遇到Depends依赖问题解决办法(XXX : Depends: gcc-12-base)

    gcc遇到依赖问题 libatomic1 Depends gcc 12 base 61 12 20220319 1ubuntu1 but 12 1 0 2ubuntu1 22 04 is to be installed libc6 dev
  • Tmux终端复用器下载安装及配置文件(超好用)

    1 Tmux简介 tmux是一款非常好用的终端复用软件 xff0c 曾经的你是不是还在为开n个终端而烦恼呢 xff0c 有了tmux就可以实现多终端显示在一个桌面上 xff0c 分屏丝滑 xff0c 当然还有其他功能 xff0c 比如保护现
  • make menuconfig遇到 warning:.config does not exists

    一生一芯PA0 xff1a PA0 xff1a make menuconfig 编译报错 问题描述 遇到的报错 xff1a 解决方案 xff1a 安装缺失的工具 xff1a 安装 bison 和 flex即可 xff0c flex和 bis
  • LibTorch1.7.1: error: ‘min_values’ is not a member of ‘at’

    错误描述 xff1a 原来用的libtorch的版本是1 5 0的 xff0c 今天换成了最新的1 7 1 xff0c 就报了这个错误 xff1a error min values is not a member of at 解决方法 xf
  • Github使用指南

    文章目录 注册成为用户GitHub功能及常用词汇板块说明Your profile使用仓库上传资源查找资源 注册成为用户 首次使用GitHub并准备长期使用需要先注册 xff0c 当然也可以以游客的方式进行浏览 登录官网GitHub Wher
  • 三孔插座接线方法(上地,左零,右火)

    三孔插座接线方法 一般三孔插座的线序 xff0c 如下图所示 xff1a 上 xff1a 地线 xff08 保护地 xff09 左 xff1a 零线 右 xff1a 火线 xff08 相线 xff09 正确的接接线方法 错误的接线方法 xf
  • CAN总线详解

    CAN总线协议 要了解报文数据帧的直接看第三点 1 CAN简介 CAN controller area network 控制器局域网是用于解决汽车众多控制部件之间的数据交换而开发的一种串行数据通信总线 其特点有 xff1a 总线上节点不分主
  • 【FreeRTOS】2. SVC系统调用

    SVC系统调用 问题 xff1a RTOS内核在何时去产生一个SVC系统调用 xff1f SVC中断服务里面使用的是MSP堆栈指针 xff0c 内核在何时切换为PSP指针 xff1f 1 产生SVC系统调用 FreeRTOS启动调度器的时候
  • 【FreeRTOS】3. PendSV异常

    PendSV异常 问题 xff1a 怎么触发PendSV异常 xff1f 何时使用MSP何时切换PSP xff1f PendSV如何实现上下文切换 xff1f 1 触发PendSV异常 在RTOS内核中 xff0c 任务切换的原理是 xff