freertos学习之临界区处理

简介

每个进程中访问临界资源的那段代码称为临界区(Critical Section) (临界资源是一次仅允许一个进程使用的共享资源)。
每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。
多个进程中涉及到同一个临界资源的临界区称为相关临界区。

注:多线程并发访问全局变量也是临界区问题

程序调度法则

进程进入临界区的调度原则是:

  1. 如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
  2. 任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
  3. 进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
  4. 如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象

FreeRTOS解决方法

访问一个被多任务共享,或是被多任务和中断共享的资源时,需要采用“互斥”技术以保证数据在任何时候都保持一致性。这样做的目的是要确保任务从开始访问资源就具有排它性,直到这个资源又恢复到完整状态。

基本临界区

基本临界区是指宏taskENTER_CRITICAL()和taskEXIT_CRITICAL()之间的代码区间。也被称为Critical Section或者Critical Regions. 使用方法如下:

// 为了保证PORTA的访问不被中断,将访问操作放入临界区运行
taskENTER_CRITICAL();        //进入基本临界区
 
// 在taskENTER_CRITICAL()和taskEXIT_CRITICAL()之间不会切换到其他任务,中断可以执行,也允许嵌
//套,但只是针对优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY的任务,而且这些中断不允许访问
//FreeRTOS的API函数。
 
PORTA |= 0x01;
 
 
taskEXIT_CRITICAL();        //退出基本临界区

临界区是提供互斥功能的一种非常原始的实现方法。临界区的工作 仅仅是简单的把中断全部关掉,或者是关掉优先级在configMAX_SYSCALL_INTERRUPT_PRIORITY以下的中断-依赖具体使用的FreeRTOS移植。抢占式的上下文切换只可能在某中断中完成,因此调用taskENTER_CRITICAL()可以在中断关闭的时段一直保持持续运行状态直到退出临界区。

临界区必须具有很短的时间,否则会反过来影响中断的响应时间。在每次使用taskENTER_CRITICAL()之后必须尽快的配套一个taskEXIT_CRITICAL()来退出临界区。

使用信号量或者互斥量

推荐使用互斥量,因为互斥量解决了优先级翻转的问题

void process_data(void)
{
    if(xSemaphoreTake(xSemaphore, 10) == pdTRUE)
    {
        x++;
        xSemaphoreGive( xSemaphore );
    }
}

信号量和互斥量的最大区别是

(1)用于互斥的信号量必须归还
(2)用于同步的信号量在完成同步后变丢弃,不需要归还

禁止任务调度

vTaskSuspendAll(void);   //挂起调度器创建临界区(禁止任务调度 suspend the scheduler)
 
/*
   通过vTaskSuspendAll()来挂起调度器。挂起调度器可以停止上下文切换而不用关中断,如果某个中断在调
度器挂起过程中要求进行上下文切换,则这个要求也会被挂起,直到调度器被唤醒后才会得到执行。
*/
 
vTaskResumeAll(void);  //(解除禁止任务调度 resuming the scheduler; 成对使用)
/*
返回值:pdTRUE: 
   在调度器挂起过程中,上下文切换请求也会被挂起,直到调度器唤醒才被执行,如果一个挂起的上下文切换请求在vTaskResumeAll()返回前得到执行,则返回pdTRUE.
返回值:pdFALSE:
   如果是其他情况,则返回pdFALSE.
*/
 
// 注意1:两个函数成对使用;
// 注意2:两者之间不能调用FreeRTOS系统API.

如果一段临界区太长而不适合简单的关中断来实现,可以考虑采用挂起调度器的方式
唤醒调度器是一个相对较长的操作
基本临界区是保护一段代码区间不被其他任务或中断打断。而由挂起调度器实现的临界区只能保护一段代码不被其他任务打断,并不能约束中断,因为在这种方式下,中断是使能的。
调度器处于挂起状态时,不能调用FreeRTOS的API函数。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高咩咩在人间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值