FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

2024-09-08 12:36

本文主要是介绍FreeRTOS学习笔记(四)Freertos的中断管理及临界保护,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、Cortex-M 中断管理
    • 1.1 中断优先级分组
    • 1.2 相关寄存器
    • 1.3 相关宏定义
    • 1.4 FreeRTOS 开关中断
  • 二、临界段及其保护
    • 2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )
    • 2.2 taskENTER_CRITICAL_FROM_ISR( ) 和 taskEXIT_CRITICAL_FROM_ISR( )
    • 2.3 任务调度器的挂起及恢复


前言

  本章主要是讲述Freertos的中断管理及临界保护,具体的基础知识不再赘述,可以移步观看裸机开发部分。


一、Cortex-M 中断管理

1.1 中断优先级分组

  Cortex-M利用8位宽的寄存器来处理优先级,但stm32实际上只使用了高四位[7:4],即16级中断优先级。stm32的中断优先级可以分为抢占优先级(高优先级抢占低优先级)和子优先级(数值小先执行)。
中断分组
  由于FreeRTOS 的中断配置没有处理子优先级这种情况,所以只能配置为组 4,即 NVIC_PriorityGroup_4 。此时4 位优先级就都全是抢占优先级了,没有子优先级,那么就有 0~15 共 16 个优先级。

1.2 相关寄存器

  PendSV 和 SysTick 寄存器主要用于中断服务,并且在 FreeRTOS 中扮演了重要的角色,尤其是在任务切换和系统计时方面。这里首先介绍设置PendSV(PRI_14)和SysTick(PRI_15)优先级的两个寄存器。
在这里插入图片描述
  如上图所示,4 个相临的寄存器可以拼成一个32位的寄存器(SHPR1~ SHPR3),因而FreeRTOS 在设置 PendSV 和 SysTick 的中断优先级的时候都是直接操作的地址 0xE000_ED20 + offset。为了保证任务切换不会阻碍其他任务,在 FreeRTOS中 PendSV 和 SysTick 的中断优先级都是最低的!
  接着这里再讲述三个中断屏蔽寄存器。值得注意的是FreeRTOS 的开关中断就是操作 BASEPRI 寄存器来实现的,它可以关闭低于某个阈值的中断,高于这个阈值的中断就不会被关闭。

寄存器描述
PRIMASK禁止除 NMI 和 HardFalut 外的所有异常和中断,置1视为开启
FAULTMASK禁止除 NM 外的所有异常和中断,置1视为开启
BASEPRI最大9bit,只屏蔽优先级低于设置阈值的中断

1.3 相关宏定义

描述
configPRIO_BITS设置 MCU 使用几位优先级
configLIBRARY_LOWEST_INTERRUPT_PRIORITY设置最低优先级
configKERNEL_INTERRUPT_PRIORITY设置内核中断优先级
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY设置 FreeRTOS 系统可管理的最大优先级
configMAX_SYSCALL_INTERRUPT_PRIORITY低于此优先级的中断可以调用 FreeRTOS 的 API 函数,反之则禁止

1.4 FreeRTOS 开关中断

  FreeRTOS 开关中断函数为 portENABLE_INTERRUPTS ()和portDISABLE_INTERRUPTS(),这两个函数其实是宏定义,在 portmacro.h 中有定义,如下:

#define portDISABLE_INTERRUPTS( ) vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS( )  vPortSetBASEPRI(0)

  函数 vPortSetBASEPRI( )是向寄存器 BASEPRI 写入一个值,此值作为参数 ulBASEPRI 传递进来,portENABLE_INTERRUPTS( )是开中断,它传递了个 0 给 vPortSetBASEPRI( ),根据我们前面讲解 BASEPRI 寄存器可知,结果就是开中断。

二、临界段及其保护

  临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,比如有的外设的初始化需要严格的时序,初始化过程中不能被打断。
  FreeRTOS 在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断。FreeRTOS 系统本身就有很多的临界段代码,这些代码都加了临界段代码保护,我们在写自己的用户程序的时候有些地方也需要添加临界段代码保护。

2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )

  这两个函数用于进入和退出临界区,在任务上下文中使用。它们通过禁用中断来保护临界区中的代码,确保该代码段在执行期间不会被打断。

  • taskENTER_CRITICAL( ):调用此函数后,所有中断都会被禁用,任务调度也会被禁止,这样可以确保当前任务在执行关键代码时不会被其他任务抢占或中断。
  • taskEXIT_CRITICAL( ):退出临界区时调用该函数,恢复中断和任务调度。必须确保在进入临界区后总是退出,以防止系统卡死或影响其他任务。
// 示例
void start_task(void *pvParameters)
{taskENTER_CRITICAL();  // 禁用中断,进入临界区...				   // 关键代码taskEXIT_CRITICAL();   // 重新启用中断,退出临界区
}

2.2 taskENTER_CRITICAL_FROM_ISR( ) 和 taskEXIT_CRITICAL_FROM_ISR( )

  这两个函数是在中断服务程序(ISR)中使用的版本,与任务上下文中的函数不同,这些函数可以确保临界区在中断中安全运行。除此之外,这个中断的优先级一定要低于前面提到的configMAX_SYSCALL_INTERRUPT_PRIORITY。

  • taskENTER_CRITICAL_FROM_ISR( ):与 taskENTER_CRITICAL() 类似,它也会禁用中断,但是该函数会返回一个变量,指示中断的先前状态,以便在退出临界区时恢复到正确的状态。
  • taskEXIT_CRITICAL_FROM_ISR( ):退出临界区时使用,需要传入先前的中断状态来恢复中断。
// 示例
UBaseType_t uxSavedInterruptStatus;	// FreeRTOS 中用于保存中断状态的变量
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();// 保存中断状态并进入临界区...											   // ISR 中的关键代码
taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);// 退出临界区并恢复中断状态

2.3 任务调度器的挂起及恢复

  任务调度器的挂起和恢复常用于需要确保一段代码在不被其他任务打断的情况下执行,比如同时修改多个任务的优先级或共享资源。值得注意的是,调度器的挂起和恢复会影响整个系统,不管有多少任务,它都会停止任务的切换行为,而我们前面提到的任务挂起和恢复仅影响指定的任务。
  此外,与临界区不同的是任务调度器的挂起不会影响中断,它仅仅是防止任务之间相互抢占资源。适用于临界区位于任务和任务之间,可以做到既不采用延时,也可以保护临界段。

函数描述
vTaskSuspendAll( )暂停整个任务调度器的运行
xTaskResumeAll( )恢复任务调度器,重新允许任务切换

免责声明:本文参考了网上公开资料,仅用于学习交流,若有错误或侵权请联系笔者。

这篇关于FreeRTOS学习笔记(四)Freertos的中断管理及临界保护的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1148123

相关文章

Go学习记录之runtime包深入解析

《Go学习记录之runtime包深入解析》Go语言runtime包管理运行时环境,涵盖goroutine调度、内存分配、垃圾回收、类型信息等核心功能,:本文主要介绍Go学习记录之runtime包的... 目录前言:一、runtime包内容学习1、作用:① Goroutine和并发控制:② 垃圾回收:③ 栈和

Python中bisect_left 函数实现高效插入与有序列表管理

《Python中bisect_left函数实现高效插入与有序列表管理》Python的bisect_left函数通过二分查找高效定位有序列表插入位置,与bisect_right的区别在于处理重复元素时... 目录一、bisect_left 基本介绍1.1 函数定义1.2 核心功能二、bisect_left 与

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

Spring中管理bean对象的方式(专业级说明)

《Spring中管理bean对象的方式(专业级说明)》在Spring框架中,Bean的管理是核心功能,主要通过IoC(控制反转)容器实现,下面给大家介绍Spring中管理bean对象的方式,感兴趣的朋... 目录1.Bean的声明与注册1.1 基于XML配置1.2 基于注解(主流方式)1.3 基于Java

基于Python+PyQt5打造一个跨平台Emoji表情管理神器

《基于Python+PyQt5打造一个跨平台Emoji表情管理神器》在当今数字化社交时代,Emoji已成为全球通用的视觉语言,本文主要为大家详细介绍了如何使用Python和PyQt5开发一个功能全面的... 目录概述功能特性1. 全量Emoji集合2. 智能搜索系统3. 高效交互设计4. 现代化UI展示效果

Mysql中的用户管理实践

《Mysql中的用户管理实践》:本文主要介绍Mysql中的用户管理实践,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录13. 用户管理13.1 用户 13.1.1 用户信息 13.1.2 创建用户 13.1.3 删除用户 13.1.4 修改用户

linux服务之NIS账户管理服务方式

《linux服务之NIS账户管理服务方式》:本文主要介绍linux服务之NIS账户管理服务方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、所需要的软件二、服务器配置1、安装 NIS 服务2、设定 NIS 的域名 (NIS domain name)3、修改主

浅析Java如何保护敏感数据

《浅析Java如何保护敏感数据》在当今数字化时代,数据安全成为了软件开发中至关重要的课题,本文将深入探讨Java安全领域,聚焦于敏感数据保护的策略与实践,感兴趣的小伙伴可以了解下... 目录一、Java 安全的重要性二、敏感数据加密技术(一)对称加密(二)非对称加密三、敏感数据的访问控制(一)基于角色的访问

重新对Java的类加载器的学习方式

《重新对Java的类加载器的学习方式》:本文主要介绍重新对Java的类加载器的学习方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、简介1.2、符号引用和直接引用1、符号引用2、直接引用3、符号转直接的过程2、加载流程3、类加载的分类3.1、显示

Python+PyQt5开发一个Windows电脑启动项管理神器

《Python+PyQt5开发一个Windows电脑启动项管理神器》:本文主要介绍如何使用PyQt5开发一款颜值与功能并存的Windows启动项管理工具,不仅能查看/删除现有启动项,还能智能添加新... 目录开篇:为什么我们需要启动项管理工具功能全景图核心技术解析1. Windows注册表操作2. 启动文件