前言
要独占式地访问临界资源,有3种方法:
- 临界资源的互斥访问
- 屏蔽/使能中断
- 暂停/恢复调度器。
一、屏蔽中断
代码样例
int a;
/* 在任务中,当前时刻中断是使能的
* 执行这句代码后,屏蔽中断
*/
void add_func(int val)
{
taskENTER_CRITICAL();
/* 访问临界资源 */
a += val;
/* 重新使能中断 */
taskEXIT_CRITICAL();
}
这套 taskENTER_CRITICA()/taskEXIT_CRITICAL()
宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用 taskEXIT_CRITICAL()
才会重新使能中断
在
taskENTER_CRITICA()/taskEXIT_CRITICAL()
之间: 低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断被屏蔽了。由于任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生
任务中使用: taskENTER_CRITICAL ()/taskEXIT_CRITICAL()
ISR中使用:taskENTER_CRITICAL_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR()
二、暂停调度器
如果有别的任务来跟你竞争临界资源,你可以把中断关掉,但是这代价太大了,它会影响中断的处理。如果只是禁止别的任务来跟你竞争,不需要关中断,暂停调度器就可以了,在这期间,中断还是可以发生、处理。
代码如下:
int a;
void xxx_func(int val)
{
vTaskSuspendAll();
/* 访问临界资源 */
a = val;
xTaskResumeAll();
}
vTaskSuspendAll()/xTaskResumeAll()
也是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,xTaskResumeAll()
才会重新使能调度器。