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


    FreeRTOS

    五、临界段代码保护

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

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

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

    需要应用临界区的场合

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

    套了两层宏

    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 );
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    任务级退出临界段
    taskEXIT_CRITICAL()
    
    • 1
    void vPortExitCritical( void )
    {
        configASSERT( uxCriticalNesting );
        uxCriticalNesting--;
    
        if( uxCriticalNesting == 0 )
        {
            portENABLE_INTERRUPTS();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    调用格式

    taskENTER_CRITICAL() ;
    {
       	/* 临界区 */
    }
    taskEXIT_CRITICAL()	;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    中断级进入临界段
    taskENTER_CRITICAL_FROM_ISR()
    
    • 1
    中断级退出临界段
    taskEXIT_CRITICAL_FROM_ISR()
    
    • 1

    调用格式

    uint32_t  save_status;
    save_status  = taskENTER_CRITICAL_FROM_ISR(){
           	/* 临界区 */
    }
    taskEXIT_CRITICAL_FROM_ISR(save_status );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 成对使用
    • 支持嵌套
    • 尽量保持临界段耗时短
    任务调度器的挂起和恢复

    挂起任务调度器, 调用此函数不需要关闭中断

    挂起任务调度器
    vTaskSuspendAll()
    
    • 1

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

    恢复任务调度器
    xTaskResumeAll()
    
    • 1

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

    如果等于0,则允许调度

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

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

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

    闭中断

    挂起任务调度器
    vTaskSuspendAll()
    
    • 1

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

    恢复任务调度器
    xTaskResumeAll()
    
    • 1

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

    如果等于0,则允许调度

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

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

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

    image-20231108165822662

  • 相关阅读:
    有钱还系统源码 人人还众筹还钱模式还贷系统源码
    使用Pygame做一个乒乓球游戏(2)使用精灵重构
    Java基础空指针
    力扣细节题:判断是否为平衡二叉树
    衍三的硬件笔记之如何选择MOS管
    第三十五章 使用 CSP 进行基于标签的开发 - 使用服务器端方法的提示
    PMP每日一练 | 考试不迷路-8.4(包含敏捷+多选)
    C++之旅(学习笔记)第8章 概念和泛型编程
    《剑指offer第二版》面试题14:剪绳子
    小米躺枪,联发科被曝芯片漏洞:全球37%安卓用户被监听
  • 原文地址:https://blog.csdn.net/Johnor/article/details/134293882