0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RTOS中临界区的使用技巧

嵌入式情报局 来源:最后一个bug 2023-12-12 10:09 次阅读

1裸机与RTOS的理解

首先这里只针对单核CPU架构的芯片展开讨论,大部分是MCU吧,而多核CPU的讨论相对比较复杂,暂不涉及~

玩RTOS的朋友都知道,裸机与OS的最大区别就是实现多任务的并发,其实你说裸机就不能实现任务的并发吗 ? 这个需要看所站的角度吧,只是说RTOS并发的粒度可以更加细,因为把裸机的任务拆分成多块运行,其实也是一种并发方式。

从宏观上虽然RTOS的每个任务都是在并发执行,其实微观上还是一条一条指令在顺序执行着,如下图所示:

21bda9a6-982f-11ee-8b88-92fbcf53809c.png
而对于目前主流的RTOS,如UCOS或者FreeRTOS,所实现的都是多任务,更多的是一种多线程的并发执行而非多进程,所以对应到Linux平台上称他们为thread


2并发带来的问题

并发的好处就是能够在更细的粒度来尽可能的提高CPU的利用率,这里不能说使用了多线程就一定能提高,这与你所设计的任务划分和处理有着直接的关系,只能说
多线程相比裸机更有这个能力。


而任何事物都有其利弊,多个任务在没有同步处理的情况下,任务之间是无序运行的,无序也就意味着状态的多样性和复杂度。


当然bug菌这里所说的无序是一个相对的过程,比如对于CPU而言,它就是顺序的去执行一条一条的指令,所以在这个层面它是有序的、确定的。


而把过程放大,比如执行一条C语言语句,一般它是由多条汇编指令组成,对于目前的抢占式内核,在一段时间内其多个任务就有可能指令交替执行,当这些指令都去操作同一块内存,那么内存的最终结果由于顺序不同而不同,最终难以确定。


状态的不确定就有可能造成异常行为,也就是大家经常遇到的:"怎么跑着跑着就有问题,还没啥规律~","这段代码怎么看也没问题呀~"


所以对比看来RTOS确实会带来编程上的难度~



3临界区

既然有难度,我们就要解决,把不确定性部分通过一些手段来变得确定,而造成这些不确定因素的动力是什么呢?是中断~


bug菌一直觉得,其实对于裸机而言,如果把中断服务函数看成一个更高优先级的抢占式任务,其实裸机主任务与中断任务就形成了一种两任务的并发,所以中断与任务之间也是有共享问题需要类似处理的。


为了解决这些不确定因素,我们只需要在这段代码区域限制中断的发生即可,这一段区域就是临界区,说得直白点 : 关中断与开中断。

1ENTER_CRITICAL();//进入临界区
2
3//临界区代码
4
5EXIT_CRITICAL();//退出临界区



4临界区嵌套


临界区的使用没啥可说的,但是在你的代码中怎么加临界区确实一门技巧,可是说很多3~5年的工程师也并不一定处理得好,本文暂不展开,后面bug菌整理以后再分享给大家,今天只聊聊临界区嵌套使用的问题,毕竟很多朋友在这里掉过坑~



参考伪代码:


1/*********************************************
2 * Function: Fuction1
3 * Description:功能函数
4 * Author: bug菌
5/
6void Fuction1(void)
7{
8 ENTER_CRITICAL();//进入临界区
9
10 //do something~
11
12 EXIT_CRITICAL();//退出临界区
13}
14/
*
15 * Function: Fuction2
16 * Description: 功能函数
17 * Author: bug菌
18 ********************************************/
19void Fuction2(void)
20{
21 ENTER_CRITICAL();//进入临界区
22
23 ......
24 Fuction1();
25
26 ......
27 //do something~
28
29 EXIT_CRITICAL();//退出临界区
30}


这种临界区的使用是很多朋友常犯的错误,当然这里的临界区操作仅仅只是开关中断,许多自己公司写的,或者裁剪的都是这种简约开关中断版本,所以当调用Function1函数以后,后面的代码就不在临界区内了,此时就有可能会存在共享问题。



当然目前的开源OS都会提供一种把相关嵌套标记保存在局部变量中的处理方式,如下代码所示:


1//来源于ucos源码
2#define OS_ENTER_CRITICAL() (cpu_sr = OSCPUSaveSR())
3#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr))
4
5/*********************************************
6 * Function: Fuction1
7 * Description:功能函数
8 * Author: bug菌
9 ********************************************/
10void Fuction1(void)
11{
12 int cpu_sr;
13
14 OS_ENTER_CRITICAL();//进入临界区
15
16 //do something~
17
18 OS_EXIT_CRITICAL();//退出临界区
19}
20
21/*********************************************
22 * Function: Fuction2
23 * Description: 功能函数
24 * Author: bug菌
25 ********************************************/
26void Fuction2(void)
27{
28 int cpu_sr;
29
30 OS_ENTER_CRITICAL();//进入临界区
31
32 Fuction1(void);
33
34 OS_EXIT_CRITICAL();//退出临界区
35
36}


为了更好的理解,我写了一下下面的伪代码,供大家参数~


1//中断寄存器register原本是1, 向register写0关中断,向register写1开中断
2
3void Fuction2(void)
4{
5 int cpu_sr1 = 0;
6
7 cpu_sr1 = register;
8 register = 0; //register == 0;cpu_sr1 == 1;
9
10 void Fuction1(void)
11 {
12 int cpu_sr1 = 0;
13
14 cpu_sr2 = register;
15 register = 0; //register == 0;cpu_sr2 == 0;
16
17
18 register = cpu_sr2;
19 cpu_sr2 = 0;//register == 0;cpu_sr2 == 0;
20 }
21
22 register = cpu_sr1;
23 cpu_sr1 = 0;//register == 1;cpu_sr1 == 0;
24
25}



不同的OS可能具体实现有所差异,大体上都一样~



来源:公众号,最后一个bug

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 芯片
    +关注

    关注

    452

    文章

    50134

    浏览量

    420436
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10794

    浏览量

    210697
  • RTOS
    +关注

    关注

    21

    文章

    809

    浏览量

    119342
  • 代码
    +关注

    关注

    30

    文章

    4710

    浏览量

    68190

原文标题:RTOS中临界区的使用是门技术活~

文章出处:【微信号:嵌入式情报局,微信公众号:嵌入式情报局】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    RT-Thread记录(五、RT-Thread 临界保护)

    本文聊聊临界,以及RT-Thread对临界的处理
    的头像 发表于 06-20 16:06 4918次阅读
    RT-Thread记录(五、RT-Thread <b class='flag-5'>临界</b><b class='flag-5'>区</b>保护)

    【安富莱】【RTX操作系统教程】第11章 临界段,任务锁和中断锁

    中有临界段的话,会给系统带来什么问题呢?比如此时某个任务正在调用系统API函数,而且此时中断正好关闭了,也就是进入到了临界,这个时候如果有一个紧急的中断事件被触发,这个中断就不能得
    发表于 01-25 16:52

    RTOS临界段知识详解

    执行完毕后,要立即打开中断。 临界段的作用 其实在RTOS,使用最多的临界段是OS本身的调用,但是我们用户也是需要对临界资源进行保护的(
    发表于 10-09 11:02

    ucos测试例程临界挂起

    ); //创建信号量集 OSStatInit();//初始化统计任务.这里会延时1秒钟左右 OS_ENTER_CRITICAL();//进入临界(无法被中断打断)OSTaskCreate(led_task
    发表于 05-06 00:01

    【设计技巧】rtos的核心原理简析

    其他外设中断也能够立刻切换。二、 临界 切换是可以了,但是现在我的任务运行一个东西就是不能够被打断的,怎么呢? 好了,rtos又有了一东西叫临界
    发表于 07-23 08:00

    为什么临界可以触发PENDSV中断?

    OSCtxSw OSIntCtxSw都在临界,而这两个函数都是触发中断函数PendSV处理的。临界不是关中断啦吗,为什么还可以触发Pe
    发表于 10-09 21:02

    STM32 上 RTOS 的中断管理

    后按 PA0(中断源),中断不会即时响应,离开临界后此中断会被响应。临界实现如下,此临界
    发表于 01-27 17:30

    浅析RT_Thread系统临界资源和临界

    物联网嵌入式系统:RT_Thread系统临界资源和临界(1)-禁止调度和禁止中断使用互斥特性保护临界:信号量二值信号量创建二值信号量,为
    发表于 12-22 06:13

    RTThread开关中断的具体实现过程以及进入临界的相关操作说明

    ……rt_hw_interrupt_enable(0);//(4)开中断//退出临界1……示例2存在的问题就是在第(1)步 的时候关闭了中断,在第(3)部的时候开启了中断。这样的结果跟我们的意愿是不相符的,我们期望到第(4)
    发表于 05-27 14:52

    代码进入临界时还可以抢占临界资源吗

    ;#endif /RT_USING_SMP/RTM_EXPORT(rt_enter_critical);看了代码, 发现进入临界的时候, 中断disable然后又enable, 所以, 进入临界
    发表于 11-25 10:36

    什么是临界RTOS临界段的作用是什么

    代码的临界段也称为临界,指处理时不可分割的代码区域,一旦这部分代码开始执行,则不允许任何中断打断。为确保临界段代码的执行不被中断,在进入临界
    的头像 发表于 10-06 14:38 1.2w次阅读
    什么是<b class='flag-5'>临界</b>段 <b class='flag-5'>RTOS</b><b class='flag-5'>临界</b>段的作用是什么

    Cortex-M裸机环境下临界保护的三种实现

    对特别眼熟,在 RTOS 里常常会有多任务(进程)处理,有些情况下一些特殊操作(比如 XIP 下 Flash 擦写、低功耗模式切换)不能被随意打断,或者一些共享数据不能被无序访问(A 任务正在读,B 任务却要写),这时候就要用到临界
    的头像 发表于 09-08 09:23 3113次阅读
    Cortex-M裸机环境下<b class='flag-5'>临界</b><b class='flag-5'>区</b>保护的三种实现

    什么是RTOS临界

    代码的临界段也称为临界,指处理时不可分割的代码区域,一旦这部分代码开始执行,则不允许任何中断打断。为确保临界段代码的执行不被中断,在进入临界
    的头像 发表于 02-14 09:48 1051次阅读
    什么是<b class='flag-5'>RTOS</b><b class='flag-5'>临界</b>段

    分享一下Cortex-M裸机环境下临界保护的几种实现方法

    RTOS临界,裸机依然有临界。今天给大家分享一下Cortex-M裸机环境下临界
    发表于 06-13 09:08 673次阅读
    分享一下Cortex-M裸机环境下<b class='flag-5'>临界</b><b class='flag-5'>区</b>保护的几种实现方法

    RTOS临界段知识详解

    代码的临界段也称为临界,指处理时不可分割的代码区域,一旦这部分代码开始执行,则不允许任何中断打断。
    的头像 发表于 06-13 14:07 1077次阅读
    <b class='flag-5'>RTOS</b><b class='flag-5'>临界</b>段知识详解