Freertos学习第三天-ESP32基于Freertos任务共享全局变量

对于全局变量来说如果在Freertos想要被使用必须只有一个任务写入,读出可以有多个任务。

以下代码展示了一个任务写入,另一个任务读出。

volatile uint32_t inventory = 100; //总库存
volatile uint32_t retailCount = 0; //线下销售量


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); //老板要求慢一些,客户升级后,可以再加快速度
}



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() {
}

以下代码显示了如果有多个任务写入的话,程序就会出错。因此写入数据的话需要有一定的数据保护。

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

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); //老板要求慢一些,客户升级后,可以再加快速度
}

void onlineTask(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;
      onlineCount++;
    }

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


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

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


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

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

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

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

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

}

void loop() {
}

以下代码展示了如何进行多任务全局变量处理时,进行数据保护。

创建一个句柄。

SemaphoreHandle_t xMutexInventory = NULL; //创建信号量Handler

创建一个MUTEX。

 xMutexInventory = xSemaphoreCreateMutex(); //创建MUTEX

 该函数是判断是否可以改变数据,第一个参数是MUTEX,第二个参数是规定的时间。

  if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS)

 处理完以后释放钥匙

 xSemaphoreGive(xMutexInventory);
/*
  程序: Tasks之间数据传递
        有多任务同时写入,或者数据大小超过cpu内存通道时,或者对共享资源的访问时候,需要有防范机制
        使用MUTEX对数据对Cirtical Section的内容进行保护
        可以想象成MUTEX就是一把锁
  语法:
  SemaphoreHandle_t xHandler; 创建Handler
  xHandler = xSemaphoreCreateMutex(); 创建一个MUTEX 返回NULL,或者handler
  xSemaphoreGive(xHandler); 释放
  xSemaphoreTake(xHanlder, timeout); 指定时间内获取信号量 返回pdPASS, 或者pdFAIL

  理解方法:
  MUTEX的工作原理可以想象成
  共享的资源被锁在了一个箱子里,只有一把钥匙,有钥匙的任务才能对改资源进行访问
*/

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

SemaphoreHandle_t xMutexInventory = NULL; //创建信号量Handler

TickType_t timeOut = 1000; //用于获取信号量的Timeout 1000 ticks


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

    // 在timeout的时间内如果能够获取就继续
    // 通俗一些:获取钥匙
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
      //被MUTEX保护的内容叫做 Critical Section


      //以下实现了带有随机延迟的 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++;

        //释放钥匙
        xSemaphoreGive(xMutexInventory);
      } else {
        //无法获取钥匙
      }


    };

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

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

    // 在timeout的时间内如果能够获取二进制信号量就继续
    // 通俗一些:获取钥匙
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
      //被MUTEX保护的内容叫做 Critical Section
      //以下实现了带有随机延迟的 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;
        onlineCount++;

        //释放钥匙
        xSemaphoreGive(xMutexInventory);
      } else {
        //无法获取钥匙
      }
    };

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


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

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


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

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

  xMutexInventory = xSemaphoreCreateMutex(); //创建MUTEX

  if (xMutexInventory == NULL) {
    printf("No Enough Ram, Unable to Create Semaphore.");
  } else {
    xTaskCreate(onlineTask,
                "Online Channel",
                1024 * 4,
                NULL,
                1,
                NULL);
    xTaskCreate(retailTask,
                "Retail Channel",
                1024 * 4,
                NULL,
                1,
                NULL);
    xTaskCreate(showTask,
                "Display Inventory",
                1024 * 4,
                NULL,
                1,
                NULL);
  }

}

void loop() {
}

相关推荐

  1. FreeRTOS任务调度机制学习

    2024-04-23 13:52:05       37 阅读
  2. FreeRTOS学习 -- 任务 API 函数

    2024-04-23 13:52:05       39 阅读
  3. FreeRTOS学习笔记-基于stm32(10)事件标志组

    2024-04-23 13:52:05       33 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-23 13:52:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-23 13:52:05       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-23 13:52:05       82 阅读
  4. Python语言-面向对象

    2024-04-23 13:52:05       91 阅读

热门阅读

  1. leetcode热题HOT 155. 最小栈

    2024-04-23 13:52:05       33 阅读
  2. 【React Router】快速使用

    2024-04-23 13:52:05       36 阅读
  3. spring中的Aware接口概念

    2024-04-23 13:52:05       35 阅读
  4. 8.Godot 函数|变量|运算符|条件循环语句

    2024-04-23 13:52:05       35 阅读
  5. python机器学习库中Scikit-learn和TensorFlow如何选择?

    2024-04-23 13:52:05       36 阅读
  6. 【OS】AUTOSAR架构下MCAL Modules软件分区问题分析

    2024-04-23 13:52:05       37 阅读
  7. SQL中不等于的写法

    2024-04-23 13:52:05       31 阅读
  8. Linux文件/目录高级管理一 头歌

    2024-04-23 13:52:05       38 阅读
  9. 智能合约区块应用链交易所系统教程开发搭建

    2024-04-23 13:52:05       34 阅读
  10. 笔记:Python 循环结构练习题

    2024-04-23 13:52:05       35 阅读
  11. 实验3 7段数码管译码器动态显示

    2024-04-23 13:52:05       26 阅读
  12. yolov8下实现绿萝识别

    2024-04-23 13:52:05       43 阅读
  13. 【代码随想录】day44

    2024-04-23 13:52:05       112 阅读
  14. oracle--存储过程基本框架

    2024-04-23 13:52:05       111 阅读
  15. 富格林:善用正规要领杜绝受害

    2024-04-23 13:52:05       120 阅读
  16. 嵌入式学习——C语言基础——day6

    2024-04-23 13:52:05       34 阅读