本文描述的是FreeRTOS如何处理任务与任务之间争夺临界资源,以及任务与中断之间争夺临界资源的方法。
解决主要思路:
- 对于任务与任务之间,思路为关闭任务调度,这样就可以防止其他任务来抢占临界资源。
- 对于任务与中断之间,思路为关闭中断,这样可以防止中断打断任务,中断打断中断的情况。因为任务不能打断中断,所以不用关闭任务调度。
暂停/恢复调度器函数
函数声明如下:
/* 暂停调度 */
void vTaskSuspendAll( void )
/* 恢复调度 */
BaseType_t xTaskResumeAll( void )
具体代码使用方法如下:
int g_a;/* 临界资源 */
void fun(){
/* 暂停调度 */
void vTaskSuspendAll( void )
/* 访问临界资源 */
g_a++;
/* 恢复调度 */
BaseType_t xTaskResumeAll( void )
}
屏蔽中断函数
在FreeRTOS中,中断优先级为0~190的中断不调用syscall,191~255的中断调用syscall。屏蔽中断实际上是屏蔽的中断优先级191~255的全部中断。
因为屏蔽中断函数不能够屏蔽优先级为0~190的中断,因此编写优先级为0~190的中断的中断处理函数时,不能够使用临界资源。这是一种约定。
函数声明如下:
/* 任务中屏蔽、使能中断 */
taskENTER_CRITICAL() /* 屏蔽 */
taskEXIT_CRITICAL() /* 使能 */
/* 中断中屏蔽、恢复中断 */
taskENTER_CRITICAL_FROM_ISR() /* 屏蔽,有一个返回值,表示屏蔽前的全部中断状态 */
taskEXIT_CRITICAL_FROM_ISR(x) /* 恢复,参数为屏蔽的返回值,将全部中断状态恢复原样 */
任务恢复与任务使能的区别:
- 中断中称为恢复中断,因为在屏蔽中断之前,中断状态可能为开启或禁止,之后应该恢复成原来的状态,而不一定为开启状态。
- 任务中称为使能中断,因为在屏蔽中断之前,一定为开启状态,屏蔽之后把中断给关了,之后应该再开启中断,因此叫使能。
任务中屏蔽中断代码如下:
/* 任务中屏蔽中断 */
void Task(void* param){
/* 屏蔽中断 */
taskENTER_CRITICAL();
/* 访问临界资源代码 */
/* 使能中断 */
taskEXIT_CRITICAL();
}
中断中屏蔽中断代码如下:
/* 中断中屏蔽中断 */
void xxx_IRQHandler(){
/* 定义变量,保存中断状态 */
UBaseType_t uxSavedInterruptStatus;
/* 屏蔽中断 */
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
/* 访问临界资源 */
/* 恢复中断 */
taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
}