問(wèn)題場(chǎng)景
在FreeRTOS中創(chuàng)建了線(xiàn)程A、線(xiàn)程B,其中線(xiàn)程A優(yōu)先級(jí)大于線(xiàn)程B。線(xiàn)程A、B任務(wù)代碼如下:
void A(void *argument)
{
while (1)
{
printf("A\r\n");
HAL_Delay(1000);
}
}
void B(void *argument)
{
while (1)
{
printf("B\r\n");
HAL_Delay(1000);
}
}
燒錄程序后查看串口數(shù)據(jù)發(fā)現(xiàn)只打印了A而不打印B,說(shuō)明只執(zhí)行了A線(xiàn)程沒(méi)有執(zhí)行B線(xiàn)程。
問(wèn)題原因
HAL_Delay是由ST提供的STM32 Cube HAL庫(kù)中的一個(gè)函數(shù),通常用于在STM32微控制器上實(shí)現(xiàn)簡(jiǎn)單的延時(shí)。HAL_Delay函數(shù)使用系統(tǒng)時(shí)鐘來(lái)進(jìn)行延時(shí),并且在延時(shí)期間會(huì)阻塞整個(gè)處理器,也就是說(shuō),它會(huì)使處理器暫時(shí)停止執(zhí)行其他任務(wù)和代碼。
在開(kāi)始運(yùn)行線(xiàn)程之前,線(xiàn)程A、B處于就緒態(tài),由于線(xiàn)程A優(yōu)先級(jí)比線(xiàn)程B高,F(xiàn)reeRTOS任務(wù)控制器優(yōu)先選擇線(xiàn)程A運(yùn)行,此時(shí)線(xiàn)程A進(jìn)入運(yùn)行態(tài)。隨后線(xiàn)程A打印A,然后被HAL_Delay函數(shù)"阻塞",注意此時(shí)的"阻塞"并不意味著程序進(jìn)入了阻塞態(tài),由于HAL_Delay阻塞的是整個(gè)處理器,因此FreeRTOS無(wú)法進(jìn)行其他線(xiàn)程的調(diào)度,也就是說(shuō),HAL_Delay同時(shí)阻塞了線(xiàn)程B。當(dāng)HAL_Delay函數(shù)運(yùn)行結(jié)束后,線(xiàn)程A重回就緒態(tài),由于線(xiàn)程A優(yōu)先級(jí)比線(xiàn)程B高,F(xiàn)reeRTOS任務(wù)控制器優(yōu)先選擇線(xiàn)程A運(yùn)行,循環(huán)往復(fù),線(xiàn)程B不被執(zhí)行。
解決辦法
osDelay是FreeRTOS(Real-Time Operating System)中的一個(gè)函數(shù),用于實(shí)現(xiàn)任務(wù)的延時(shí)。FreeRTOS是一個(gè)開(kāi)源的實(shí)時(shí)操作系統(tǒng),專(zhuān)門(mén)用于嵌入式系統(tǒng)。osDelay函數(shù)允許任務(wù)掛起一段時(shí)間,然后由操作系統(tǒng)調(diào)度器在指定的時(shí)間后重新運(yùn)行該任務(wù)。在等待期間,任務(wù)會(huì)被放入掛起狀態(tài),讓其他任務(wù)有機(jī)會(huì)運(yùn)行。
也就是說(shuō),當(dāng)調(diào)用osDelay時(shí),線(xiàn)程A進(jìn)入阻塞態(tài),此時(shí)任務(wù)控制器選擇進(jìn)入就緒態(tài)的線(xiàn)程B執(zhí)行,循環(huán)往復(fù),線(xiàn)程A、B同時(shí)被執(zhí)行。我們可以將任務(wù)A和B進(jìn)行如下改動(dòng),即可看到既打印A又打印B。
void A(void *argument)
{
while (1)
{
printf("A\r\n");
osDelay(1000);
}
}
void B(void *argument)
{
while (1)
{
printf("B\r\n");
osDelay(1000);
}
}
使用osDelay可能帶來(lái)的問(wèn)題
觀察一下HAL_Delay和osDelay的函數(shù)原型:
/**
* @brief This function provides minimum delay (in milliseconds) based
*/
__weak void HAL_Delay(uint32_t Delay);
/*
Wait for Timeout (Time Delay).
*/
osStatus_t osDelay (uint32_t ticks);
可以看到HAL_Delay函數(shù)的目的是提供毫秒級(jí)別的延時(shí),意味著當(dāng)你輸入HAL_Delay(500),硬件會(huì)盡量延時(shí)精確到500ms的時(shí)間。
與之不同的是,osDelay函數(shù)的輸入是ticks。ticks是一個(gè)計(jì)時(shí)單位,表示任務(wù)將被掛起的時(shí)間長(zhǎng)度。每個(gè)tick的時(shí)間取決于FreeRTOS配置的時(shí)鐘節(jié)拍(tick)周期。例如,如果tick周期為1毫秒,那么傳遞參數(shù)ticks為10就會(huì)使任務(wù)掛起10毫秒。由此可見(jiàn),osDelay函數(shù)延時(shí)的時(shí)間和一個(gè)ticks記時(shí)時(shí)間長(zhǎng)度有很大關(guān)系。
那么如何確定ticks具體代表多長(zhǎng)時(shí)間呢?首先我們應(yīng)該找到用于配置的頭文件,通常這個(gè)頭文件名字叫做FreeRTOSConfig.h。其中,configTICK_RATE_HZ配置選項(xiàng)的值表示每秒鐘系統(tǒng)時(shí)鐘節(jié)拍(tick)的數(shù)量。configTICK_RATE_HZ的值一般默認(rèn)被設(shè)置為1000,表示系統(tǒng)時(shí)鐘每秒產(chǎn)生1000個(gè)tick,即每個(gè)tick的時(shí)間間隔為1毫秒,此時(shí)osDelay對(duì)單個(gè)任務(wù)延時(shí)的時(shí)間長(zhǎng)度和HAL_Delay近似。
-
程序
+關(guān)注
關(guān)注
117文章
3785瀏覽量
81000 -
RTOS
+關(guān)注
關(guān)注
22文章
811瀏覽量
119588 -
FreeRTOS
+關(guān)注
關(guān)注
12文章
484瀏覽量
62136 -
線(xiàn)程
+關(guān)注
關(guān)注
0文章
504瀏覽量
19675
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論