FreeRTOS中断、临界区和任务调度器

一、中断

中断是 CPU 的一种常见特性,中断一般由硬件产生,当中断发生后,会中断 CPU 当前正
在执行的程序而跳转到中断对应的服务程序种去执行,ARM Cortex-M 内核的 MCU 具有一个
用于中断管理的嵌套向量中断控制器
NVIC。ARM Cortex-M 的 NVIC 最大可支持 256 个中断源,其中包括 16 个系统中断和 240 个外部中断。

中断优先级配置寄存器的值与对应的优先等级成反比,即中断优先级配置寄存器的值越小,中断的优先等级越高。

STM32 的中断优先级可以分为抢占优先级和子优先级。抢占优先级:抢占优先级高的中断可以打断正在执行但抢占优先级低的中断,即抢占优先级支持中断嵌套。子优先级:抢占优先级相同时,子优先级高的中断不能打断正在执行但子优先级低的中的中断,即子优先级不支持中断嵌套


二、临界区

 宏 taskENTER_CRITICAL()

此宏用于在非中断中进入临界区,展开后是函数 vPortEnterCritical(),函数vPortEnterCritical() 的代码如下所示:

void vPortEnterCritical( void )
{
    /* 关闭受 FreeRTOS 管理的中断 */
    portDISABLE_INTERRUPTS();

    /* 临界区支持嵌套 */
    uxCriticalNesting++;

    if( uxCriticalNesting == 1 )
    {
        /* 这个函数不能在中断中调用 */
        configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
    }
}

从上面的代码中可以看出,函数 vPortEnterCritical()进入临界区就是关闭中断,当然了,不受 FreeRTOS 管理的中断是不受影响的。还可以看出,FreeRTOS 的临界区是可以嵌套的,意思
就是说,在程序中可以重复地进入临界区,只要后续重复退出相同次数的临界区即可。  

宏 taskEXIT_CRITICAL()

此宏用于从非中断中退出临界区,此宏展开后是vPortExitCritical(),函数vPortExitCritical()的代码如下所示:

void vPortExitCritical( void )
{
    /* 必须是进入过临界区才能退出 */
    configASSERT( uxCriticalNesting );

    uxCriticalNesting--;

    if( uxCriticalNesting == 0 )
    {
        /* 打开中断 */
        portENABLE_INTERRUPTS();
    }
}

这个函数就很好理解了,就是将用于临界区嵌套的计数器减 1,当计数器减到 0 的时候,
说明临界区已经没有嵌套了,于是调用函数 portENABLE_INTERRUPT()打开中断。在函数的一
开始还有一个断言,这个断言用于判断用于临界区嵌套的计数器在进入此函数的不为 0,这样
就保证了用户不会在还未进入临界区时,就错误地调用此函数退出临界区。

三、任务调度器

1、FreeRTOS 中提供的任务调度器是基于优先级的全抢占式调度:在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的。

2、函数 vTaskStartScheduler()用于启动任务调度器,任务调度器启动后,FreeRTOS 便会开始进行任务调度,除非调用函数 xTaskEndScheduler()停止任务调度器,否则不会再返回。也就是说调用vTaskStartScheduler函数启动任务调度器之后不会执行函数后面的语句

3、挂起任务调度器,禁止任务的调度和切换,执行内容不允许被其他内容打断,但是中断可以正常打断执行的内容。挂起任务调度器主要是防止任务与任务之间的资源抢夺。与临界区不一样的是,挂起任务调度器,未关闭中断;任务调度器仅仅是防止了任务之间的资源争夺,中断照样可以直接响应;

vTaskSuspendAll() ;
/*代码*/
xTaskResumeAll()    ;

4、 vTaskStartScheduler()主要做了六件事情
(1) 创建空闲任务,根据是否支持静态内存管理,使用静态方式或动态方式创建空闲任务。
(2) 创建定时器服务任务,创建定时器服务任务需要配置启用软件定时器,创建定时器服务
任务,同样是根据是否配置支持静态内存管理,使用静态或动态方式创建定时器服务任务。   (3)关闭中断,使用 portDISABLE_INTERRUPT()关闭中断,这种方式只关闭受 FreeRTOS 管
理的中断。关闭中断主要是为了防止 SysTick 中断在任务调度器开启之前或过程中,产生中断。
FreeRTOS 会在开始运行第一个任务时,重新打开中断。
(4)初始化一些全局变量,并将任务调度器的运行标志设置为已运行
(5)初始化任务运行时间统计功能的时基定时器,任务运行时间统计功能需要一个硬件定时
器提供高精度的计数,这个硬件定时器就在这里进行配置,如果配置不启用任务运行时间统计
功能的,就无需进行这项硬件定时器的配置。
(6)最后就是调用函数 xPortStartScheduler()。

四、 NVIC异常类型

五、总结

进入临界区只是关闭了freeRTOS管理的中断,通过配置freertosconfig.h中的宏 configMAX_SYSCALL_INTERRUPT_PRIORITY (配置 FreeRTOS 可管理的最高优先级的中断,值为5),所以进入临界区之后中断优先级大于5的都可以打断临界区的运行。然后任务切换也可以打断临界区的运行

挂起任务调度器只是关闭了任务的调度和切换,但是此时中断都可以打断此任务的运行

优先级最小的中断>优先级最大的任务  中断是数字越小优先级越高,任务优先级是数字越大优先级越高

  • 27
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值