1 FreeRTOS API
1.1 Time Delay
void vTaskDelay(portTickType xTicksToDelay);
延時參數:msecs / portTICK_RATE_MS,譬如延時500ms,vTaskDelay(500 / portTICK_RATE_MS)。
1.2 FreeRTOS定時器
FreeRTOS的定時器函數都是異步的(async)
xTimerStart()發送消息將TimerHandle_t添加到激活list中。
xTimerStop()發送消息將TimerHandle_t從激活list中刪除。
xTimerChangePeriod()發送消息將TimerHandle_t從激活list中刪除,修改超時時間,然後重新添加到激活list中。
1.3 睡眠喚醒
at kernel/rtos/FreeRTOS/Source/tasks.c
static portTASK_FUNCTION( prvIdleTask, pvParameters )
--->
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
at kernel/rtos/FreeRTOS/Source/portable/GCC/XXX/port_tick.c
void tickless_handler(uint32_t xExpectedIdleTime)
2 FreeRTOS的隊列管理
2.1 基本概念
隊列是先進先出(FIFO, First-In-First-Out)的線性表。在具體應用中通常用鏈表或者數組來實現。隊列只允許在後端(稱爲rear)進行插入操作,在前端(稱爲front)進行刪除操作。隊列的操作方式和堆棧類似,唯一的區別在於隊列只允許新數據在後端進行添加。
在FreeRTOS中,對隊列有專門的管理機制及函數,在queue.h定義。使用隊列進行消息傳送,可以避免數據衝突與丟失等現象。如:有一個任務,需要根據另外三個任務的數據來執行它的操作或運行流程,且在這四個任務運行時,是不定時的,沒有任何規律可言,那麼按照傳統的公共變量的方式,就有可能產生數據丟失或數據訪問衝突。如果在這裏使用FreeRTOS的隊列來傳遞數據信息,則相當容易地把這種問題給解決了。在FreeRTOS中使用隊列,最簡單的應用,需要創建隊列、發送隊列消息、等待接收隊列消息、刪除隊列等操作。使用隊列,不僅可以傳送單字節消息,也可以傳送數據結構。在這裏,隊列管理相關的函數定義不就再進行說明了,需要時,可以參考queue.h。
2.2 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所傳遞的消息
xQueueHandle led_msg_handle; // 用於傳遞消息的一個公共Handle變量
2)在main程序中,創建一個消息用於消息的傳遞
led_msg_handle = xQueueCreate(10 , sizeof(led_msg)); // 創建一個消息,最多可以有10個值進行排隊,每個值的大小爲數據結構led_msg大小。
3)在LED燈操作的任務中等待消息並處理
void led_task(void *pvParameters)
{
led_msg receive_msg;
while (1) // 該任務是一個不退出的循環任務
{
while (xQueueReceive(led_msg_handle, &receive_msg, portMAX_DELAY) != pdPASS ); // 等待消息直到收到一個有效的消息數據,並放入receive_msg變量中
switch (receive_msg.msg_src)
{
case TASK1_MSG:
; // 執行任務1傳遞過來的消息,對LED的操作
break;
case TASK2_MSG:
; // 執行任務2傳遞過來的消息,對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 = 0x1; //假定該任務要傳遞的值爲0x1
xQueueSend(led_msg_handle, &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 = 0x2; //假定該任務要傳遞的值爲0x2
xQueueSend(led_msg_handle, &send_msg, portMAX_DELAY); //發送消息
}
}
到此,隊列的基本應用例子程序已完成。如果在應用程序中的某種條件下,不再需要這個隊列,則可以調用xQueueDelete(led_msg_handle)將該隊列刪除。
3 Abbreviations
AWS IOT:Amazon Web Service
FreeRTOS開發指南
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.