Arduino-ESP32使用FREERTOS使用相互排斥Mutex来解决竞争冒险Race Condition

目录

一、通过全局变量进行任务间的数据传递

(一)volatile关键字

 (二)程序例程

 二、竞争冒险(Race Condition)问题提出

 三、使用Mutex(Mutual Exclusion)解决竞争冒险问题

四、Mutex实例


一、通过全局变量进行任务间的数据传递

(一)volatile关键字

当要求使用 volatile 声明的变量的值的时候,系统总是重新从它所在的内存读取数据,即使它前面的指令刚刚从该处读取过数据。而且读取的数据立刻被保存。例如:

volatile int i=10;
int a = i;
...
// 其他代码,并未明确告诉编译器,对 i 进行过操作
int b = i;

 volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中。而优化做法是,由于编译器发现两次从 i读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读。这样以来,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。

以上是个人认为重要的知识点,详细请看C/C++ 中 volatile 关键字详解 | 菜鸟教程

Volatile关键字(记忆技巧)

1.Volatile中文译为易变的

2.使用Volatile定义的变量,在代码中每次使用都需要经过内存读取

3.防止中断突然改变其变量(因为中断改变变量直接放入内存,若在程序运行的时候直接从寄存器中读取,则会造成数据错误)

 (二)程序例程

 定义两个全局变量,用于记录库存和销售量

// 养成良好习惯,被多进程和中断调用的变量使用 volatile 修饰符
volatile uint32_t inventory = 100; //总库存
volatile uint32_t retailCount = 0; //线下销售量

定义一个retailTask函数,用于改变库存和销量

void retailTask(void *pvParam) {
  while (1) {

    //以下实现了带有随机延迟的 inventory减1;
    //等效为 inventory--; retailCount++;
    uint32_t inv = inventory;
    for (int i; i < random(10, 100); i++) vTaskDelay(pdMS_TO_TICKS(i));
    if (inventory > 0) {
      inventory = inv - 1;
      retailCount++;
    }

  };

  vTaskDelay(10); //老板要求慢一些,客户升级后,可以再加快速度
}

 定义showTask函数,用于展示库存和销量

void showTask(void *pvParam) {
  while (1) {

    printf("Inventory : %d\n", inventory);
    printf("  Retail : %d\n", retailCount);


    if (inventory == 0 ) {
      printf("\n-----SALES SUMMARY-----\n");
      printf("  Total Sales:  %d\n\n", retailCount);
    }
    vTaskDelay(pdMS_TO_TICKS(100));
  }
}

 主函数,创建两个任务

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);

  xTaskCreate(retailTask,
              "Online Channel",
              1024 * 4,
              NULL,
              1,
              NULL);

  xTaskCreate(showTask,
              "Display Inventory",
              1024 * 4,
              NULL,
              1,
              NULL);

}

void loop() {
}

 例程网址:用全局变量实现任务间通信

注意!!!使用全局变量大小一定要与ESP32的CPU大小一致,也就是32位

 二、竞争冒险(Race Condition)问题提出

例程网址:竞争冒险

 三、使用Mutex(Mutual Exclusion)解决竞争冒险问题

理解方法:

MUTEX的工作原理可以想象成

共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问

将Mutex比喻成一把钥匙,首先创建钥匙,再取钥匙,再归还钥匙

1.Create

2.Take

3.Give

  语法:

  SemaphoreHandle_t xHandler; 创建Handler

  xHandler = xSemaphoreCreateMutex(); 创建一个MUTEX 返回NULL,或者handler

  xSemaphoreGive(xHandler); 释放

  xSemaphoreTake(xHanlder, timeout); 指定时间内获取信号量 返回pdPASS, 或者pdFAIL

 例程网址:使用Mutex解决冒险竞争问题

四、Mutex实例

使用MPU6050搭配LCD显示MPU6050的数据

例程网址: https://wokwi.com/projects/333400924498166356

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值