Skip to content

资源管理

独占的访问临界资源有三种方式

  • 公平竞争: 使用互斥量, 谁先获得谁就使用
  • 屏蔽中断
  • 屏蔽任务切换

屏蔽中断

屏蔽中断有两套宏:任务中使用、ISR中使用:

c
任务中使用: taskENTER_CRITICA()/taskEXIT_CRITICAL() 
ISR中使用:taskENTER_CRITICAL_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR()

低优先级的中断被屏蔽了:优先级低于、等于 configMAX_SYSCALL_INTERRUPT_PRIORITY

高优先级的中断可以产生:优先级高于 configMAX_SYSCALL_INTERRUPT_PRIORITY

这个宏会操作中断屏蔽寄存器, stm32只使用了八位寄存器的高四位

  • 但是,这些中断ISR里,不允许使用FreeRTOS的API函数(这些中断需要在上面的宏的范围里面)

任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生

c
static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
    uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

    __asm
    {
        /* Set BASEPRI to the max syscall priority to effect a critical
             * section. */
        /* *INDENT-OFF* */
        msr basepri, ulNewBASEPRI	//设置这个寄存器设置屏蔽的等级
            dsb
            isb
            /* *INDENT-ON* */
    }
}
  • 在中断中使用
c
void vAnInterruptServiceRoutine( void )
{
/* 用来记录当前中断是否使能 */
UBaseType_t uxSavedInterruptStatus;
/* 在ISR中,当前时刻中断可能是使能的,也可能是禁止的
* 所以要记录当前状态, 后面要恢复为原先的状态
* 执行这句代码后,屏蔽中断
*/
uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
/* 访问临界资源 */
/* 恢复中断状态 */
taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
/* 现在,当前ISR可以被更高优先级的中断打断了 */
}

在屏蔽以后需要保持当前函数的状态, 返回的是当前的屏蔽的等级, 默认设置的是11优先级

禁止任务调度

直接暂停调度器就可以了

c
/* 暂停调度器 */
void vTaskSuspendAll( void );
/* 恢复调度器
* 返回值: pdTRUE表示在暂定期间有更高优先级的任务就绪了
* 可以不理会这个返回值
*/
BaseType_t xTaskResumeAll( void );
c
void vTaskSuspendAll( void )
{
    /* A critical section is not required as the variable is of type
     * BaseType_t.  Please read Richard Barry's reply in the following link to a
     * post in the FreeRTOS support forum before reporting this as a bug! -
     * https://goo.gl/wu4acr */

    /* portSOFRWARE_BARRIER() is only implemented for emulated/simulated ports that
     * do not otherwise exhibit real time behaviour. */
    portSOFTWARE_BARRIER();

    /* The scheduler is suspended if uxSchedulerSuspended is non-zero.  An increment
     * is used to allow calls to vTaskSuspendAll() to nest. */
    ++uxSchedulerSuspended;//主要就是这一个全局变量

    /* Enforces ordering for ports and optimised compilers that may otherwise place
     * the above increment elsewhere. */
    portMEMORY_BARRIER();
}

这些个函数可以进行递归使用, 内部会记录嵌套的深度, 只有深度为0的时候, taskEXIT_CRITICAL()才会重新使能中断