RT-Thread论坛
直播中

张娟

8年用户 2248经验值
私信 关注
[问答]

在rtthread的main函数里用HAL_Delay函数不起作用是哪里的问题?

在rtthread的main函数里用HAL_Delay函数无效,我设置延时500ms打印一次,但是实际上,一秒打印了几百次,很显然是HAL_Delay出现了问题。用RT_thread_mdelay函数就没有这个问题。
求大佬提供解决方法
CUBMX选的timbase source时钟源选的是Systick,优先级是15


main函数里代码如下

运行结果如下(一秒打印了几百个Hello RT-Thread!)



回帖(2)

李煜启

2025-9-15 16:50:32

  • hal_delay是弱定义函数,查看一下是否在其他地方被意外重定义了
举报

丁冬芹

2025-9-17 17:46:24

问题分析


在 RT-Thread 的 main() 函数中使用 HAL_Delay() 失效的根本原因是:RT-Thread 在启动调度器后接管了 Systick 中断,导致 HAL 库的时钟计数器停止更新。而 rt_thread_mdelay() 使用 RT-Thread 自己的时钟系统,因此能正常工作。




解决方法


✅ 方案一:重写 HAL_GetTick()(推荐)


这是最直接的解决方案,让 HAL 库直接使用 RT-Thread 的时钟源:


// 在 main.c 或其他文件中添加以下代码
uint32_t HAL_GetTick(void) {
    // 将 RT-Thread 的 tick 转换为毫秒
    return (rt_tick_get() * 1000) / RT_TICK_PER_SECOND;
}

原理



  • rt_tick_get() 获取 RT-Thread 的系统时钟节拍数。

  • RT_TICK_PER_SECOND 是每秒的节拍数(默认为 1000)。

  • 通过公式将节拍转换成毫秒时间,使 HAL_Delay() 依赖正确的时钟。




✅ 方案二:确保 Systick 中断由 HAL 管理(适用于调度器启动前)


如果需要在 调度器启动前(如初始化阶段)使用 HAL_Delay()



  1. rtthread_startup() 前调用 HAL_Init()
    int main(void) {
       HAL_Init(); // 初始化 HAL 库时钟
       rtthread_startup(); // 启动 RT-Thread 调度器
       // ...后续代码
    }

  2. rt_hw_board_init() 中初始化 HAL 时钟(在 board.c 文件):
    void rt_hw_board_init() {
       HAL_Init();        // 初始化 HAL
       SystemClock_Config(); // 配置系统时钟(由 STM32CubeMX 生成)
       // ...其他硬件初始化
    }




✅ 方案三:替换为 RT-Thread 的延时函数(最佳实践)


强烈建议在 RT-Thread 线程中使用原生延时函数


#include 

int main(void) {
    while (1) {
        rt_kprintf("Hello RT-Thread!n");
        rt_thread_mdelay(500); // 使用 RT-Thread 的毫秒延时
    }
    return 0;
}

优势



  • 兼容 RT-Thread 的调度器,避免阻塞整个系统。

  • 无需修改底层 HAL 库代码。




注意事项




  1. 优先级冲突



    • 确保 Systick 中断优先级(默认优先级最低)不被其他高优先级中断阻塞。

    • 检查 RT_TICK_PER_SECOND(在 rtconfig.h 中)是否合理(通常为 1000)。




  2. 调试建议



    • 检查 uwTick 变量(HAL 时钟计数器)是否在中断中更新:
      void SysTick_Handler(void) {
      // RT-Thread 接管后此处变为 rt_tick_increase()
      HAL_IncTick(); // 如果保留此行,HAL_Delay() 可能恢复工作
      rt_tick_increase();
      }

      注意:同时调用两者可能导致时钟混乱,通常二选一。







总结



























方案 适用场景 优点
重写 HAL_GetTick() 需兼容 HAL 驱动代码 无需修改现有 HAL_Delay() 调用
确保 HAL 初始化 调度器启动前的初始化阶段 解决初始化阶段延时问题
改用 rt_thread_mdelay 通用 RT-Thread 应用开发 符合 RTOS 规范,避免调度阻塞

推荐实践



  • 在 RT-Thread 线程中 统一使用 rt_thread_mdelay

  • 如需在 HAL 驱动中使用 HAL_Delay(),采用 方案一重写 HAL_GetTick()



通过以上任一方案均可解决 HAL_Delay() 失效问题。优先推荐使用 RT-Thread 原生延时函数以确保系统稳定性。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分