FreeRTOS系列|中断管理和临界段

2023-05-16

FreeRTOS中断管理和临界段

1. 中断管理

1.1 中断管理简介

中断是微控制器的一个常见特性,中断由硬件产生,当中断产生后CPU就会中断当前的流程转而去处理中断服务,Cortex-M内核的MCU提供了一个用于中断管理的嵌套向量中断控制器(NVIC)

当多个中断来临时处理器应该享有哪一个中断是由中断的优先级来决定的,高优先级的中断(优先级编号小)首先得到响应,而高优先级的中断可以抢占低优先级的中断,即中断嵌套。Cortex-M处理器的有些中断是具有固定的优先级的,比如复位、NMI、HardFault,这些中断的优先级都是负数,优先级也是最高的

Cortex-M处理有三个固定优先级和256个可编程的优先级,最多有128个抢占登记,实际的优先级数量由芯片厂商决定的。多数厂商都会精简设计,比如STM32就只选择了4位作为优先级,共只有16级优先级。如下图示:
在这里插入图片描述
Cortex-M处理器还把256个优先级按位分为高低两段:抢占优先级(分组优先级)和亚优先级(子优先级),通过NVIC中的AIRCR寄存器的PRIGROUP(优先级分组)位段来配置分组。下图即为抢占优先级和亚优先级的表达,以及位数和PRIGROUP分组的关系:
在这里插入图片描述
上面提到STM32只使用了4位,因此STM32最多只有5组优先级分组设置。而移植FreeRTOS到STM32时,一般都是配置组4,也就是4位优先级全都是抢占优先级了,没有亚优先级,因此就有0~15共16个优先级。

在STM32上移植FreeRTOS还需要重点关注PRIMASK、FAULTMASK和BASEPRI这三个寄存器,这三个寄存器的说明见下表。FreeRTOS的开关中断是操作BASEPRI寄存器来实现的,它可以关闭低于某个阈值的中断,高于这个阈值的中断则不会被关闭
在这里插入图片描述

1.2 中断相关函数
  • 关闭中断
/* 关闭中断 */
void taskDISABLE_INTERRUPTS(void)
//只能关掉优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断
//此函数不允许嵌套
/* 源码分析 */
#define portDISABLE_INTERRUPTS()	vPortRaiseBASEPRI()
static portFORCE_INLINE void vPortRaiseBASEPRI(void)
{	/*vPortRaiseBASEPRI()是向寄存器BASEPRI写入宏configMAX_SYSCALL_INTERRUPT_PRIORITY
	**表示优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断会被屏蔽*/
	uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
    __asm
    {
    	msr basepri, ulNewBASEPRI
        dsb
        isb
    }
}
  • 打开中断
/* 打开中断 */
void taskENABLE_INTERRUPTS (void)
//此函数不允许嵌套
/* 源码分析 */
#define portENABLE_INTERRUPTS()		vPortSetBASEPRI( 0 )
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{	//vPortSetBASEPRI()是向BASEPRI寄存器写入一个值		
    __asm
    {
    	msr basepri, ulBASEPRI
    }
}

2. 临界段

2.1 临界段的定义

代码的临界段也称为临界区,是指那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。为确保临界段代码的执行不被中断,在进入临界段之前须关中断,而临界段代码执行完毕后,要立即打开中断

在这里插入图片描述
不想被打断访问的资源有哪些:

  • 读取或者修改变量(全局变量)
  • 调用公共函数的代码(不可重入函数)
  • 使用硬件资源(外设)
  • 对时序有精准要求的操作
  • 用户不想被打断的代码
2.2 临界段相关函数
  • 进入/退出临界段:任务级临界段代码保护
/*********** 进入临界段 ***********/
函数原型:void taskENTER_CRITICAL(void)
///
/* 源码分析 */
#define taskENTER_CRITICAL()    portENTER_CRITICAL()
#define portENTER_CRITICAL()	vPortEnterCritical()
void vPortEnterCritical( void )
{	
    portDISABLE_INTERRUPTS();	//关闭中断
    uxCriticalNesting++;	//记录临界段嵌套次数
    if( uxCriticalNesting == 1 )
    {
        configASSERT((portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK) == 0);
    }
}
/*********** 退出临界段 ***********/
函数原型:void taskEXIT_CRITICAL(void)
///
/* 源码分析 */
#define taskEXIT_CRITICAL()		portEXIT_CRITICAL()
#define portEXIT_CRITICAL()     vPortExitCritical()
void vPortExitCritical( void )
{	
    configASSERT( uxCriticalNesting );
    uxCriticalNesting--;			//记录临界段嵌套次数
    if( uxCriticalNesting == 0 )	
    {
        portENABLE_INTERRUPTS();	//打开中断
    }
}
  • 进入/退出临界段:中断级临界段代码保护
/*********** 进入临界段 ***********/
函数原型:UBaseType_t taskENTER_CRITICAL_FROM_ISR(void)
返 回 值:返回上次中断屏蔽寄存器操作值
///
/* 源码分析 */
#define taskENTER_CRITICAL_FROM_ISR() 		portSET_INTERRUPT_MASK_FROM_ISR()
#define portSET_INTERRUPT_MASK_FROM_ISR()	ulPortRaiseBASEPRI()
static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
{	
	uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
    __asm
    {
        mrs ulReturn, basepri		//读出BASEPRI的值,保存在ulReturn中
        msr basepri, ulNewBASEPRI	//将ulNewBASEPRI的值写入到BASEPRI寄存器中
        dsb
        isb
    }
    return ulReturn;				//返回ulReturn,退出临界区代码保护时要使用
}
/*********** 退出临界段 ***********/
函数原型:void taskENTER_CRITICAL_FROM_ISR(UBaseType_t uxSavedInterruptStatus)
传 入 值:传入上次中断屏蔽寄存器操作值
///
/* 源码分析 */
#define taskEXIT_CRITICAL_FROM_ISR(x)	portCLEAR_INTERRUPT_MASK_FROM_ISR(x)
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortSetBASEPRI(x)
static portFORCE_INLINE void vPortSetBASEPRI(uint32_t ulBASEPRI)
{	
	__asm
    {
        msr basepri, ulBASEPRI	//将进入临界区时的返回值,传入BASEPRI寄存器
    }
}

在这里插入图片描述

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

FreeRTOS系列|中断管理和临界段 的相关文章

  • FreeRTOS例程4-串口DMA收发不定长数据

    FreeRTOS例程4 串口DMA收发不定长数据 知乎 zhihu com
  • FreeRTOS config开始的宏

    FreeRTOSConfig h系统配置文件中可以自定义 FreeRTOS h中定义默认值 configAPPLICATION ALLOCATED HEAP 默认情况下FreeRTOS的堆内存是由编译器来分配的 将宏configAPPLIC
  • 【FreeRTOS 信号量】互斥信号量

    互斥信号量与二值信号量类似 但是互斥信号量可以解决二值信号量出现的优先级翻转问题 解决办法就是优先级继承 普通互斥信号量创建及运行 参阅安富莱电子demo 互斥信号量句柄 static SemaphoreHandle t xMutex NU
  • STM32CubeMX+FreeRTOS学习笔记(一)

    嵌入式实时操作系统FreeRTOS 基本概述 在嵌入式领域当中 实时操作系统的应用越来越广泛了 目前嵌入式操作系统种类很多 例如 Clinux C OS II C OS III FreeRTOS RT Thread等等 这篇文章所记录的就是
  • 解决错误“ #error “include FreeRTOS.h“ must appear in source files before “include event_groups.““例子分享

    今天来给大家分享一下 关于之前自己在学习FreeRTOS过程中遇到的一个错误提示 话不多说 我们直接来看 错误分析 首先 我们看一下错误的提示 error 35 error directive include FreeRTOS h must
  • FreeRTOS学习(八) 延时函数

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 FreeRTOS延时函数有两个 分别是 vTaskDelay vTaskDelayUntil 1 vTaskDelay 任务相对延时 函数原型
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • stm32f103zet6移植标准库的sdio驱动

    sdio移植 st官网给的标准库有给一个用于st出的评估板的sdio外设实现 但一是文件结构有点复杂 二是相比于国内正点原子和野火的板子也有点不同 因此还是需要移植下才能使用 当然也可以直接使用正点原子或野火提供的实例 但为了熟悉下sdio
  • FreeRTOS之事件

    FreeRTOS之事件 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 一 事件定义 事件 事件集 与高数上的集合意义差不多 事件啊 其实是实现任务间通信的机制 主要用于实现多任务间的同步 但是事件类型
  • 啊哈C的简单使用

    打开啊哈C 新建一个程序输出hello world include
  • FreeRTOS学习笔记(8)---- 软件定时器

    使用FreeRTOS软件定时器需要在文件FreeRTOSConfig h先做如下配置 1 configUSE TIMERS 使能软件定时器 2 configTIMER TASK PRIORITY 定时器任务优先级 3 configTIMER
  • FreeRTOS死机原因

    1 中断回调函数中没有使用中断级API xxFromISR 函数 xSemaphoreGiveFromISR uart busy HighterTask 正确 xSemaphoreGive uart busy 错误 2 比configMAX
  • 【FreeRTOS 事件】任务通知事件

    普通任务通知事件创建创建及运行 参阅安富莱电子demo define BIT 0 1 lt lt 0 define BIT 1 1 lt lt 1 static TaskHandle t xHandleTaskUserIF NULL sta
  • freeRTOS出现任务卡死的情况。

    最近在做一个产品二代升级的项目 代码是上一任工程师留下的 很多BUG 而且融合了HAL库和LL库 以及github上下载的GSM源码 很不好用 我这边是将2G模块换成了4G 且添加了单独的BLE模块 因此只在源码的基础上 去除2G和BLE代
  • 13-FreeRTOS任务创建与删除

    任务创建和删除API函数位于文件task c中 需要包含task h头文件 task h里面包函数任务的类型函数 例如 对xTaskCreate的调用 通过指针方式 返回一个TaskHandle t 变量 然后可将该变量用vTaskDele
  • 再论FreeRTOS中的configTOTAL_HEAP_SIZE

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

    我使用的是带有 5 4 版 FreeRTOS 的 MSP430f5438 我有一个有趣的问题 我无法弄清楚 基本上 当我将 configTICK RATE HZ 设置为不同的值时 LED 闪烁得更快或更慢 它应该保持相同的速率 我将 con
  • 使用 GCC 编译器的 ARM 内核的堆栈回溯(当存在 MSP 到 PSP 切换时)

    核心 ARM Cortex M4 编译器 GCC 5 3 0 ARM EABI 操作系统 免费 RTOS 我正在使用 gcc 库函数 Unwind Reason Code Unwind Backtrace Unwind Trace Fn v
  • 有关 CMake 错误的问题:没有为目标提供源

    我正在尝试使用 cmake 和 eclipse 将 FreeRtos 添加到我的项目中 但出现错误 我运行的是 debian 10 我的 cmake 版本是 3 13 4 cmake 的文件可以在以下位置找到这个 git 仓库 https

随机推荐

  • 从零完成slam实战,以Vins-Fusion为例

    写在前面 1 本文以vins fusion为例 xff0c 是因为其框架正统 简单清晰 xff0c 易于调试和后续改进 xff1b camera imu外参及同步时间td可实时估计 xff1b 已有融合gps方案且较为容易可添加融合其它传感
  • Vins-Fusion整体框架,数据流分析

    一 VINS Fusion VINS Fusion是一种基于优化的多传感器状态估计器 xff0c 可实现自主应用 xff08 无人机 汽车和AR VR xff09 的精确自我定位 VINS Fusion是VINS Mono的扩展 xff0c
  • Vins-Fusion初始化位姿——3D-2D:PNP求解当前帧位姿

    继上一篇博文Vins Fusion 外参camera imu 标定 xff0c 本文继续介绍Vins Fusion初始化时 xff0c 通过PNP求解当前帧位姿 一 3D 2D xff1a PNP PnP是求解3D到2D点对运动的估计 xf
  • ORB_SLAM3启动流程以stereo_inertial_realsense_D435i为例

    概述 ORB SLAM3 是第一个同时具备纯视觉 xff08 visual xff09 数据处理 视觉 43 惯性 xff08 visual inertial xff09 数据处理 和构建多地图 xff08 multi map xff09
  • BoW(词袋)模型详细介绍

    最近学习BoW模型 xff0c 将自己网上看到的资料及对论文的理解 xff0c 将BoW模型总结如下 xff01 BoW模型 Bag of words model BoW model 最早出现在自然语言处理 xff08 Natural La
  • Win10 VS Code + CMake STM32开发环境

    Win10 VS Code 43 CMake STM32开发环境 软件 软件安装与环境变量的配置不多讲 xff0c 这步都搞不定还是老老实实用MDK把 VS Codecmake 插件 c c 43 43 插件mingwgcc arm non
  • makefile 转 cmake STM32工程

    makefile 转 cmake STM32工程 STM32开发由MDK转到 vscode好久了 每次新建工程 xff0c stm32cubemx生成代码都要手动把makefile转到cmake xff0c 好烦 xff0c 特别一下小的频
  • STM32使用FreeRtos + C++

    编译环境 MDK5 25 gcc arm7 2 C文件不可包含CPP的头文件 C调用C 43 43 函数 在CPP文件内编写C函数 xff0c 头文件声明 头文件不可出现C 43 43 关键字 在main中调用此函数作为程序入口即可 voi
  • FreeRTOS系列|时间管理

    FreeRTOS时间管理 1 FreeRTOS延时函数 在使用FreeRTOS的过程中经常会在一个任务中使用延时函数对该任务延时 xff0c 当执行延时函数的时候就会进行任务切换 xff0c 并且此任务就会进入阻塞态 xff0c 直到延时完
  • 【Linux C与C++一线开发实践】之一 Linux概述与Linux C++开发

    Linux系统启动的基本过程 对于一台Linux系统来说 xff0c 用户按下开机按钮后 xff0c 一共要经历如下几个过程
  • 【Linux C与C++一线开发实践】之三 Linux多进程

    进程是操作系统结构的基础 进程是一个具有独立功能的程序对某个数据集在处理机上的执行过程 xff0c 进程也是作为资源分配的一个基本单位 Linux作为一个多用户 多任务的操作系统 xff0c 必定支持多进程 多进程是现代操作系统的基本特征
  • C++--结构体和类

    结构体和类只有一个区别就是前者访问控制默认为public xff0c 而类的默认访问控制是private 而对于public private protected的访问控制都是在编译期间由编译器检查的 xff0c 编译通过后 xff0c 程序
  • 嵌入式开发工程师面试题 – C语言部分

    嵌入式开发工程师面试题 C语言部分 申明 xff1a 来源于嵌入式开发工程师面试题 C语言部分 和 网摘 xff09 xff01 1 内核的裁剪怎么裁剪 解析 xff1a 在linux 下的ubuntu 上面做内核的 裁剪 xff0c 主要
  • 协方差与自相关

    协方差矩阵是一个矩阵 xff0c 其每个元素是各个向量元素之间的协方差 这是从标量随机变量 到高维度随机向量 的自然推广 假设是以个标量随机变量组成的列向量 xff0c 并且是其第i个元素的期望值 xff0c 即 协方差矩阵被定义的第i x
  • 基础解系

    基础解系首先是线性无关的 xff0c 简单的理解就是能够用它的线性组合表示出该 方程组的任意一组解 xff0c 基础解系是针对有无数多组解的方程而言 xff0c 若是齐次线性方程组则应是有效方程组的个数少于未知数的个数 xff0c 若非齐次
  • 机器学习实践指南:案例应用解析(第二版)

    试读及购买链接 机器学习实践指南2版代码及资源 原书中的360网盘链接因为360关闭网盘的原因已经失效 1 https pan baidu com s 1nw37A5N 2 http www hzbook com Books 9324 ht
  • 数学之路-python计算实战(7)-机器视觉-图像产生加性零均值高斯噪声

    图像产生加性零均值高斯噪声 xff0c 在灰度图上加上噪声 xff0c 加上噪声的方式是每个点的灰度值加上一个噪声值 xff0c 噪声值的产生方式为Box Muller算法 生成高斯噪声 在计算机模拟中 xff0c 经常需要生成正态分布的数
  • 数学之路-python计算实战(16)-机器视觉-滤波去噪(邻域平均法滤波)

    coding utf 8 code myhaspl 64 myhaspl com 邻域平均法滤波 半径为2 import cv2 import numpy as np fn 61 34 test3 jpg 34 myimg 61 cv2 i
  • R语言与数据模型(1)-平均,方差,中位数,分位数,极差

    1 求平均数 gt x lt c 1 10 20 30 40 50 NA 60 gt xm lt mean x gt xm 1 NA na rm表示允许缺失数据NA gt xm lt mean x na rm 61 TRUE gt xm 1
  • FreeRTOS系列|中断管理和临界段

    FreeRTOS中断管理和临界段 1 中断管理 1 1 中断管理简介 中断是微控制器的一个常见特性 xff0c 中断由硬件产生 xff0c 当中断产生后CPU就会中断当前的流程转而去处理中断服务 xff0c Cortex M内核的MCU提供