FreeRTOS How-to

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zoosenpin/article/details/78399521
1 FreeRTOS API
1.1 Time Delay
void vTaskDelay(portTickType xTicksToDelay);
延时的msecs / portTICK_RATE_MS,譬如延时500ms,那么vTaskDelay(500 / portTICK_RATE_MS)。

2 Task和Process名词上的区别
该解释不严格,只是为了好记。
Task是工作在核心态的,没有MMU保护;而Process 是工作在用户态的,需要有MMU保护。所以多Process的OS实现比较复杂,而多Task的实现相对简单。
因此RTOS中多以多Task支持,而不支持Process;Nucleus中的是多Task的OS而不是多Process。
线程和进程的比较
https://wenku.baidu.com/view/ffc9676748d7c1c708a145aa.html

3 Suspend-Resume
3.1 Call Flow
@ kernel/rtos/FreeRTOS/Source/tasks.c
static portTASK_FUNCTION( prvIdleTask, pvParameters )
--->
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );

@ kernel/rtos/FreeRTOS/Source/portable/GCC/XXX/port_tick.c
void tickless_handler(uint32_t xExpectedIdleTime)

4 FreeRTOS的队列管理的应用
4.1 Example
先解释一下队列:是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。
在FreeRTOS中,对队列有专门的管理机制及函数,在queue.h定义。使用队列进行消息传送,可以避免数据冲突与丢失等现象。如:有一个任务,需要根据另外三个任务的数据来执行它的操作或运行流程,且在这四个任务运行时,是不定时的,没有任何规律可言,那么按照传统的公共变量的方式,就有可能产生数据丢失或数据访问冲突。如果在这里使用FreeRTOS的队列来传递数据信息,则相当容易地把这种问题给解决了。在FreeRTOS中使用队列,最简单的应用,需要创建队列、发送队列消息、等待接收队列消息、删除队列等操作。使用队列,不仅可以传送单字节消息,也可以传送数据结构。在这里,队列管理相关的函数定义不就再进行说明了,需要时,可以参考queue.h。下面直接举例,说明如何使用FreeRTOS队列。

例如:有一组LED灯,在同一个物理操作端口上面,另外三个不同的任务,需要操作这组LED灯来指示系统状态。这时,引入一个单独的任务来操作这组LED灯,那三个不同的任务则向这一个LED灯操作任务发送消息来控制LED灯。则应用程序框架如下所示:

1、 定义消息数据结构及变量
typedef struct //定义一个需要传递的消息的数据结构
{
       u8 msg_src;// 消息来源编号
       u8 msg_val;// 消息值
} Led_msg;

#define  Task1_msg  0x1 // 定义任务1所传递的消息
#define  Task2_msg  0x2 // 定义任务2所传递的消息
#define  Task3_msg  0x3  // 定义任务3所传递的消息

xQueueHandle  hLED_MSG;//用于传递消息的一个公共Handle变量

2、 在main程序中,创建一个消息用于消息的传递
        hLED_MSG = xQueueCreate( 10 , sizeof(Led_msg) );//创建一个消息,最多可以有10个值进行排队,每个值的大小为数据结构Led_msg大小。

3、 在LED灯操作的任务中等待消息并处理
void Task_LED( void *pvParameters )
{
        Led_msg Receive_msg;
        While(1) //该任务是一个不退出的循环任务
        {
               While(xQueueReceive(hLED_MSG, & Receive_msg, portMAX_DELAY ) != pdPASS );// 等待消息直到收到一个有效的消息数据,并放入Receive_msg变量中
               Switch(Receive_msg.msg_src)
               {
                case: Task1_msg
                       ;;;;;// 执行任务1传递过来的消息,对LED的操作
                       Break;
                case: Task2_msg
                       ;;;;;// 执行任务2传递过来的消息,对LED的操作
                       Break;
                case: Task3_msg
                       ;;;;;// 执行任务3传递过来的消息,对LED的操作
                       Break;
                default:
                       Break;
                }
        }
}

4、消息的发送
void Task1 ( void *pvParameters )
{
        Led_msg Send_msg;
        While(1)
        {
                ;;;;;//任务1的任务部份
                Send_msg. msg_src = Task1_msg; //指定任务1消息编号
                Send_msg. msg_val = 0x5;//假定该任务要传递的值为0x5
                xQueueSend(hLED_MSG , & Send_msg, portMAX_DELAY ); //发送消息
        }
}

void Task2 ( void *pvParameters )
{
        Led_msg Send_msg;
        While(1)
        {
                ;;;;;//任务2的任务部份
                Send_msg. msg_src = Task2_msg; //指定任务2消息编号
                Send_msg. msg_val = 0x77;//假定该任务要传递的值为0x77
                xQueueSend(hLED_MSG , & Send_msg, portMAX_DELAY ); //发送消息
        }
}

void Task3 ( void *pvParameters )
{
        Led_msg Send_msg;

        While(1)
        {
                ;;;;;//任务3的任务部份
                Send_msg. msg_src = Task3_msg; //指定任务3消息编号
                Send_msg. msg_val = 0x9;//假定该任务要传递的值为0x9
                xQueueSend(hLED_MSG , & Send_msg, portMAX_DELAY ); //发送消息
        }
}

到此,队列的基本应用例子程序已完成。如果在应用程序中的某种条件下,不再需要这个队列,则可以调用xQueueDelete(hLED_MSG)将该队列删除。基本了解了FreeRTOS任务的创建及应用,以及队列的应用,则可以完成一些简单应用程序的编写。

转载之:http://www.uectr.com/ArticleTechnology-349.html

4.2 queue usage
#include "freertos/queue.h"

typedef struct fg_data {
        unsigned short v;
        unsigned short i;
        unsigned short p;
        unsigned short kwh;
} fg_data_t;
static xQueueHandle UartMsgQueue;

Initialization:
UartMsgQueue = xQueueCreate( 5 /*depth*/, 8/*element size*/);

TX:
fg_data_t fgdata_tx;
fgdata_tx.v = 1;

xQueueSend( UartMsgQueue, ( void* )&fgdata, 1000/portTICK_RATE_MS);
ARG3: if queue has no room, the function will wait for maximum time, when timeout happens and still has no room, the function returns failure, otherwise returns success.

RX:
fg_data_t fgdata_rx;
xQueueReceive( UartMsgQueue, &fgdata_rx, 1000/portTICK_RATE_MS )
ARG3: if queue has been empty, the function will wait for maximum time, when timeout happens and no data available, the function returns failure, otherwise returns the data.

5 FreeRTOS定时器
FreeRTOS的定时器函数都是异步的(async)
xTimerStart()发送消息将TimerHandle_t添加到激活list中。
xTimerStop()发送消息将TimerHandle_t从激活list中删除。
xTimerChangePeriod()发送消息将TimerHandle_t从激活list中删除,修改超时时间,然后重新添加到激活list中。

6 URLs
基于STM32的FREERTOS平台下的低功耗设计原理
http://www.stmcu.org/article/id-328297

7 Abbreviations
AWS IOT:Amazon Web Service

猜你喜欢

转载自blog.csdn.net/zoosenpin/article/details/78399521
今日推荐