RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

FreeRTOS中osDelay和HAL_Delay的區(qū)別

撞上電子 ? 2023-10-29 08:00 ? 次閱讀

問(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近似。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 程序
    +關(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
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    ADS1299內(nèi)部產(chǎn)生信號(hào)測(cè)試,SPI接收到的數(shù)據(jù)不對(duì),為什么?

    ;amp;amp;tmp,1,1000);//===fff===í£?1á?D??á?£ê? HAL_Delay(1000);LED1_TOGGLE();HAL
    發(fā)表于 11-13 06:23

    在rtthread啟動(dòng)函數(shù)調(diào)用HAL_Dealy()導(dǎo)致卡死的原因?

    看到文章推薦將系統(tǒng)的左右初始化都放入rt_hw_board_init()內(nèi),于是將所有初始化都搬進(jìn)去,結(jié)果由于內(nèi)部調(diào)用了Hal_Delay(),導(dǎo)致卡死,HAL庫(kù)的時(shí)鐘源被設(shè)置成TIM6,但是
    發(fā)表于 09-27 06:42

    STM32CUBEMX生成freeRTOS代碼的時(shí)候出現(xiàn)警告

    to use HAL timebase source other than the Systick. HAL函數(shù)如果是阻塞型呼叫,內(nèi)部會(huì)用到HAL_Delay(),FreeRTOS應(yīng)
    發(fā)表于 09-04 14:13

    cubeide中使用Hal_Delay()時(shí),每次調(diào)試總會(huì)跳轉(zhuǎn)到異常狀態(tài),如何解決?

    cubeide 中使用Hal_Delay()時(shí),每次調(diào)試總會(huì)跳轉(zhuǎn)到異常狀態(tài)。 Break at address \"0xaf5cf47e\" with no debug
    發(fā)表于 07-23 07:52

    FreeRTOS串口重定向使用HAL庫(kù)函數(shù)中斷出現(xiàn)異常的原因?

    由于需要使用到FreeRTOS 考慮到ISR優(yōu)先級(jí)會(huì)比任務(wù)優(yōu)先級(jí)高,并且查看HAL_UART_Transmit函數(shù)實(shí)現(xiàn)需要使用到systick 。 所以在重定義時(shí)使用了函數(shù)
    發(fā)表于 05-22 08:18

    基于STM32Cubemx創(chuàng)建FreeRTOS,創(chuàng)建UART任務(wù)遇到的兩個(gè)問(wèn)題求解

    ) != HAL_OK) { Error_Handler(); } } 主程序UART任務(wù)如下: void Uart_test_Thread() { for(;;) { //osDelay
    發(fā)表于 05-10 07:33

    stm32cubemx的HAL_Delay()函數(shù),當(dāng)HAL_GetTick()的計(jì)數(shù)正好要溢出時(shí),是不是延時(shí)就不準(zhǔn)了?

    ; } __weak void HAL_Delay(__IO uint32_t Delay) { uint32_t tickstart = 0; tickstart = HAL
    發(fā)表于 05-09 06:20

    HAL庫(kù)開(kāi)啟定時(shí)器中斷時(shí)會(huì)卡死程序的原因?

    當(dāng)開(kāi)啟定時(shí)器中斷時(shí)候,開(kāi)啟定時(shí)器時(shí)會(huì)卡死程序,調(diào)試,全速運(yùn)行卡死在-HAL_TIM_Base_Start_IT函數(shù),單步調(diào)試發(fā)現(xiàn)卡死在程序應(yīng)用的HAL_delay函數(shù)內(nèi),但是另外寫(xiě)一個(gè)定時(shí)器中斷和使用延時(shí)的程序不會(huì)卡死,求助各位大佬,這可能是什么原因!!
    發(fā)表于 04-16 07:12

    STM32CubeIDE+FreeRtos+LWIP初始化不通過(guò)怎么解決?

    MX_LAIP_Init就過(guò)不去。調(diào)試代碼,發(fā)現(xiàn)HAL_Delay();函數(shù)出現(xiàn)錯(cuò)誤。上網(wǎng)查了下,也有人碰到過(guò),重構(gòu)解決。然后還是過(guò)不去,調(diào)試發(fā)現(xiàn)創(chuàng)建任務(wù)時(shí)又出現(xiàn)了問(wèn)題,卡在添加新鏈表上,不知道原因。大家這么用的時(shí)候,有沒(méi)有碰到過(guò)類(lèi)似的問(wèn)題,或者初始化的應(yīng)該注意什么。
    發(fā)表于 04-15 07:42

    STM32L476+ST253993增加freertos,但是代碼下進(jìn)去系統(tǒng)運(yùn)行時(shí)就卡住,為什么?

    。rtos使用systick,HAL_delay使用TIM7 freertos的兩個(gè)任務(wù),一個(gè)是LED閃爍,一個(gè)是RFID測(cè)試程序 第一次執(zhí)行時(shí),任務(wù)2的第一個(gè)測(cè)試代碼完成后,到osdelay里就出不來(lái)了
    發(fā)表于 04-15 07:27

    STM32F7 IAP跳轉(zhuǎn)后HAL_Delay沒(méi)有執(zhí)行的原因?

    ;!!!!!!!!!inintt okrn\"); MX_TIM14_Init(); HAL_Delay(5); printf(\"!!!!!!!!!dddrn\"); while(1
    發(fā)表于 04-09 06:53

    stm32FREERTOS的延時(shí)函數(shù)osDelayUntil()死機(jī)的原因?

    我在使用STM32F4跑freertos的時(shí)候發(fā)現(xiàn)一旦使用osDelayUntil()函數(shù),就會(huì)死機(jī),但是用osDelay()函數(shù)就不會(huì),按理說(shuō)不是都可以用的嗎?有知道原因的嗎,謝謝!
    發(fā)表于 03-22 07:56

    STM32F767ZGT6改IAP后HAL_Delay卡死,定時(shí)器不進(jìn)中斷,直到freeRTOS初始化才開(kāi)始中斷,為什么?

    以后程序卡在HAL_Delay里,在定時(shí)器中斷中加串口打印發(fā)現(xiàn)應(yīng)該是定時(shí)器一直沒(méi)有開(kāi)啟導(dǎo)致計(jì)數(shù),應(yīng)該MX_FREERTOS_Init()以及osKernelStart執(zhí)行完以后才開(kāi)啟的定時(shí)器, 我把
    發(fā)表于 03-21 06:13

    STM32燒寫(xiě)程序后出現(xiàn)Break at address\"0x1ff0a752\",程序卡死怎么解決?

    ); HAL_Delay(100); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOF
    發(fā)表于 03-12 06:36

    基于STM32CubeIDE軟件實(shí)現(xiàn)的STM32外部中斷實(shí)例

    因?yàn)镻E2配置為GPIO_EXTI2斷,它出現(xiàn)在了列表。同時(shí)出現(xiàn)的還有SysTick,它是HAL_Delay的時(shí)基來(lái)源,如下圖note處所說(shuō)的,每隔一個(gè)固定時(shí)間產(chǎn)生一次中斷。
    發(fā)表于 01-12 16:15 ?1587次閱讀
    基于STM32CubeIDE軟件實(shí)現(xiàn)的STM32外部中斷實(shí)例
    RM新时代网站-首页