RT-Thread论坛
直播中

向日葵的花季

9年用户 1330经验值
擅长:电源/新能源
私信 关注
[问答]

rtthread一直卡在rt_thread_idle_entry()的原因?


我上面的代码中如果加入rt_thread_delay就一直卡在rt_thread_idle_entry空闲线程,如果去掉rt_thread_delay就能正常打印,请问这是怎么回事。我的RT_tiCK_PER_SECOND设置为1000,rt_thread_delay(1)应该只有1ms啊


回帖(2)

张林锋

2025-9-12 17:37:49
可以先排查一下SysTick中断有没有触发
举报

河神大人

2025-9-17 17:43:54

从你描述的现象来看,当加入 rt_thread_delay() 时系统卡在空闲线程,而移除后工作正常,这表明 系统时钟中断或调度机制未正常工作。以下是可能原因和解决方案:




? 根本原因分析




  1. 时钟中断未触发  



    • rt_thread_delay(1) 依赖系统时钟中断推进时间节拍(tick),若时钟中断未触发:

      • 系统无法感知时间流逝

      • 线程无法从阻塞态唤醒

      • 系统只能运行空闲线程 (idle_entry)


    • 验证方法:在 SysTick_Handler() 中断服务函数中放一个断点/打印,检查是否被触发。




  2. SysTick 中断配置错误  



    • board.crt_hw_board_init() 函数未正确初始化 SysTick 定时器

    • 示例缺失代码:
      void rt_hw_board_init()
      {
      // 确保调用以下关键初始化:
      SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);  // 配置SysTick频率
      // ...其他硬件初始化
      }




  3. 未调用 rt_tick_increase()

    即使 SysTick 中断触发,但若中断服务函数 未更新系统滴答,延时依然无效:


    void SysTick_Handler(void)
    {
       rt_interrupt_enter();    // 通知内核进入中断
       rt_tick_increase();      // <-- 必须调用此函数更新系统节拍!
       rt_interrupt_leave();    // 通知内核退出中断
    }



  4. 线程优先级问题  



    • 你的线程优先级可能设置过低(如 ≥ 空闲线程优先级 RT_THREAD_PRIORITY_MAX-1)

    • 一旦调用 delay() 挂起线程,系统无更高优先级线程可运行,只剩空闲线程。




  5. 堆栈溢出导致异常  



    • 线程堆栈过小,调用 rt_thread_delay 时函数调用链导致溢出

    • 检查是否定义了 RT_USING_OVERFLOW_CHECK 并在运行时观察日志输出






✅ 解决方案


步骤 1:验证 SysTick 中断配置


在板级初始化文件 board.c 中检查以下代码:


// 确保 SysTick 以正确频率初始化
void rt_hw_board_init()
{
    // 关键配置 ↓
    SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);

    // 启用RT-Thread的定时器框架
    rt_system_timer_init();
}

步骤 2:检查 SysTick 中断服务函数


drv_common.c 或中断向量表中定位中断服务函数:


void SysTick_Handler(void) 
{
    rt_tick_increase();  // 必须调用此函数!
}


⚠️ 注意:若使用标准库(如STM32 HAL),中断函数名可能为 SysTick_Handler(void);若为自定义名称,需在中断向量表中正确注册。



步骤 3:调整线程优先级


确保你的线程优先级 高于空闲线程


// 创建线程示例:优先级建议设为5~10 (数字越小优先级越高)
rt_thread_t thread = rt_thread_create(
    "test",
    thread_entry,
    RT_NULL,
    512,
    8,  // <-- 优先级设为8(必须 < RT_THREAD_PRIORITY_MAX-1)
    5
);

步骤 4:检查堆栈大小


增大线程堆栈排除溢出问题:


rt_thread_create(..., 1024, ...);  // 测试时堆栈从512增大到1024

步骤 5:补充系统初始化调用


确认在 main() 中正确启动了 RT-Thread 内核:


int main(void)
{
    rt_thread_startup(rt_thread_create( ... ));  // 启动主线程
    rt_system_scheduler_start();                 // 开始调度器 -> 某些BSP会封装在底层
}



? 调试建议




  1. 中断触发测试

    SysTick_Handler 中加入调试代码:


    void SysTick_Handler(void) {
       static int count = 0;
       rt_kprintf("[Tick] %dn", count++);  // 查看是否周期性打印
       rt_tick_increase();
    }

    若无输出,说明中断未触发或函数未正确注册。




  2. 查看线程状态

    使用 list_thread 命令(在 Finsh 控制台)观察线程状态:


    thread   pri  status      sp     stack size  max used
    ------   ---  -------     ---    ----------  --------
    tidle    31   ready       ...    0x200       12%
    your_thr 10   suspend     ...    0x400       35%  <-- 查看是否处于suspend态



  3. 检查系统时钟频率

    确认 RT_TICK_PER_SECOND 配置与硬件匹配:


    // rtconfig.h 中检查定义
    #define RT_TICK_PER_SECOND 1000  // 1 tick = 1ms





? 总结关键点
































问题现象 **可能原因」 修复方法
卡在空闲线程 SysTick中断未触发 初始化SysTick并注册中断服务函数
移除delay()后恢复正常 时间节拍未更新 在SysTick中断中调用 rt_tick_increase
线程无法唤醒 线程优先级 ≤ 空闲线程优先级 提高业务线程优先级
随机崩溃 线程堆栈溢出 增大堆栈并使用溢出检测工具

按照上述步骤逐一排查,重点检查 SysTick中断服务函数rt_tick_increase()调用,问题通常可快速解决。

举报

更多回帖

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