STM32H750之FreeRTOS学习--------(五)临界段代码保护

FreeRTOS

文章目录

  • FreeRTOS
      • 五、临界段代码保护
          • 临界段代码保护函数
            • 任务级进入临界段
            • 任务级退出临界段
            • 中断级进入临界段
            • 中断级退出临界段
          • 任务调度器的挂起和恢复
            • 挂起任务调度器
            • 恢复任务调度器
            • 挂起任务调度器
            • 恢复任务调度器

五、临界段代码保护

临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段

为什么程序会被打断?因为在freeRTOS中任务与任务之间是通过任务调度器实现并发执行的

什么可以打断当前任务的执行?中断,任务调度

需要应用临界区的场合

  • IIC,SPI需要严格按照时序的任务
  • 创建任务的任务,该任务通常不能被打断
临界段代码保护函数
任务级进入临界段
taskENTER_CRITICAL()

套了两层宏

image-20231108164511459

image-20231108164559890

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列表为

  1. 与临界区不一样的是,挂起任务调度器,未关闭中断;
  2. 它仅仅是防止了任务之间的资源争夺,中断照样可以直接响应;
  3. 挂起调度器的方式,适用于临界区位于任务与任务之间;既不用去延时中断,又可以做到临界区的安全

闭中断

挂起任务调度器
vTaskSuspendAll()

调用一次挂起调度器,该变量uxSchedulerSuspended就加一 ,变量uxSchedulerSuspended的值,将会影响Systick触发PendSV中断,即影响任务调度

恢复任务调度器
xTaskResumeAll()

调用一次恢复调度器,该变量uxSchedulerSuspended就减一

如果等于0,则允许调度

1、将所有在xPendingReadyList中的任务移到对应的就绪链表中

2、移除等待就绪列表中的列表项,恢复至就绪列表,直到xPendingReadyList列表为

  1. 与临界区不一样的是,挂起任务调度器,未关闭中断;
  2. 它仅仅是防止了任务之间的资源争夺,中断照样可以直接响应;
  3. 挂起调度器的方式,适用于临界区位于任务与任务之间;既不用去延时中断,又可以做到临界区的安全

STM32H750之FreeRTOS学习--------(五)临界段代码保护_第1张图片

你可能感兴趣的:(FreeRTOS,嵌入式硬件)