Freertos—中断+临界区

一、学习资料

Freertos临界区和开关中断:

https://www.cnblogs.com/yangguang-it/p/7161486.html

https://blog.csdn.net/LiaRonBob/article/details/105083306

二、临界区概念

临界区其实就是一段在执行的时候不能被中断的代码段

临界区函数:进入临界区taskENTER_CRITICAL(); 和退出临界区taskEXIT_CRITICAL();

具体函数定义有两种:

【FreeRTOS】FreeRTOS学习笔记(6)— 中断+临界区的保护_系统调度_07

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 } 
View Code
复制代码

退出临界区:

复制代码
 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 }
View Code
复制代码

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 }
View Code
复制代码

三、中断

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寄存器,实现关中断(准确来说是关部分中断).

【FreeRTOS】FreeRTOS学习笔记(6)— 中断+临界区的保护_临界区_03

【FreeRTOS】FreeRTOS学习笔记(6)— 中断+临界区的保护_系统调度

【FreeRTOS】FreeRTOS学习笔记(6)— 中断+临界区的保护_系统调度_02

不带返回值的关中断函数

【FreeRTOS】FreeRTOS学习笔记(6)— 中断+临界区的保护_寄存器_04

【FreeRTOS】FreeRTOS学习笔记(6)— 中断+临界区的保护_临界区_05

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中定义

【FreeRTOS】FreeRTOS学习笔记(6)— 中断+临界区的保护_寄存器_06

2022-03-22

posted @   追随技术  阅读(714)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示