RTOS 入门(1):什么是 RTOS ?试手 FreeRTOS

RTOS 入门(1):什么是 RTOS ?试手 FreeRTOS

1. 通用操作系统(GPOS / General Purpose Operating System)

操作系统一般具有三种功能:

  1. Task scheduling 任务调度
  2. Resource management 资源管理
  3. Device drivers 设备驱动

为什么我们需要实时操作系统?

  • 大多数通用操作系统在设计之初将人机交互放在最重要的位置,所以调度器会给任务划分优先级,这也就意味着有些运行时限会被忽略或者是延后。而因此所产生的微小延迟,对于人类来说是可以接收的。
  • 除此之外,GPOS的调度器通常还是非强制性的,这就意味着我们无法知道某个任务确切的执行时刻和执行时间。这样的特性在一些系统中是致命的,比如汽车的刹车系统。
  • 所以,在对于时间有严格要求的项目中,就需要实时操作系统(RTOS / Real-Time Operating System)的参与。RTOS采用的是基于优先级的抢占式调度方法,确保高优先级任务能够得到及时处理,严格遵守时限。

2. 无限循环结构(Super Loop)

在这里插入图片描述

  • 在STM32中主函数中的while(1)循环以及Arduino代码中的loop函数,都是采用了所谓的无限循环结构。
  • 在一些比较业务比较简单的情况下,结合定时器以及中断,Super Loop 也可以实现理想的效果。但是它的限制在于你无法同时执行多个任务,以上图为例,如果 Task2 所需要的时间较长,而 Task3 又是你的屏幕刷新函数,那你的项目执行就会出现卡顿的情况
  • 如果你间隔小于1ms,那你最好的方式是通过中断来处理问题;但是如果你需要间隔小于几百ns,你需要主频非常高的CPU或者是FPGA。
  • 实时操作系统与无限循环结构在嵌入式开发当中并没有高低之分,要根据具体的情况去选择。

3. 任务、线程、进程

TaskThreadProcess
任务是任何一项我们想在代码中完成的工作线程是 CPU 使用其寄存器组和对堆栈的工作单元进程是一个正在执行的计算机程序实例
  • 一个进程会使用一个或多个线程完成工作
  • 同一个进程之间的线程之间可以共享资源(堆、内存)
  • 通常情况下,RTOS只能管理一个进程,而GPOS可以管理多个进程
  • 在 FreeRTOS中 task 作为一种专有名词可以用来替代 thread 的

4. 适用实时操作系统的情况

在这里插入图片描述

  • 首先,使用实时操作系统就意味着一定的开销,所以RTOS一般仅适用于时钟频率、内存较高的单片机
  • 在此基础之上,如果你需要同时执行一些任务,并且需要严格遵守时限,那么RTOS是适用的。

5. FreeRTOS 实现 LED 灯闪烁

程序运行环境:ESP32 Arduino 环境

需要注意的是,ESP32 并不运行 Vanilla-FreeRTOS,为了支持双核芯片,在原生 FreeRTOS 基础上进行了修改,使其支持 SMP(对称多处理)。
但是基础的语法依旧是保持一致的,所以依赖 ESP32 程序库的 FreeRTOS 直接学习也不失为一个好的选择。

#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else 
static const BaseType_t app_cpu = 1;
#endif

// Pins
static const int led_pin = 2;

// Our task: blink an LED
void toggleLED(void *parameter){
  while(1){
    digitalWrite(led_pin, HIGH);
    vTaskDelay(500 / portTICK_PERIOD_MS);
    digitalWrite(led_pin, LOW);
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

void setup() {
  // Configure pin
  pinMode(led_pin, OUTPUT);

  // Task to run forever
  xTaskCreatePinnedToCore(  // use xTaskCreate() in vanilla FreeRTOS
              toggleLED,    // Function to be called
              "Toggle LED", // Name of task
              1024,         // Stack size (bytes in ESP32, words in FreeRTOS)
              NULL,         // Parameter to pass to function
              1,            // Task priority (0 to configMAX_PRIORTIES )
              NULL,         // Task handle
              app_cpu);     // Run on one core for demo purposes (ESP32 only)
    
  // If this waa vailla FreeRTOS, you would want to call vTaskStartSchedule() in
  // main after setting up your tasks
}

void loop() {
  // put your main code here, to run repeatedly:

}
  • ESP32是一个双核开发板,但是我们的实验只使用它的单核模式。

  • vTaskDelay 函数是一个非阻塞式的延时函数,该函数指定的是延时多少 Tick,而不是ms。语句 vTaskDelay(500 / portTICK_PERIOD_MS); 表示的才是50ms。但是RTOS中默认的Tick时长是1ms,所以 vTaskDelay(500);vTaskDelay(500 / portTICK_PERIOD_MS); 两个语句都表示延时500ms。

  • xTaskCreatePinnedToCore 函数创建一个任务并且只在指定的 CPU 运行,这是 ESP32 独有的函数,与 vanilla FreeRTOS 中 xTaskCreate 函数的作用是一致的。在 ESP32 中 xTaskCreate 函数仍是有效的,但是调用它则会通知调度器用任意的CPU执行任务。

  • ESP32 中任务栈大小的单位是 bytes,任务栈最小是 768 bytes。而在 vanilla FreeRTOS 中任务栈大小的单位则是 words。

  • 任务优先级从 0 开始,一直到 config 中定义的最大优先级,ESP32 默认的最大优先级是 24。

  • 在 vanilla FreeRTOS 中,在设置完任务之后需要调用 vTaskStartSchedule 通知调度器开始工作。但是在Arduino框架之下,该函数在 setup 函数之前已经被调用,无需重复调用。


参考链接:

  1. 【Digi-Key】RTOS入门
  2. FreeRTOS(IDF)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值