|
事件標志組 嵌入式事件標志組是一種在嵌入式系統(tǒng)中廣泛使用的同步機制,主要用于實現(xiàn)多任務間的同步與通信。
事件標志組是一組事件標志位的集合,每個位代表一個事件是否發(fā)生。它允許任務等待特定的事件發(fā)生,當事件發(fā)生時,相關(guān)任務將被喚醒并執(zhí)行相應的操作。
特點 靈活性:用戶可以根據(jù)需要自定義每個位事件的含義,如bit0表示按鍵是否按下。支持一對多、多對多的同步模式,即一個任務可以等待多個事件的發(fā)生,也可以是多個任務同步多個事件。高效性:使用位操作,效率高,占用資源少。擴展性:雖然常用的是16位或32位無符號的數(shù)據(jù)類型來存儲事件標志,但其中的高8位可能用作控制信息,低24位用作存儲事件標志,因此可以存儲多個事件標志。工作原理 等待事件:任務通過調(diào)用相應的API函數(shù)(如FreeRTOS中的xEventGroupWaitBits)來等待一個或多個事件標志位的發(fā)生?梢栽O置等待條件,如等待所有指定的事件標志位都為1,或等待其中任意一個事件標志位為1。觸發(fā)事件:當事件發(fā)生時,通過調(diào)用相應的API函數(shù)(如FreeRTOS中的xEventGroupSetBits)來設置相應的事件標志位為1,從而觸發(fā)等待該事件的任務。喚醒所有符合條件的任務,類似于“廣播”的作用。執(zhí)行任務:被喚醒的任務根據(jù)事件標志位的狀態(tài)執(zhí)行相應的操作,并可以選擇是否清除事件標志位。應用場景 多任務同步:在需要多個任務協(xié)同工作的場景中,可以使用事件標志組來同步這些任務,但無數(shù)據(jù)傳輸。中斷處理:在中斷服務程序中設置事件標志位,以通知主任務或其他任務進行相應的處理。狀態(tài)監(jiān)控:用于監(jiān)控系統(tǒng)的各種狀態(tài),如設備是否就緒、數(shù)據(jù)是否到達等。例子:在嵌入式系統(tǒng)中,處理USB數(shù)據(jù)的同步發(fā)送通常涉及多線程編程,并使用適當?shù)耐綑C制來確保數(shù)據(jù)的一致性和完整性。在這種情況下,可以使用事件標志和消息隊列來協(xié)調(diào)一個生產(chǎn)線程(生成USB數(shù)據(jù))和一個消費線程(發(fā)送USB數(shù)據(jù))。
設計思路:
消息隊列:用于存儲從生產(chǎn)線程到消費線程的數(shù)據(jù)。每個數(shù)據(jù)項可能是一個指向USB數(shù)據(jù)包緩沖區(qū)的指針或包含數(shù)據(jù)包信息的結(jié)構(gòu)體。事件標志:用于通知消費線程有新的數(shù)據(jù)可供處理,或者當隊列為空時通知生產(chǎn)線程暫停生產(chǎn)。互斥鎖:保護消息隊列和事件標志的訪問,防止競態(tài)條件。
實現(xiàn)步驟:
1. 定義消息隊列和事件標志使用RTOS提供的API來創(chuàng)建消息隊列和事件標志。消息隊列應能夠存儲指向USB數(shù)據(jù)包的指針或相關(guān)結(jié)構(gòu)體。2. 生產(chǎn)線程生產(chǎn)線程負責生成USB數(shù)據(jù),并將其放入消息隊列中。
void producer_thread(void *arg)
{
while (1)
{
// 生成USB數(shù)據(jù)包
usb_packet_t *packet = generate_usb_packet();
// 鎖定互斥鎖
rtos_mutex_lock(&mutex);
// 將數(shù)據(jù)包放入隊列
if (rtos_queue_send(&usb_queue, &packet, portMAX_DELAY) == pdPASS)
{
// 通知消費線程有新數(shù)據(jù)
rtos_event_group_set_bits(&event_group, EVENT_BIT_DATA_READY);
}
// 解鎖互斥鎖
rtos_mutex_unlock(&mutex);
// 等待一段時間或根據(jù)其他條件繼續(xù)生成數(shù)據(jù)
vTaskDelay(pdMS_TO_TICKS(100));
}
}
3. 消費線程消費線程從消息隊列中取出數(shù)據(jù),并發(fā)送USB數(shù)據(jù)包。
void consumer_thread(void *arg)
{
usb_packet_t *packet;
while (1)
{
// 等待數(shù)據(jù)就緒事件
EventBits_t uxBits = xEventGroupWaitBits(
&event_group,
EVENT_BIT_DATA_READY,
pdTRUE,
pdFALSE,
portMAX_DELAY
);
if (uxBits & EVENT_BIT_DATA_READY)
{
// 鎖定互斥鎖
rtos_mutex_lock(&mutex);
// 從隊列接收數(shù)據(jù)包
if (rtos_queue_receive(&usb_queue, &packet, portMAX_DELAY) == pdPASS)
{
// 發(fā)送USB數(shù)據(jù)包
send_usb_packet(packet);
// 釋放數(shù)據(jù)包(如果需要)
free_usb_packet(packet);
}
// 解鎖互斥鎖
rtos_mutex_unlock(&mutex);
}
}
}
4. 初始化與啟動創(chuàng)建消息隊列、事件標志和互斥鎖,并啟動生產(chǎn)者和消費者線程。
void app_main(void)
{
// 初始化消息隊列、事件標志和互斥鎖
rtos_queue_create(&usb_queue, ...);
rtos_event_group_create(&event_group);
rtos_mutex_create(&mutex);
// 創(chuàng)建并啟動生產(chǎn)者和消費者線程
xTaskCreate(producer_thread, "Producer", STACK_SIZE, NULL, PRIORITY, NULL);
xTaskCreate(consumer_thread, "Consumer", STACK_SIZE, NULL, PRIORITY, NULL);
// 其他初始化...
}
注意事項 在使用事件標志組時,需要注意避免競態(tài)條件,確保任務間的同步與通信的正確性。合理安排事件標志位的數(shù)量和使用方式,避免資源浪費和效率低下。在設計系統(tǒng)時,應充分考慮任務間的依賴關(guān)系和同步需求,以選擇合適的同步機制。猜你喜歡:
WiFi6+藍牙+星閃,三合一開發(fā)板,真香!
Github上熱門 C 語言項目匯總!
嵌入式,可測試性軟件設計!
一些低功耗軟件設計的要點!
嵌入式 C 保護結(jié)構(gòu)體的方式
實用 | 10分鐘教你通過網(wǎng)頁點燈
談談嵌入式軟件的兼容性!
分享一個嵌入式代碼生成器設計思路!
點擊閱讀原文,查看更多分享。 |
|