韦东山freeRTOS系列教程之第十二章资源管理(Resource Management)

Posted 韦东山

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了韦东山freeRTOS系列教程之第十二章资源管理(Resource Management)相关的知识,希望对你有一定的参考价值。

需要获取更好阅读体验的同学,请访问我专门设立的站点查看,地址:http://rtos.100ask.net/

系列教程总目录

本教程连载中,篇章会比较多,为方便同学们阅读,点击这里可以查看文章的 目录列表,目录列表页面地址:https://blog.csdn.net/thisway_diy/article/details/121399484

概述

在前面讲解互斥量时,引入过临界资源的概念。在前面课程里,已经实现了临界资源的互斥访问。

本章节的内容比较少,只是引入两个功能:屏蔽/使能中断、暂停/恢复调度器。

要独占式地访问临界资源,有3种方法:

  • 公平竞争:比如使用互斥量,谁先获得互斥量谁就访问临界资源,这部分内容前面讲过。
  • 谁要跟我抢,我就灭掉谁:
    • 中断要跟我抢?我屏蔽中断
    • 其他任务要跟我抢?我禁止调度器,不运行任务切换
.. toctree::
   :maxdepth: 2

   section1

12.1 屏蔽中断

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

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

12.1.1 在任务中屏蔽中断

在任务中屏蔽中断的示例代码如下:

/* 在任务中,当前时刻中断是使能的
 * 执行这句代码后,屏蔽中断
 */
taskENTER_CRITICAL();

/* 访问临界资源 */

/* 重新使能中断 */
taskEXIT_CRITICAL();

taskENTER_CRITICA()/taskEXIT_CRITICAL()之间:

  • 低优先级的中断被屏蔽了:优先级低于、等于configMAX_SYSCALL_INTERRUPT_PRIORITY
  • 高优先级的中断可以产生:优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY
    • 但是,这些中断ISR里,不允许使用FreeRTOS的API函数
  • 任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生

这套taskENTER_CRITICA()/taskEXIT_CRITICAL()宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用taskEXIT_CRITICAL()才会重新使能中断。

使用taskENTER_CRITICA()/taskEXIT_CRITICAL()来访问临界资源是很粗鲁的方法:

  • 中断无法正常运行
  • 任务调度无法进行
  • 所以,之间的代码要尽可能快速地执行

12.1.2 在ISR中屏蔽中断

要使用含有"FROM_ISR"后缀的宏,示例代码如下:

void vAnInterruptServiceRoutine( void )

    /* 用来记录当前中断是否使能 */
    UBaseType_t uxSavedInterruptStatus;
    
    /* 在ISR中,当前时刻中断可能是使能的,也可能是禁止的
     * 所以要记录当前状态, 后面要恢复为原先的状态
     * 执行这句代码后,屏蔽中断
     */
    uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
    
    /* 访问临界资源 */

    /* 恢复中断状态 */
    taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus );
    /* 现在,当前ISR可以被更高优先级的中断打断了 */

taskENTER_CRITICA_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR()之间:

  • 低优先级的中断被屏蔽了:优先级低于、等于configMAX_SYSCALL_INTERRUPT_PRIORITY
  • 高优先级的中断可以产生:优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY
    • 但是,这些中断ISR里,不允许使用FreeRTOS的API函数
  • 任务调度依赖于中断、依赖于API函数,所以:这两段代码之间,不会有任务调度产生

12.2 暂停调度器

如果有别的任务来跟你竞争临界资源,你可以把中断关掉:这当然可以禁止别的任务运行,但是这代价太大了。它会影响到中断的处理。

如果只是禁止别的任务来跟你竞争,不需要关中断,暂停调度器就可以了:在这期间,中断还是可以发生、处理。

使用这2个函数来暂停、恢复调度器:

/* 暂停调度器 */
void vTaskSuspendAll( void );

/* 恢复调度器
 * 返回值: pdTRUE表示在暂定期间有更高优先级的任务就绪了
 *        可以不理会这个返回值
 */
BaseType_t xTaskResumeAll( void );

示例代码如下:

vTaskSuspendScheduler();

/* 访问临界资源 */

xTaskResumeScheduler();

这套vTaskSuspendScheduler()/xTaskResumeScheduler()宏,是可以递归使用的,它的内部会记录嵌套的深度,只有嵌套深度变为0时,调用taskEXIT_CRITICAL()才会重新使能中断。

以上是关于韦东山freeRTOS系列教程之第十二章资源管理(Resource Management)的主要内容,如果未能解决你的问题,请参考以下文章

韦东山freeRTOS系列教程之第十三章调试方法

韦东山freeRTOS系列教程之第五章队列(queue)

韦东山freeRTOS系列教程之第九章任务通知(Task Notifications)

韦东山freeRTOS系列教程之第六章队列(queue)

韦东山freeRTOS系列教程之第八章事件组(event group)

韦东山freeRTOS系列教程之第十章软件定时器(software timer)