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

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

    关注

    114

    文章

    3631

    浏览量

    79553
  • RTOS
    +关注

    关注

    20

    文章

    776

    浏览量

    118800
  • FreeRTOS
    +关注

    关注

    12

    文章

    473

    浏览量

    61351
  • 线程
    +关注

    关注

    0

    文章

    490

    浏览量

    19500
收藏 人收藏

    评论

    相关推荐

    STM32F103VE运行的STM32CubeMX生成的freertos工程,FreeRTOS堆栈设置导致任务不执行切换怎么解决?

    ); osDelay(200); } } void task2_task(void *pvParameters) { while(1) { HAL_GPIO_TogglePin(GPIOD,LED1_Pin
    发表于 04-26 07:51

    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烧写程序后出现Break at address\"0x1ff0a752\",程序卡死怎么解决?

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

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

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

    根据AD7916时序配置3线无繁忙提示读不到信号是为什么?

    根据AD7916时序配置3线无繁忙提示读不到信号 无效的 AD_ read( 撤销) { 8 吨 = 0; adc_nss(1); adc_cnv(1); hal_delay(2
    发表于 12-01 16:07

    AD7916无法采集电源,SDO输出一直都低电平的原因?怎么处理?

    ; adc_nss(1); adc_cnv(1); hal_delay(3); ad_cnv(0); hal_delay(1); for(cnt = 0; cnt < 16
    发表于 12-01 15:47

    用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 665次阅读
    <b class='flag-5'>HAL</b>库常用函数汇总

    FreeRtos和ucos的区别

    FreeRtos和ucos的区别?先从那个入手好?
    发表于 10-18 08:15

    STM32 HAL库的功能和使用方法 STM32 HAL库和标准库的区别

    和可维护性,从而节省开发成本和时间。STM32 HAL库是STM32系列芯片的HAL库,由ST公司提供和维护。下面将介绍STM32 HAL库的功能、使用方法以及与标准库的区别
    发表于 08-08 18:21 2288次阅读