STM32 FreeRTOS中断管理
目录
FreeRTOS的中断管理
1、STM32中断优先级管理
2、FreeRTOS任务优先级管理
3、寄存器和内存映射寄存器
4、BASEPRI寄存器
5、FreeRTOS与STM32中断管理结合使用
vPortRaiseBASEPRI
vPortSetBASEPRI
6、FromISR后缀
7、在中断服务函数中调用FreeRTOS的API函数需注意
FreeRTOS的临界段代码
1、通过中断管理临界区
1)taskENTER_CRITICAL():进入临界区
2)taskEXIT_CRITICAL():退出临界区
3)taskENTER_CRITICAL_FROM_ISR():进入临界区(中断级)
4)taskEXIT_CRITICAL_FROM_ISR():退出临界区(中断级)
2、通过挂起和恢复任务调度器管理临界区
1)uxSchedulerSuspended
2)vTaskSuspendAll():挂起任务调度器
3)xTaskResumeAll():恢复任务调度器
FreeRTOS的中断管理
1、STM32中断优先级管理
在STM32中,中断优先级是通过中断优先级配置寄存器的高4位 [7:4] 来配置的。因此STM32支持最多16级中断优先级,其中数值越小表示优先级越高,即更紧急的中断。
2、FreeRTOS任务优先级管理
FreeRTOS任务调度的优先级相反,数值越大越优先。任务优先级的最大值由FreeRTOSConfig.h中的配置项configMAX_PRIORITIES决定,默认为5,如下。
#define configMAX_PRIORITIES ( 5 )
该配置项在当前环境下不能大于32,否则编译报错,如下。
#if ( configMAX_PRIORITIES > 32 )#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
因此,可以得出结论,在当前配置下,FreeRTOS的任务最多可以有32个优先级。
优先级范围[0, configMAX_PRIORITIES),即最大优先级为configMAX_PRIORITIES-1。
3、寄存器和内存映射寄存器
这里的寄存器不同于STM32的外设寄存器,后者是内存映射寄存器,实际上是在内存中划分特定的地址空间,用于访问和控制外设的功能。而此处的寄存器是Cortex-M3内核中“真正的”寄存器,基于SR锁存器构建。
4、BASEPRI寄存器
BASEPRI寄存器即Base Priority Mask Register(基本优先级屏蔽寄存器)。顾名思义,该寄存器是用来屏蔽中断响应的,位定义如下。
BASEPRI只有bit7-bit4起作用,当这四位不为0时,会屏蔽优先级数值上大于等于该值的中断响应。如:BASEPRI设置为0x50(只看bit7-bit4,也就是5),代表中断优先级在5~15内的均被屏蔽,0~4的中断优先级正常执行。
当bit7-bit4为0时无效,即不屏蔽任何中断。
5、FreeRTOS与STM32中断管理结合使用
FreeRTOS可以与STM32原生的中断机制结合使用。
FreeRTOS初始化时,PendSV和SysTick被设置最低中断优先级(数值最大,15),保证系统任务切换不会阻塞系统其他中断的响应。
FreeRTOS提供了一组宏定义用于禁用和启用中断,如下。
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
vPortRaiseBASEPRI
vPortRaiseBASEPRI是一个内连汇编函数,如下。
static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;__asm{/* Set BASEPRI to the max syscall priority to effect a critical* section. */
/* *INDENT-OFF* */msr basepri, ulNewBASEPRIdsbisb
/* *INDENT-ON* */}
}
该函数先把configMAX_SYSCALL_INTERRUPT_PRIORITY赋值给ulNewBASEPRI,然后通过msr指令将ulNewBASEPRI的值赋给basepri寄存器。上述过程实际上是将configMAX_SYSCALL_INTERRUPT_PRIORITY配置项的值赋给了basepri寄存器。该配置项在FreeRTOSConfig.h中定义,默认值为191。因为是赋给basepri的,所以只有bit7-bit4有效,因而191等价于0xB0。
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191
该配置项默认值为191,那么,默认情况下,FreeRTOS进入临界区时会屏蔽中断优先级数值上大于等于11的中断。我们可以说FreeRTOS管理的最大优先级为11。
在STM32F103ZET6单片机上使用FreeRTOS时,建议将上述配置项设置为较低的优先级值(逻辑上优先级较高),通常是5。需要注意的是,vPortRaiseBASEPRI函数中,会将configMAX_SYSCALL_INTERRUPT_PRIORITY直接赋值给BASEPRI寄存器,而不会进行移位操作,因此,当我们要让FreeRTOS可以管理的最大优先级设置为5时,要确保configMAX_SYSCALL_INTERRUPT_PRIORITY的bit7-bit4为5,通常赋值为0x50。
vPortSetBASEPRI
vPortSetBASEPRI也是一个内联汇编函数,如下。
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{__asm{/* Barrier instructions are not used as this function is only used to* lower the BASEPRI value. */
/* *INDENT-OFF* */msr basepri, ulBASEPRI
/* *INDENT-ON* */}
}
该函数将ulBASEPRI赋值给BASEPRI寄存器。因此,portENABLE_INTERRUPTS()宏的逻辑是将0赋给BASERPI,不再屏蔽任何中断。
6、FromISR后缀
FreeRTOS提供了一组带FromISR后缀的函数,这类函数是对应无后缀API的另一个版本,专门用于在ISR(Interrupt Service Routine,中断服务函数或例程)中调用,相较于无后缀版本,增加了一些额外操作。
7、在中断服务函数中调用FreeRTOS的API函数需注意
1、中断服务函数的优先级需在FreeRTOS所管理的范围内,阈值由configMAX_SYSCALL_INTERRUPT_PRIORITY指定。
2、建议将所有优先级位指定为抢占优先级位,方便FreeRTOS管理。
3、在中断服务函数里边需调用FreeRTOS的API函数,必须使用带“FromISR”后缀的函数。
FreeRTOS的临界段代码
临界段代码,又称为临界区,指的是那些必须在不被打断的情况下完整运行的代码段。例如,某些外设的初始化可能要求严格的时序,因此在初始化过程中不允许被中断打断。
1、通过中断管理临界区
在FreeRTOS中,临界段代码需要被“临界区进入”和“临界区退出”函数保护起来。临界区的进入和退出可以通过中断来实现,相关函数有 4 个:
1)taskENTER_CRITICAL():进入临界区
void vPortEnterCritical( void )
{portDISABLE_INTERRUPTS();uxCriticalNesting++;/* This is not the interrupt safe version of the enter critical function so* assert() if it is being called from an interrupt context. Only API* functions that end in "FromISR" can be used in an interrupt. Only assert if* the critical nesting count is 1 to protect against recursive calls if the* assert function also uses a critical section. */if( uxCriticalNesting == 1 ){configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );}
}
是通过portDISABLE_INTERRUPTS()宏禁用中断实现的。
2)taskEXIT_CRITICAL():退出临界区
void vPortExitCritical( void )
{configASSERT( uxCriticalNesting );uxCriticalNesting--;if( uxCriticalNesting == 0 ){portENABLE_INTERRUPTS();}
}
是通过调用portENABLE_INTERRUPTS()宏启用中断实现的。
3)taskENTER_CRITICAL_FROM_ISR():进入临界区(中断级)
4)taskEXIT_CRITICAL_FROM_ISR():退出临界区(中断级)
进入和退出临界区是成对使用的。每进入一次临界区,全局变量uxCriticalNesting都会加一,每调用一次退出临界区,uxCriticalNesting减一,只有当 uxCriticalNesting 为 0 时才会调用函数 portENABLE_INTERRUPTS()使能中断。这确保了在存在多个临界区代码的情况下,不会因为某个临界区代码的退出而破坏其他临界区的保护。只有当所有的临界区代码都退出时,中断才会被重新使能。
上文提到,PendSV和SysTick两个中断的优先级在FreeRTOS初始化时都被置为最低优先级15,而这两个中断时FreeRTOS任务切换的核心。因此,在进入临界区时,FreeRTOS无法执行任务切换,保证了临界区操作的原子性。但要注意,优先级高于(数值上低于)配置项configMAX_SYSCALL_INTERRUPT_PRIORITY的中断未被FreeRTOS管理,仍然可以打断任务执行。
2、通过挂起和恢复任务调度器管理临界区
挂起和恢复任务调度器, 调用此函数不需要关闭中断:
1)uxSchedulerSuspended
这是一个全局变量,声明及初始化如下。
PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE;
pdFALSE数值上为0,如下。
#define pdFALSE ( ( BaseType_t ) 0 )
在FreeRTOS中,任务调度器可以被多次挂起,uxSchedulerSuspended用于记录调度器被挂起的次数,只要它不为0,则无法进行任务切换。
2)vTaskSuspendAll():挂起任务调度器
该函数的核心逻辑只有一行,如下。
++uxSchedulerSuspended;
调用该函数后,任务切换被禁止,当前任务的执行不会被其它任务打断,从而保护了临界区代码。
3)xTaskResumeAll():恢复任务调度器
该函数核心逻辑如下。
--uxSchedulerSuspended;if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ){……}
首先将uxSchedulerSuspended减1,而后判断是否为pdFALSE,是则说明所有临界区已退出,可以恢复任务调度,执行相关操作。
vTaskSuspendAll和xTaskResumeAll是成对出现的,临界区可以嵌套,仅在所有临界区全部退出时,才能恢复任务切换。
与中断管理临界区不同的是,挂起任务调度器时未关闭中断;这种方式仅仅防止了任务之间的资源争夺,中断仍然可以直接响应;挂起调度器的方法适用于临界区位于任务与任务之间的情况;这样既不需要延迟中断,同时又能确保临界区的安全性。
相关文章:

STM32 FreeRTOS中断管理
目录 FreeRTOS的中断管理 1、STM32中断优先级管理 2、FreeRTOS任务优先级管理 3、寄存器和内存映射寄存器 4、BASEPRI寄存器 5、FreeRTOS与STM32中断管理结合使用 vPortRaiseBASEPRI vPortSetBASEPRI 6、FromISR后缀 7、在中断服务函数中调用FreeRTOS的API函数需注意 F…...

数据结构-栈和队列
文章目录 一、栈1.概念与结构2.数组栈的实现2.1 栈的结构定义2.2 栈的初始化2.3 栈的销毁2.4 栈的判空2.5 栈的入栈2.6 栈的出栈2.7 查看栈顶元素2.8 栈的大小 3.两种栈的图示结构 二、队列1.概念与结构2.链式队列的实现2.1 队列的结构定义2.2 队列的初始化2.3 队列的销毁2.4 队…...

RabbitMQ---TTL与死信
(一)TTL 1.TTL概念 TTL又叫过期时间 RabbitMQ可以对队列和消息设置TTL,当消息到达过期时间还没有被消费时就会自动删除 注:这里我们说的对队列设置TTL,是对队列上的消息设置TTL并不是对队列本身,不是说队列过期时间…...

第4章 Kafka核心API——Kafka客户端操作
Kafka客户端操作 一. 客户端操作1. AdminClient API 一. 客户端操作 1. AdminClient API...

Python爬虫学习前传 —— Python从安装到学会一站式服务
早上好啊,大佬们。我们的python基础内容的这一篇终于写好了,啪唧啪唧啪唧…… 说实话,这一篇确实写了很久,一方面是在忙其他几个专栏的内容,再加上生活学业上的事儿,确实精力有限,另一方面&…...

Lora理解QLoRA
Parameter-Efficient Fine-Tuning (PEFT) :节约开销的做法,fine-tune少量参数,而不是整个模型; Low-Rank Adaptation (LoRA) :是PEFT的一种;冻结原参数矩阵,只更新2个小参数矩阵。 原文经过对比…...
Linux测试处理fps为30、1920*1080、一分钟的视频性能
前置条件 模拟fps为30、1920*1080、一分钟的视频 项目CMakeLists.txt cmake_minimum_required(VERSION 3.30) project(testOpenGl)set(CMAKE_CXX_STANDARD 11)add_executable(testOpenGl main.cpptestOpenCl.cpptestOpenCl.hTestCpp.cppTestCpp.hTestCppThread.cppTestCppTh…...

Flink (六):DataStream API (三) 窗口
1. 窗口 窗口(Window)是处理无界流的关键所在。窗口可以将数据流装入大小有限的“桶”中,再对每个“桶”加以处理。 下面展示了 Flink 窗口在 keyed streams 和 non-keyed streams 上使用的基本结构。 我们可以看到,这两者唯一的…...
MYSQL学习笔记(二):基本的SELECT语句使用(基本、条件、聚合函数查询)
前言: 学习和使用数据库可以说是程序员必须具备能力,这里将更新关于MYSQL的使用讲解,大概应该会更新30篇,涵盖入门、进阶、高级(一些原理分析);这一篇是讲解SELECT语句使用,包括基本、条件、聚合函数查询,…...

PCL 点到面的ICP算法实现点云配准(C++详细过程版)
ICP算法 一、算法原理1、算法概述2、实现流程3、参考文献二、代码实现三、结果展示四、相关链接一、算法原理 1、算法概述 实现的算法与 PCL 点到面的ICP精配准(线性最小二乘优化)一文相同,使用C++代码复现线性优化的求解过程,求解过程如下所示,由于原版英文文献的计算过…...
MarsCode青训营打卡Day1(2025年1月14日)|稀土掘金-16.最大矩形面积问题
资源引用: 最大矩形面积问题 - MarsCode 打卡小记录: 今天是开营第一天,和小伙伴们组成了8人的团队,在接下来的数十天里相互监督,打卡刷题! 稀土掘金-16.最大矩形面积问题(16.最大矩形面积问题…...
我的世界-与门、或门、非门等基本门电路实现
一、红石比较器 (1) 红石比较器结构 红石比较器有前端单火把、后端双火把以及两个侧端 其中后端和侧端是输入信号,前端是输出信号 (2) 红石比较器的两种模式 比较模式 前端火把未点亮时处于比较模式 侧端>后端 → 0 当任一侧端强度大于后端强度时,输出…...
【FISCO BCOS】二十三、部署WeBASE-Node-Manager
WeBASE-Node-Manager是WeBASE的子组件之一,可以处理前端页面所有web请求,管理各个节点的状态,管理链上所有智能合约,对区块链的数据进行统计、分析,对异常交易的审计,私钥管理等,今天我们来部署WeBASE-Node-Manager。 环境:ubuntu 22 、已搭建单机四节点(节点已启动)…...
app版本控制java后端接口版本管理
java api version 版本控制 java接口版本管理 1 自定义 AppVersionHandleMapping 自定义AppVersionHandleMapping实现RequestMappingHandlerMapping里面的方法 public class AppVersionHandleMapping extends RequestMappingHandlerMapping {Overrideprotected RequestCondit…...

Go语言strings包与字符串操作:从基础到高级的全面解析
Go语言strings包与字符串操作:从基础到高级的全面解析 引言 Go语言以其简洁、高效和强大的标准库而闻名,其中strings包是处理字符串操作的核心工具。本文将深入探讨Go语言中strings包的功能及其在实际开发中的应用,帮助开发者更好地理解和使用这一工具。 1. strings包概述…...

使用redis-cli命令实现redis crud操作
项目场景: 线上环境上redis中的key影响数据展示,需要删除。但环境特殊没办法通过 redis客户端工具直连。只能使用redis-cli命令来实现。 操作步骤: 1、确定redis安装的服务器; 2、找到redis的安装目录下 ##找到redis安装目…...

Ubuntu升级Linux内核教程
本文作者CVE-柠檬i: CVE-柠檬i-CSDN博客 本文使用的方法是dpkg安装,目前版本为5.4.0-204,要升级成5.8.5版本 下载 下载网站:https://kernel.ubuntu.com/mainline/ 在该网站下载deb包,选择自己想要升级的版本,这里是5…...

5、docker-compose和docker-harbor
安装部署docker-compose 自动编排工具,可以根据dockerfile自动化的部署docker容器。是yaml文件格式,注意缩进。 1、安装docker-compose 2、配置compose配置文件docker-compose.yml 3、运行docker-compose.yml -f:指定文件,up&…...
Leetcode3097:或值至少为 K 的最短子数组 II
题目描述: 给你一个 非负 整数数组 nums 和一个整数 k 。 如果一个数组中所有元素的按位或运算 OR 的值 至少 为 k ,那么我们称这个数组是 特别的 。 请你返回 nums 中 最短特别非空 子数组的长度,如果特别子数组不存在,那么返…...

HTML应用指南:利用GET请求获取全国特斯拉充电桩位置
随着电动汽车的普及,充电基础设施的建设变得至关重要。作为电动汽车领域的先驱,特斯拉不仅在车辆技术创新上持续领先,还积极构建广泛的充电网络,以支持其不断增长的用户群体。为了提升用户体验和服务质量,开发人员和数…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

论文笔记——相干体技术在裂缝预测中的应用研究
目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术:基于互相关的相干体技术(Correlation)第二代相干体技术:基于相似的相干体技术(Semblance)基于多道相似的相干体…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...