Skip to content

两个特殊的任务

李述铜

983字约3分钟

2025-08-30

除用户自己创建的任务外,RT-Thread会自动创建两个特殊任务:main和 空闲任务

  • main任务:系统主任务,用于执行main函数
  • 空闲任务:当系统中没有其他就绪任务时运行

main任务

在RT-Thread 中,用户应用程序的main()函数并不是系统启动入口,而是作为一个线程(任务)被启动。

该任务是在系统调度器启动后由内核自动创建并运行的第一个任务。该任务由rt_application_init()创建(支持静态和动态两种方式)。

 */
void rt_application_init(void)
{
    rt_thread_t tid;

#ifdef RT_USING_HEAP
    tid = rt_thread_create("main", main_thread_entry, RT_NULL,
                           RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(tid != RT_NULL);
#else
    rt_err_t result;

    tid = &main_thread;
    result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
                            main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(result == RT_EOK);

    /* if not define RT_USING_HEAP, using to eliminate the warning */
    (void)result;
#endif /* RT_USING_HEAP */

    rt_thread_startup(tid);
}

该任务主要用于系统初始化后的主流程(初始化驱动、创建其他线程、启动主程序逻辑等)。在完成必要的工作之后,可以从main()返回,也可继续完成其它工作。比如增加一个while(1)循环,实现某个模块的功能。

配置参数

main任务的相关配置参数(如优先级、栈大小)放在rt_config.h中,用户可根据自己的需要进行修改。

#define RT_MAIN_THREAD_STACK_SIZE   2048     // 主线程栈大小
#define RT_MAIN_THREAD_PRIORITY     10       // 主线程优先级

空闲任务

空闲任务主要用于实现以下功能:

  • 系统空闲处理:节省CPU,或进入低功耗
  • 资源回收:清理已被删除的动态线程(动态任务的资源由空闲任务统一释放)
  • 钩子支持:可以注册钩子函数做低优先级处理工作

相关实现代码如下。

static void rt_thread_idle_entry(void *parameter)
{
#ifdef RT_USING_SMP
    if (rt_hw_cpu_id() != 0)
    {
        while (1)
        {
            rt_hw_secondary_cpu_idle_exec();
        }
    }
#endif /* RT_USING_SMP */

    while (1)
    {
#ifdef RT_USING_IDLE_HOOK
        rt_size_t i;
        void (*idle_hook)(void);

        for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
        {
            idle_hook = idle_hook_list[i];
            if (idle_hook != RT_NULL)
            {
                idle_hook();
            }
        }
#endif /* RT_USING_IDLE_HOOK */

#ifndef RT_USING_SMP
        rt_defunct_execute();
#endif /* RT_USING_SMP */

#ifdef RT_USING_PM
        void rt_system_power_manager(void);
        rt_system_power_manager();
#endif /* RT_USING_PM */
    }
}

void rt_thread_idle_init(void)
{
    rt_ubase_t i;
    char tidle_name[RT_NAME_MAX];

    for (i = 0; i < _CPUS_NR; i++)
    {
        rt_sprintf(tidle_name, "tidle%d", i);
        rt_thread_init(&idle[i],
                tidle_name,
                rt_thread_idle_entry,
                RT_NULL,
                &rt_thread_stack[i][0],
                sizeof(rt_thread_stack[i]),
                RT_THREAD_PRIORITY_MAX - 1,
                32);
#ifdef RT_USING_SMP
        rt_thread_control(&idle[i], RT_THREAD_CTRL_BIND_CPU, (void*)i);
#endif /* RT_USING_SMP */
        /* startup */
        rt_thread_startup(&idle[i]);
    }

#ifdef RT_USING_SMP
    RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2);

    rt_sem_init(&system_sem, "defunct", 1, RT_IPC_FLAG_FIFO);

    /* create defunct thread */
    rt_thread_init(&rt_system_thread,
            "tsystem",
            rt_thread_system_entry,
            RT_NULL,
            rt_system_stack,
            sizeof(rt_system_stack),
            RT_THREAD_PRIORITY_MAX - 2,
            32);
    /* startup */
    rt_thread_startup(&rt_system_thread);
#endif
}

缺省情况下,空闲任务是自动创建的最低优先级任务,从而实现在没有其他任务就绪运行时执行。此外,默认的栈大小由IDLE_THREAD_STACK_SIZE配置,用户可根据自己的实现需要进行修改。

注册空闲钩子

我们可以将自定义的处理函数注册为空闲任务钩子,从而让空闲任务能够在自己的循环中调用。通过该功能,可以实现LED心跳、CPU 空闲统计等功能。

void my_idle_hook(void)
{
    led_toggle(LED0);   // 模拟低功耗处理或LED指示
}
RT_WEAK void rt_hw_idle_hook(void)  // 若硬件中已有定义,可重写
{
    my_idle_hook();
}

int hook_init(void)
{
    rt_thread_idle_sethook(my_idle_hook);
    return 0;
}
INIT_APP_EXPORT(hook_init);

具体要实现什么的功能,请根据实际项目的需要来决定。简单来说,就是在里面完成一些很不重要、优先级非常低的功能。

空闲任务禁止运行

根据RT-Thread的内部设计方式,除非CPU进入低功耗模式,否则必须运行一个任务。此外,空闲任务还承担着回收任务资源的操作。

因此,在空闲任务中,不能执行任何可能让该任务暂停运行的操作(CPU进入低功耗模式除外),例如:延迟(rt_thread_mdelay())、挂起(rt_thread_suspend())以及事件等待的操作。

也就是说,当其它高优先级任务都暂停运行时,空闲任务必须“一直忙个不停”,绝对“禁止停下来”。