Freertos—中断+临界区
一、学习资料
Freertos临界区和开关中断:
https://www.cnblogs.com/yangguang-it/p/7161486.html
https://blog.csdn.net/LiaRonBob/article/details/105083306
二、临界区概念
临界区其实就是一段在执行的时候不能被中断的代码段
临界区函数:进入临界区taskENTER_CRITICAL(); 和退出临界区taskEXIT_CRITICAL();
具体函数定义有两种:
1、不带版本保护,不能嵌套
进入临界区:

1 void vPortEnterCritical(void) 2 { 3 4 /* Mask interrupts up to the max syscall interrupt priority. */ 5 6 ulPortSetInterruptMask(); 7 8 /* Now interrupts are disabled ulCriticalNesting can be accessed 9 10 directly. Increment ulCriticalNesting to keep a count of how many times 11 12 portENTER_CRITICAL() has been called. */ 13 14 ulCriticalNesting++; 15 16 /* This is not the interrupt safe version of the enter critical function so 17 18 assert() if it is being called from an interrupt context. Only API 19 20 functions that end in "FromISR" can be used in an interrupt. Only assert if 21 22 the critical nesting count is 1 to protect against recursive calls if the 23 24 assert function also uses a critical section. */ 25 26 if (ulCriticalNesting == 1) { 27 28 configASSERT(ulPortInterruptNesting == 0); 29 30 } 31 }
退出临界区:

1 void vPortExitCritical(void) 2 3 { 4 5 if (ulCriticalNesting > portNO_CRITICAL_NESTING) { 6 7 /* Decrement the nesting count as the critical section is being 8 9 exited. */ 10 11 ulCriticalNesting--; 12 13 /* If the nesting level has reached zero then all interrupt 14 15 priorities must be re-enabled. */ 16 17 if (ulCriticalNesting == portNO_CRITICAL_NESTING) { 18 19 /* Critical nesting has reached zero so all interrupt priorities 20 21 should be unmasked. */ 22 23 portCLEAR_INTERRUPT_MASK(); 24 25 } 26 27 } 28 29 }
2、带版本保护,可以嵌套

1 #define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() 2 3 /* 在 portmacro.h 中定义 */ 4 5 #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() 6 7 /* 在 portmacro.h 中定义 */ 8 9 static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void ) 10 11 { 12 13 uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; 14 15 __asm 16 17 { 18 19 mrs ulReturn, basepri 20 21 msr basepri, ulNewBASEPRI 22 23 dsb 24 25 isb 26 27 } 28 29 return ulReturn; 30 31 }
三、中断
Freertos的临界区被打断的情况分两种,一种是系统调度,另外一种是外部中断。其实系统
调度最终也是通过中断来实现的,也可以归结为中断。因此临界区保护其实就是对中断的开关控制。
FreeRTOS关中断的函数在portmacro.h中定义,分不带返回值和带返回值两种.
不带返回值的关中断函数
1、不带返回值的关中断函数,不能嵌套,不能在中断里面使用。不带返回值的意思是:在往 BASEPRI写入新的值的时候,不用先将BASEPRI的值保存起来,即不用管当前的中断状态是怎么样的,既然不用管当前的中断状态,也就意味着这样的函数不能在中断里面调用
2、configMAX_SYSCALL_INTERRUPT_PRIORITY是一个在FreeRtOSConfig.h中定义的宏,即要写入到BASEPRI寄存器的值。该宏默认定义为191,高四位有效,即等于0xb0,或者是11,即优先级大于等于11的中断都会被屏蔽,11以内的中断则不受FreeRTOS管理(数值越小,优先级越高)。
3、将configMAX_SYSCALL_INTERRUPT_PRIORITY的值写入BASEPRI寄存器,实现关中断(准确来说是关部分中断).
不带返回值的关中断函数
1、带返回值的关中断函数,可以嵌套,可以在中断里面使用。带返回值的意思是:在往 BASEPRI写入新的值的时候,先将BASEPRI的值保存起来,在更新完BASEPRI的值的时候,将之前保存好的
BASEPRI的值返回,返回的值作为形参传入开中断函数
2、configMAX_SYSCALL_INTERRUPT_PRIORITY是一个在FreeRTOSConfig.h中定义的宏,即要写入到BASEPRI寄存器的值。该宏默认定义为191,高四位有效,即等于0xb0,或者是11,即优先级大于等于11的中断都会被屏蔽,11以内的中断则不受FreeRTOS管理。
3、保存BASEPRI的值,记录当前哪些中断被关闭
4、返回原来BASEPRI的值
3、开中断
FreeRTOS开中断的函数在portmacro.h中定义
2022-03-22
本文来自博客园,作者:追随技术,转载请注明原文链接:https://www.cnblogs.com/545235abc/p/16170069.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)