本节来讲一讲FreeRTOS如何保护临界段,先讲临界段的概念,再讲保护临界段的方法。

1)临界段的概念

简单来讲,临界段是一段执行时不允许被中断(或其他任务)打断的代码;如果被打断,就有可能运行出错。

举个例子:

假设我们有一个任务Task1需要向队列FIFO中写入数据,中断服务函数TaskISR1也需要向队列FIFO中写入数据;我们知道,FIFO的写或者读需要依次执行:写入/读出数据、更新读/写指针。

如果Task1在向FIFO中写入数据时,执行完写入数据,但还没有更新写指针,此时中断来了,TaskISR1开始运行,它也需要向FIFO中写入,而由于Task1运行时还没有更新写指针,则TaskISR写入的数据会把Task1刚刚写入的数据覆盖,然后更新写指针;这就出现了一次丢失数据的错误。

当然错误还不只如此,中断服务程序TaskISR1运行完毕后,回到Task1继续运行,它会接着被打断的位置向后执行,更新写指针;这样就相当于没有写入数据,但又更新了一次写指针。

像这个例子中的FIFO写入数据、读出数据的代码段,就是临界段;它的读写数据和更新读写指针,两个操作之间不能被打断,否则就会可能出错。

用户代码中用于任务和中断间通信的变量、不可重入函数,操作系统的某些底层代码,都有可能是临界段。如果不保护好临界段,代码就会出现各种难以排查、难以复现的bug。

而最简单的保护临界段的方法,就是关闭中断,以及关闭任务调度。也就是暂时禁止中断和其他任务执行,等到临界段执行完毕后再恢复。具体使用时,如果有可能被中断打断,则关闭中断,如果有可能被高优先级的任务打断,则可以关闭任务调度。

注意!这种“关闭”是临时的,执行完临界段之后,必须要恢复允许中断和任务调度的状态。否则,中断和其他任务就无法运行了。

此外,由于执行临界段时,关闭了任务或任务调度,系统无法响应其他的实时事件,会降低系统的实时性;所以我们编写代码时,需要准确识别临界段,使得临界段尽量短,即只把需要保护的最小的一段代码保护起来即可。

2)freeRTOS中的临界段保护

freeRTOS系统中定义了保护临界段的宏:

在任务中,taskENTER_CRITICAL(),用于进入临界段前保护;taskEXIT_CRITICAL(),用于临界段执行完之后,退出保护。

查看代码调用情况,可以看到它们最后是由下述两个函数实现:

这其中除了开/关中断的代码,还有一个嵌套计数,为的是记录进入了几层“关中断”中,这样在退出临界区时,就不会错误地提前退出了。

其中的开/关中断的操作,是用嵌入的汇编代码实现的,如下所示,关闭中断时,只关闭了优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断:

由于freeRTOS提供的进入临界段的代码,本质上是关闭中断,而一旦关闭中断,则freeRTOS的任务切换功能也被禁止了,所以,它同时能够保护中断和任务间的临界段冲突。

另外,如果想要在中断服务程序中进入临界段,要使用另一套函数来保护临界段:taskENTER_CRITICAL_FROM_ISR(),用于进入临界段前保护;taskEXIT_CRITICAL_FROM_ISR( x )用于临界段执行完之后,退出保护。代码的实现是类似的,感兴趣的可以自行阅读代码。

3)保护临界段的测试实例

我们以一个例子来试验freeRTOS临界段的保护功能:

首先来看不保护临界段的情况。

建立任务,我们把defaultTask任务优先级设置为普通,Task02任务的优先级设置为高,这样,Task02就可以打断defaultTask的执行:

编写一个具有临界段属性的函数,这里我们用串口来实现,就是普通地往串口寄存器中写入数据:

编写两个任务内部执行的功能,都是通过访问串口的临界段函数,打印输出;不同的是高优先级的Task2第一次运行时延迟了5ms,这样可以实现defaultTask任务先执行5ms,之后Task02打断它执行:

上述程序运行结果如下:

可以看到,串口打印的输出,DefaultTask任务首次运行时,打印了前6个字符:Defaul后,被Task02打断,进入了Task02任务的打印功能;Task02打印完毕后,才继续打印DefaultTask未完成的打印字符:tTask is running。

所以,如果临界段Uart1Send函数不加保护,它的打印输出有可能被打断,输出不正确的字符串。

如下所示修改defaultTask的代码,加入临界段保护和退出的语句:

再次运行上述程序,可以看到输出如下,输出了正确的字符串:

所以,临界段保护代码功能是有效的。

4)关闭任务调度

上述的freeRTOS定义的临界区保护的操作,是直接关闭中断;而实际上,有时有的临界段中断里不访问,只用保护不被其他任务打断即可;这时也可以临时关闭任务调度功能,来实现临界段的保护。

freeRTOS系统中定义了关闭任务调度和开启任务调度的函数:

vTaskSuspendAll()、xTaskResumeAll()

这两个函数也需要成对使用,关闭任务调度后,然后执行临界段,最后一定要恢复到开启调度的状态。

而且,在关闭调度后,不能再使用任何会引起任务切换的函数,如之前讲到的延时vTaskDelayUntil、vTaskDelay,以及以后会讲到的信号量、消息队列等函数;直到重新开启任务调度。

在3)中的例子,临界段访问的冲突是不同任务间引起的,我们也可以通过临时关闭任务调度来实现临界段的保护,如下所示:

这个程序的执行结果,和使用taskENTER_CRITICAL()、taskEXIT_CRITICAL()保护临界段是一样的。大家可以自行测试一下。

好了,本节的内容就到这里了。

如果觉得有用可以关注作者微信号“小白白学电子”,在公众号可以找到代码和资料下载地址:

【FreeRTOS】06 临界段的保护——关中断和关调度相关推荐

  1. FreeRTOS内核实现03:临界段的保护

    目录 1. 临界段概述 1.1 什么是临界段 1.2 临界段何时会被打断 2. 关中断操作 2.1 不带中断保护 2.2 带中断保护 3. 开中断操作 4. 进入临界段操作 4.1 不带中断保护 4. ...

  2. FreeRTOS临界段的保护

    什么是临界段 临界段用一句话概括就是一段在执行的时候不能被中断的代码段.在 FreeRTOS 里面, 这个临界段最常出现的就是对全局变量的操作,全局变量就好像是一个枪把子,谁都可以 对他开枪,但是我开 ...

  3. 从0到1写RT-Thread内核——临界段的保护

    临界段就是一段在执行的时候不能被中断的代码段,在RT-Thread里,临界段最常出现的就是对全局变量的操作(类似Linux下的锁).RT-Thread对临界段的保护是直接把中断全部关了,NMI FAU ...

  4. FreeRTOS中断配置与临界段

    Cortex-M中断 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序(中断服务程序),处理完毕后又返回原被暂停的程序继续运行.Cortex- ...

  5. FreeRTOS 临界段和开关中断

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 临界段 代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码 的执行不被 ...

  6. FreeRTOS内核详解(1) —— 临界段保护原理

    什么是临界段 临界段用一句话概括就是一段在执行的时候不能被中断的代码段. 在 FreeRTOS 里面,这个临界段最常出现的就是对全局变量的操作,由于不同任务间可以切换运行,当一个任务在访问某个全局变量 ...

  7. FreeRTOS源码分析与应用开发01:中断配置与临界段

    目录 1. 异常与中断的基本概念 1.1 异常分类 1.2 中断概述 1.2.1 中断处理宜短暂 1.2.2 临界段影响中断实时性 1.3 中断硬件基础 1.3.1 外设 1.3.2 中断控制器 1. ...

  8. freertos临界段保护

    freertos临界段保护 中断的基础知识 cortex-m里面开中断.关中断指令 关中断和开中断 进入临界段和退出临界段 中断的基础知识 嵌套: 嵌套向量中断控制器 NVIC(Nested Vect ...

  9. FreeRTOS — 临界段和开关中断

    以下内容转载自安富莱电子:http://forum.armfly.com/forum.php 1.临界段 代码的临界段也称为临界区,一旦这部分代码开始执行,则不允许任何中断打断.为确保临界段代码的执行 ...

最新文章

  1. bugku 杂项 就五层你能解开吗_你能解开这个和数字有关的逻辑解谜游戏吗? | 每日一考...
  2. oracle 新建路径,Linux环境安装Oracle11g(三)——用户、路径创建及配置环境变量
  3. Linux打印指定的行范围
  4. SAP BTP 平台 CloudFoundry 环境入门级别的介绍
  5. 看阿里云如何用云上技术创新,帮助哈啰单车实现智能数据收治
  6. 什么是Apache Spark?这篇文章带你从零基础学起
  7. oracle下的inventory文件夹,oracle INVENTORY 详解
  8. set get java_JAVA中关于set()和get()方法的理解及使用
  9. 011-你觉得自动化测试有什么意义,都需要做些什么
  10. python list去重函数_Python基础中的集合,函数——06
  11. cmos和ttl_TTL和CMOS的比较
  12. linux系统notebook,RedNotebook——Linux环境桌面日记本
  13. LICEcap--小巧而精致的GIF录屏工具
  14. 利用Python网络爬虫抓取韩寒博客推荐第一篇(urllib的简单使用与Beautifulsoup实战,i/o编程)
  15. 10大程序员必逛网站,良心推荐,建议收藏!
  16. 字节、腾讯、金山wps、跟谁学、百度 go工程师面试题集锦
  17. 三.MFC DLL窗口的创建和注入显示
  18. 计算机导论部分知识整理
  19. 系统架构演变:SOA、微服务架构的区别和联系
  20. 初级中学理化生实验室建设与配备标准

热门文章

  1. 为PostgreSQL配置work_mem
  2. 2021年中国数据安全行业发展现状及未来发展前景分析:数据安全市场快速增长[图]
  3. PostgreSQL的ON CONFLICT
  4. 1年时间强势进阶,百度财报公布好看视频成长秘密
  5. Python Opencv 通过轨迹(跟踪)栏实现更改整张图像的背景颜色(末尾有一个小训练——是将所学得的图像颜色修改应用为画板一般的刷新)
  6. 8张图,看懂数据驱动业务的六个层次
  7. 在 EXCEL 中,“插入已剪切单元格”的快捷键
  8. 进制之间的快速转换法:8421码及原码反码补码之间的相互转换关系
  9. 2019, XII Samara Regional Intercollegiate Programming Contest 解题报告
  10. iPhone 游戏 Dungeon Hunter2 地牢猎手 今日通关