FreeRTOS入门基础

news/2024/12/29 18:07:18/

RTOS是为了更好地在嵌入式系统上实现多任务处理和时间敏感任务而设计的系统。它能确保任务在指定或预期的时间内得到处理。FreeRTOS是一款免费开源的RTOS,它广泛用于需要小型、预测性强、灵活系统的嵌入式设备。

创建第一个任务

  1. 任务函数:任务是通过函数来定义的。函数通常看起来像这样的无限循环
       void vTaskFunction( void * pvParameters ){for( ;; ){// 任务代码}}

  2. 创建任务:使用xTaskCreate()函数来创建一个任务。
       xTaskCreate(vTaskFunction,       // 任务函数"TaskName",          // 任务名称STACK_SIZE,          // 堆栈大小NULL,                // 参数TASK_PRIORITY,       // 任务优先级NULL );              // 用来传回创建的任务的句柄

  3. 启动调度器:创建任务后,需要启动调度器,这样RTOS就能开始管理这些任务了。
       vTaskStartScheduler();

freertos基本组件

FreeRTOS作为一个实时操作系统(RTOS),提供了多种基础组件来组织代码并有效地管理任务。以下是一些FreeRTOS的基本组件:

  1. 任务 (Tasks):

    • 任务是FreeRTOS中的基本执行单位,相当于一个独立的线程。每个任务都有自己的优先级,调度器根据这些优先级来决定运行哪个任务。
  2. 队列 (Queues):

    • 队列用于在任务之间发送和接收数据。它们可以帮助实现任务同步,并提供一种安全传递消息的方法,如事件、内存块等。
      #include "FreeRTOS.h"
      #include "queue.h"// 队列句柄,用于后续的队列操作如发送和接收
      QueueHandle_t xQueue;// main() 或者任何初始化函数中
      void main() {// 创建一个可以存储10个元素的队列,每个元素大小为sizeof( BaseType_t )xQueue = xQueueCreate(10, sizeof(BaseType_t));if (xQueue == NULL) {// 队列创建失败,可能是由于内存不足// 错误处理代码} else {// 队列成功创建// 可以继续使用队列}// ... 其余初始化代码 ...// 启动任务,开始调度器vTaskStartScheduler();// ... 其余代码 ...
      }

      在这个例子中:

    • xQueueCreate 函数的第一个参数(10)指定了队列能够存储的元素的数量。
    • 第二个参数(sizeof(BaseType_t))指定了队列中每个元素的大小。
    • 注意,在使用 xQueueCreate() 创建队列之前,必须确保已经调用了 vTaskStartScheduler(),因为队列的使用依赖于FreeRTOS的内存管理函数,它们在调度器启动时初始化。此外,创建队列通常在系统的初始化阶段进行,然后各个任务可以通过队列句柄进行数据的发送和接收。

       

      创建队列后,可以使用 xQueueSend()xQueueReceive() 等函数来在任务之间传递数据。如果队列创建成功,xQueueCreate() 将返回一个非NULL的 QueueHandle_t 句柄,用于后续的队列操作。如果内存不足或者有其他原因导致队列创建失败,则返回NULL。

  3. 信号量 (Semaphores):

    • 信号量是一种同步机制,可以用来控制对共享资源的访问,或者在任务之间同步操作。在FreeRTOS中有两种主要类型的信号量:二进制信号量和计数信号量。
      #include "FreeRTOS.h"
      #include "semphr.h"SemaphoreHandle_t xSemaphore = NULL;void main_demo( void )
      {// 二进制信号量创建xSemaphore = xSemaphoreCreateBinary();if (xSemaphore != NULL){// 信号量创建成功,可以被使用}else{// 信号量创建失败,处理错误情况}// ...// 后续代码,如启动调度器和任务等// ...
      }
      #include "FreeRTOS.h"
      #include "semphr.h"SemaphoreHandle_t xCountingSemaphore;void main_demo( void )
      {// 计数信号量创建,最大计数和初始计数xCountingSemaphore = xSemaphoreCreateCounting(maxCount, initialCount);if (xCountingSemaphore != NULL){// 信号量创建成功}else{// 信号量创建失败,处理错误情况}// ...// 后续代码,如启动调度器和任务等// ...
      }

      在计数信号量的创建中, maxCount 表示信号量能够达到的最大计数值,而 initialCount 是信号量的初始计数值。

       

      信号量通常用于同步任务或中断服务程序 (ISR),例如,保护共享资源,协调任务的执行,任务通知等。创建后的信号量句柄可以通过任务和中断服务程序进行给出 (Give) 和取得 (Take) 操作。

  4. 互斥量 (Mutexes):

    • 互斥量是特殊类型的信号量,专门用于管理资源访问。与二元信号量不同,互斥量具有所有权的概念,使其在处理优先级反转问题时更加有效。
  5. 定时器 (Timers):

    • 定时器可以在一个定义好的时间之后运行一个函数。FreeRTOS支持一次性定时器和周期性定时器。
      #include "FreeRTOS.h"
      #include "timers.h"TimerHandle_t xTimer;void vTimerCallback(TimerHandle_t xTimer)
      {// 这里处理定时器到期时的逻辑
      }void main_demo( void )
      {const TickType_t xTimerPeriod = pdMS_TO_TICKS( 1000 ); // 定时周期1000毫秒// 创建软件定时器xTimer = xTimerCreate("Timer",                // 定时器的文本名称,用于调试xTimerPeriod,           // 定时器的周期,以tick计数pdTRUE,                 // pdFALSE为单次定时器,pdTRUE为周期性定时器( void * ) 0,           // 可用于传递给回调函数的标识符,通常是NULLvTimerCallback          // 定时器到期时调用的回调函数);if (xTimer == NULL){// 定时器创建失败,可能是由于内存不足}else{// 定时器创建成功,可以启动定时器if (xTimerStart(xTimer, 0) != pdPASS){// 定时器启动失败}}// ...// 后续代码,如启动调度器和任务等// ...
      }

      在这个例子中:

    • 第一个参数("Timer")是定时器名称。
    • 第二个参数(xTimerPeriod)设置定时器周期,通过pdMS_TO_TICKS宏转换了毫秒到tick。
    • 第三个参数指定了定时器是单次的 (pdFALSE) 还是自动重载的周期性定时器 (pdTRUE)。
    •  

      定时器创建后,你需要调用xTimerStart()函数来启动定时器,此后定时器将按照设定的周期运行。在资源有限的嵌入式系统里,软件定时器是一种资源节约的实现定时功能的方式,因为你可以在一个定时服务中管理多个定时器,而无需为每个定时任务创建单独的线程。

    • 第四个参数是指针,它会被传递给定时器回调函数,可以用作计数器或存储状态信息。
    • 第五个参数是定时器到期时调用的回调函数。
  6. 事件组 (Event Groups):

    • 事件组是一种可以等待或设置一组事件标志的机制。这允许任务在多种事件中等待任意组合的事件。
      #include "FreeRTOS.h"
      #include "event_groups.h"EventGroupHandle_t xEventGroup;void main_demo( void )
      {// 创建事件组xEventGroup = xEventGroupCreate();if(xEventGroup == NULL){// 事件组创建失败,通常是因为内核没有足够的可用堆空间// 错误处理代码}else{// 事件组成功创建,可以使用xEventGroup来设置、清除和等待事件标志}// ...// 启动任务和调度器等// ...
      }

      在这个例子中,xEventGroupCreate 用于创建一个新的事件组,并返回一个 EventGroupHandle_t 类型的句柄,以供后续的事件组操作使用。如果事件组创建失败,则返回 NULL,通常是由于内存不足。

       

      成功创建事件组后,可以使用如下函数操作事件标志:

    • xEventGroupSetBits:设置事件组中的一个或多个事件标志。
    • xEventGroupClearBits:清除事件组中的一个或多个事件标志。
    • xEventGroupWaitBits:等待事件组中的一个或多个特定事件标志变为设置状态。
    • 事件组是处理多个任务和中断共享状态或事件同步时的一个非常有用的工具,能够以线程安全的方式进行复杂的事件标志操作。
  7. 任务通知 (Task Notifications):

    • 任务通知是一种轻量级的信号量替代方式,可以快速地向任务发送信号。
    • 发送任务通知

      // 取得需要通知的任务的句柄,可以在任务创建时获取
      TaskHandle_t xTaskToNotify = ...;// 发送通知给任务,'ulValue' 是通知值
      uint32_t ulValue = 10;
      BaseType_t xHigherPriorityTaskWoken = pdFALSE; // 仅在中断服务程序中使用// 任务级代码
      xTaskNotify(xTaskToNotify, ulValue, eSetValueWithOverwrite);// 或者在 ISR 中
      xTaskNotifyFromISR(xTaskToNotify, ulValue, eSetValueWithOverwrite, &xHigherPriorityTaskWoken);
      portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

      在上面的代码中,xTaskToNotify 是要接收通知的任务的句柄。ulValue 是要发送的通知值。eSetValueWithOverwrite 指示即使之前的通知未被任务接收,也将覆盖通知值。

    • 等待任务通知

      // 该变量将接收通知值
      uint32_t ulNotificationValue;
      BaseType_t xResult;// 等待通知
      xResult = xTaskNotifyWait(0x00,          // 在进入等待时不清除任何位ULONG_MAX,     // 在退出等待时将清除所有位&ulNotificationValue,  // 存储接收到的通知值portMAX_DELAY); // 一直等待直到接收到通知if(xResult == pdPASS)
      {// 任务接收到通知,`ulNotificationValue` 包含收到的值
      }

      在上面的等待通知代码中,xTaskNotifyWait 第一个参数为零表示调用任务进入等待通知状态时,不清除任务的任何通知状态位。第二个参数 ULONG_MAX 表示调用任务在接收到通知时将清除任务的所有通知状态位。第四个参数是阻塞时间,这个例子中使用 portMAX_DELAY,任务会无限期地等待直到收到通知。

       

      通过 xTaskNotifyGive 和 ulTaskNotifyTake 的组合,任务通知机制也可以模仿二进制信号量的行为。任务通知作为一种轻量级的同步机制,在许多场合可以替代信号量和事件组,以节省系统资源。

资源地址

FreeRTOS - Market leading RTOS (Real Time Operating System) for embedded systems with Internet of Things extensions

 Free RTOS Book and Reference Manual


http://www.ppmy.cn/news/1387901.html

相关文章

外贸网站文章批量生成器

随着全球贸易的不断发展,越来越多的企业开始关注外贸市场,而拥有高质量的内容是吸引潜在客户的关键之一。然而,为外贸网站生产大量优质的文章内容可能是一项耗时且繁琐的任务。因此,外贸网站文章批量生成软件成为了解决这一难题的…

简单来说依赖注入 Unity (c#)

在游戏开发领域,构建引人入胜且组织良好的游戏是最终目标。然而,随着项目复杂性的增加,管理依赖关系和确保代码灵活性可能成为一项艰巨的任务。这就是依赖注入 (DI) 发挥作用的地方。 在本文中,我们将深入 Unity 中的依赖注入世界,探索其概念、优点和实际实现。最后,你将…

nginx相关内容的安装

nginx的安装 安装依赖 yum install gcc gcc-c automake autoconf libtool make gd gd-devel libxslt-devel -y 安装lua与lua依赖 lua安装步骤如下: mkdir /www mkdir /www/server #选择你自己的目录即可,不需要跟我一致 cd /www/server tar -zxvf lua-5.4.3.tar.gz cd lua-5.4…

鸿蒙Harmony应用开发—ArkTS声明式开发(绘制组件:Rect)

矩形绘制组件。 说明&#xff1a; 该组件从API Version 9开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Rect(value?: {width?: string | number,height?: string | number,radius?: string | number | Array<s…

在ubuntu下安装MQTT 服务

ubuntu系统版本22.4.4LTS amd64 在ubuntu系统下打开终端输入命令 ## 安装MQTT 服务 sudo apt-get install mosquitto mosquitto-clients继续执行后系统就完成了安装并默认已启动服务 ## 查看MQTT运行状态 systemctl status mosquitto## 启动服务 systemctl start mosquitto…

24 OpenCV直方图反向投影

文章目录 参考反向投影作用calceackProject 反向投影mixchannels 通道图像分割示例 参考 直方图反向投影 反向投影 反向投影是反映直方图模型在目标图像中的分布情况简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型 作用…

Midjourney 和 Dall-E 的优劣势比较

Midjourney 和 Dall-E 的优劣势比较 Midjourney 和 Dall-E 都是强大的 AI 绘画工具&#xff0c;可以根据文本描述生成图像。 它们都使用深度学习模型来理解文本并将其转换为图像。 但是&#xff0c;它们在功能、可用性和成本方面存在一些差异。 Midjourney 优势: 可以生成更…

【算法与数据结构】二叉树(前中后)序遍历

文章目录 &#x1f4dd;前言&#x1f320; 创建简单二叉树&#x1f309;二叉树的三种遍历&#x1f320;前序&#x1f309;中序遍历 &#x1f320;后序遍历 &#x1f320;二叉树节点个数&#x1f309;二叉树节点个数注意点 &#x1f6a9;总结 &#x1f4dd;前言 一棵二叉树是结…