FreeRTOS
文章目录
- FreeRTOS
- 五、临界段代码保护
- 临界段代码保护函数
- 任务级进入临界段
- 任务级退出临界段
- 中断级进入临界段
- 中断级退出临界段
- 任务调度器的挂起和恢复
- 挂起任务调度器
- 恢复任务调度器
- 挂起任务调度器
- 恢复任务调度器
五、临界段代码保护
临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段
为什么程序会被打断?因为在freeRTOS中任务与任务之间是通过任务调度器实现并发执行的
什么可以打断当前任务的执行?中断,任务调度
需要应用临界区的场合
- IIC,SPI需要严格按照时序的任务
- 创建任务的任务,该任务通常不能被打断
临界段代码保护函数
任务级进入临界段
taskENTER_CRITICAL()
套了两层宏
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();//关闭中断
uxCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */
if( uxCriticalNesting == 1 )
{
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
}
}
任务级退出临界段
taskEXIT_CRITICAL()
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
调用格式
taskENTER_CRITICAL() ;
{
/* 临界区 */
}
taskEXIT_CRITICAL() ;
中断级进入临界段
taskENTER_CRITICAL_FROM_ISR()
中断级退出临界段
taskEXIT_CRITICAL_FROM_ISR()
调用格式
uint32_t save_status;
save_status = taskENTER_CRITICAL_FROM_ISR();
{
/* 临界区 */
}
taskEXIT_CRITICAL_FROM_ISR(save_status );
- 成对使用
- 支持嵌套
- 尽量保持临界段耗时短
任务调度器的挂起和恢复
挂起任务调度器, 调用此函数不需要关闭中断
挂起任务调度器
vTaskSuspendAll()
调用一次挂起调度器,该变量uxSchedulerSuspended就加一 ,变量uxSchedulerSuspended的值,将会影响Systick触发PendSV中断,即影响任务调度
恢复任务调度器
xTaskResumeAll()
调用一次恢复调度器,该变量uxSchedulerSuspended就减一
如果等于0,则允许调度
1、将所有在xPendingReadyList中的任务移到对应的就绪链表中
2、移除等待就绪列表中的列表项,恢复至就绪列表,直到xPendingReadyList列表为
空
- 与临界区不一样的是,挂起任务调度器,未关闭中断;
- 它仅仅是防止了任务之间的资源争夺,中断照样可以直接响应;
- 挂起调度器的方式,适用于临界区位于任务与任务之间;既不用去延时中断,又可以做到临界区的安全
闭中断
挂起任务调度器
vTaskSuspendAll()
调用一次挂起调度器,该变量uxSchedulerSuspended就加一 ,变量uxSchedulerSuspended的值,将会影响Systick触发PendSV中断,即影响任务调度
恢复任务调度器
xTaskResumeAll()
调用一次恢复调度器,该变量uxSchedulerSuspended就减一
如果等于0,则允许调度
1、将所有在xPendingReadyList中的任务移到对应的就绪链表中
2、移除等待就绪列表中的列表项,恢复至就绪列表,直到xPendingReadyList列表为
空
- 与临界区不一样的是,挂起任务调度器,未关闭中断;
- 它仅仅是防止了任务之间的资源争夺,中断照样可以直接响应;
- 挂起调度器的方式,适用于临界区位于任务与任务之间;既不用去延时中断,又可以做到临界区的安全