0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FreeRTOS中osDelay和HAL_Delay的区别

撞上电子 2023-10-29 08:00 次阅读

问题场景

FreeRTOS中创建了线程A、线程B,其中线程A优先级大于线程B。线程A、B任务代码如下:

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);
}
}

烧录程序后查看串口数据发现只打印了A而不打印B,说明只执行了A线程没有执行B线程。

问题原因

HAL_Delay是由ST提供的STM32 Cube HAL库中的一个函数,通常用于在STM32微控制器上实现简单的延时。HAL_Delay函数使用系统时钟来进行延时,并且在延时期间会阻塞整个处理器,也就是说,它会使处理器暂时停止执行其他任务和代码。

在开始运行线程之前,线程A、B处于就绪态,由于线程A优先级比线程B高,FreeRTOS任务控制器优先选择线程A运行,此时线程A进入运行态。随后线程A打印A,然后被HAL_Delay函数"阻塞",注意此时的"阻塞"并不意味着程序进入了阻塞态,由于HAL_Delay阻塞的是整个处理器,因此FreeRTOS无法进行其他线程的调度,也就是说,HAL_Delay同时阻塞了线程B。当HAL_Delay函数运行结束后,线程A重回就绪态,由于线程A优先级比线程B高,FreeRTOS任务控制器优先选择线程A运行,循环往复,线程B不被执行。

解决办法

osDelay是FreeRTOS(Real-Time Operating System)中的一个函数,用于实现任务的延时。FreeRTOS是一个开源的实时操作系统,专门用于嵌入式系统。osDelay函数允许任务挂起一段时间,然后由操作系统调度器在指定的时间后重新运行该任务。在等待期间,任务会被放入挂起状态,让其他任务有机会运行。

也就是说,当调用osDelay时,线程A进入阻塞态,此时任务控制器选择进入就绪态的线程B执行,循环往复,线程A、B同时被执行。我们可以将任务A和B进行如下改动,即可看到既打印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可能带来的问题

观察一下HAL_Delay和osDelay的函数原型:

/**
* @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函数的目的是提供毫秒级别的延时,意味着当你输入HAL_Delay(500),硬件会尽量延时精确到500ms的时间。

与之不同的是,osDelay函数的输入是ticks。ticks是一个计时单位,表示任务将被挂起的时间长度。每个tick的时间取决于FreeRTOS配置的时钟节拍(tick)周期。例如,如果tick周期为1毫秒,那么传递参数ticks为10就会使任务挂起10毫秒。由此可见,osDelay函数延时的时间和一个ticks记时时间长度有很大关系。

那么如何确定ticks具体代表多长时间呢?首先我们应该找到用于配置的头文件,通常这个头文件名字叫做FreeRTOSConfig.h。其中,configTICK_RATE_HZ配置选项的值表示每秒钟系统时钟节拍(tick)的数量。configTICK_RATE_HZ的值一般默认被设置为1000,表示系统时钟每秒产生1000个tick,即每个tick的时间间隔为1毫秒,此时osDelay对单个任务延时的时间长度和HAL_Delay近似。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 程序
    +关注

    关注

    116

    文章

    3769

    浏览量

    80805
  • RTOS
    +关注

    关注

    21

    文章

    809

    浏览量

    119393
  • FreeRTOS
    +关注

    关注

    12

    文章

    483

    浏览量

    61955
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19638
收藏 人收藏

    评论

    相关推荐

    ADS1299内部产生信号测试,SPI接收到的数据不对,为什么?

    ;amp;amp;tmp,1,1000);//===fff===Í£Ö¹Á¬Ðø¶Áģʽ HAL_Delay(1000);LED1_TOGGLE();HAL
    发表于 11-13 06:23

    在rtthread启动函数调用HAL_Dealy()导致卡死的原因?

    看到文章推荐将系统的左右初始化都放入rt_hw_board_init()内,于是将所有初始化都搬进去,结果由于内部调用了Hal_Delay(),导致卡死,HAL库的时钟源被设置成TIM6,但是
    发表于 09-27 06:42

    STM32CUBEMX生成freeRTOS代码的时候出现警告

    to use HAL timebase source other than the Systick. HAL函数如果是阻塞型呼叫,內部会用到HAL_Delay(),FreeRTOS
    发表于 09-04 14:13

    cubeide中使用Hal_Delay()时,每次调试总会跳转到异常状态,如何解决?

    cubeide 中使用Hal_Delay()时,每次调试总会跳转到异常状态。 Break at address \"0xaf5cf47e\" with no debug
    发表于 07-23 07:52

    基于STM32Cubemx创建FreeRTOS,创建UART任务遇到的两个问题求解

    ) != HAL_OK) { Error_Handler(); } } 主程序UART任务如下: void Uart_test_Thread() { for(;;) { //osDelay
    发表于 05-10 07:33

    stm32cubemx的HAL_Delay()函数,当HAL_GetTick()的计数正好要溢出时,是不是延时就不准了?

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

    HAL库开启定时器中断时会卡死程序的原因?

    当开启定时器中断时候,开启定时器时会卡死程序,调试,全速运行卡死在-HAL_TIM_Base_Start_IT函数,单步调试发现卡死在程序应用的HAL_delay函数内,但是另外写一个定时器中断和使用延时的程序不会卡死,求助各位大佬,这可能是什么原因!!
    发表于 04-16 07:12

    STM32CubeIDE+FreeRtos+LWIP初始化不通过怎么解决?

    MX_LAIP_Init就过不去。调试代码,发现HAL_Delay();函数出现错误。上网查了下,也有人碰到过,重构解决。然后还是过不去,调试发现创建任务时又出现了问题,卡在添加新链表上,不知道原因。大家这么用的时候,有没有碰到过类似的问题,或者初始化的应该注意什么。
    发表于 04-15 07:42

    STM32L476+ST253993增加freertos,但是代码下进去系统运行时就卡住,为什么?

    。rtos使用systick,HAL_delay使用TIM7 freertos的两个任务,一个是LED闪烁,一个是RFID测试程序 第一次执行时,任务2的第一个测试代码完成后,到osdelay里就出不来了
    发表于 04-15 07:27

    STM32F7 IAP跳转后HAL_Delay没有执行的原因?

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

    stm32FREERTOS的延时函数osDelayUntil()死机的原因?

    我在使用STM32F4跑freertos的时候发现一旦使用osDelayUntil()函数,就会死机,但是用osDelay()函数就不会,按理说不是都可以用的吗?有知道原因的吗,谢谢!
    发表于 03-22 07:56

    STM32F767ZGT6改IAP后HAL_Delay卡死,定时器不进中断,直到freeRTOS初始化才开始中断,为什么?

    以后程序卡在HAL_Delay里,在定时器中断中加串口打印发现应该是定时器一直没有开启导致计数,应该MX_FREERTOS_Init()以及osKernelStart执行完以后才开启的定时器, 我把
    发表于 03-21 06:13

    STM32使用__disable_irq()后就无法使用HAL_Delay(xx),这是为什么?

    __enable_irq();//打开所有中断但实际应用中发现,当使用__disable_irq(); 关闭所有中断后,再用__enable_irq();打开所有中断,就会出现HAL_Delay(xx)不能再使用,所以直接用上述方式也不可取。那么,究竟该如何正确地的关闭和开启SysTick的中断呢?
    发表于 12-03 09:09

    用AD7787作为AD芯片AIN1频道没问题,但是AIN2失败了的原因?

    = AD7787_Read(AD7787_CH1);/ad7787_ch1=0011 000 000 hal_delay( 10) ; = AD7787_Read(AD7787_CH2);/ad7787_ch2
    发表于 12-01 06:43

    HAL库常用函数汇总

    1,系统函数HAL_Delay原型:voidHAL_Delay(uint32_tDelay);作用:利用滴答定时器生成的系统延迟函数参数:Delay:延迟时间,单位是ms返回值:无示例代码
    的头像 发表于 11-29 08:00 2982次阅读
    <b class='flag-5'>HAL</b>库常用函数汇总