(1)在前面介绍互斥量时,我们已知临界资源的概念,通过互斥量可以实现临界资源的互斥访问。
(2)本文介绍两个功能:屏蔽/使能中断、暂停/恢复调度器。
(3)要独占式地访问临界资源,有3种方法:
屏蔽中断有两套宏:在任务中使用、在ISR中使用:
(1)在任务中屏蔽中断地示例代码如下:
/* 在任务中,当前时刻中断是使能的
* 执行这句代码后,屏蔽中断
*/
taskENTER_CRITICAL();
/* 访问临界资源 */
/* 重新使能中断 */
taskEXIT_CRITICAL();
(2)在 taskENTER_CRITICA() / taskEXIT_CRITICAL() 之间:
(3)这套 taskENTER_CRITICA() / taskEXIT_CRITICAL() 宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用 taskEXIT_CRITICAL() 才会重新使能中断。
(4)使用 taskENTER_CRITICA() / taskEXIT_CRITICAL() 来访问临界资源是很粗鲁的方法:
(1)要使用含有"FROM_ISR"后缀的宏,示例代码如下:
void vAnInterruptServiceRoutine( void )
{
/* 用来记录当前中断是否使能 */
UBaseType_t uxSavedInterruptStatus;
/* 在ISR中,当前时刻中断可能是使能的,也可能是禁止的
* 所以要记录当前状态, 后面要恢复为原先的状态
* 执行这句代码后,屏蔽中断
*/
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
/* 访问临界资源 */
/* 恢复中断状态 */
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
/* 现在,当前ISR可以被更高优先级的中断打断了 */
}
(2)在 taskENTER_CRITICA_FROM_ISR() / taskEXIT_CRITICAL_FROM_ISR() 之间:
(1)如果有别的任务来跟你竞争临界资源,你可以把中断关掉:这当然可以禁止别的任务运行,但是这代价太大了,它会影响到中断的处理。
(2)如果只是禁止别的任务来跟你竞争,不需要关中断,暂停调度器就可以了:在这期间,中断还是可以发生处理。
(3)使用这2个函数来暂停、恢复调度器:
/* 暂停调度器 */
void vTaskSuspendAll( void );
/* 恢复调度器
* 返回值: pdTRUE表示在暂定期间有更高优先级的任务就绪了
* 可以不理会这个返回值
*/
BaseType_t xTaskResumeAll( void );
(4)示例代码如下:
int a;
void xxx_func(int val)
{
vTaskSuspendAll();
/* 访问临界资源 */
a = val;
xTaskResumeAll();
}
(5)这套 vTaskSuspendAll() / xTaskResumeAll()
宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,xTaskResumeAll()
才会重新使能调度器。
?
?