一、前言我们知道RTThread默认保底有3条线程main线程空闲线程还有最近学的定时器线程我们也知道RTThread默认有很多链表定时器链表、挂起链表、就绪链表的链表数组这些以及优先级位图信号量与互斥量等线程基础杂项我们虽然总是使用但是不清楚它们是怎么来的所以今天分析一下。二、RTThread的启动过程这是官方那里拿的RTThread启动过程。我们主要看懂这个过程就行了首先startup_xx.s 是芯片厂家给出的汇编启动文件比如startup_stm32.s、startup_GD32.s然后根据编译器的不同最终进入的入口不一样但是不管哪一个入口最终都会进入rtthread_startup()这个函数里面rtthread_startup()就负责完成整个工程的初始化和启动。rtthread_startup()函数详解rtthread_startup()是核心启动整个项目的函数。第一步调用rt_hw_interrupt_disable()关闭全局中断因为操作系统正在做核心初始化此时内核数据结构就绪队列、线程控制块等还不完整。如果此时触发中断中断服务函数有可能访问未初始化完成的内核变量造成系统崩溃。 关闭全局中断保证后面一长串系统初始化代码可以原子执行不受任何中断干扰。等系统初始化完成、调度器启动之后中断才会重新打开。第二步调用rt_boarad_init()负责最底层单板硬件初始化属于板级层面注意不是外设驱动。主要工作配置芯片系统主时钟、初始化调试串口控制台、基础 GPIO同时执行所有标记INIT_BOARD_EXPORT的初始化函数。⚠️注意这里不会初始化 ADC、PWM、SPI 这类外设驱动。这一步在调度器启动之前只保证基础硬件可以工作让后续内核能够打印日志。第三步通过上面初始化好的调试串口输出 RT-Thread 版本、编译器、芯片架构等开机日志。也就是我们串口上电最先看到的那一段版本字符串。第四步rt_system_timer_init()配置 SysTick系统滴答定时器产生周期性的滴答中断tick。tick 是 RT-Thread 的时间基准线程延时、软件定时器、时间片轮转全都依赖这个定时器。第五步rt_system_scheduler_init()对调度器的初始化并且就绪链表和优先级位图就是在这里初始化的。第六步rt_system_signal_init()对线程信号相关内容初始化。第七步调用rt_thread_init(main_thread_entry)构造 main 线程的线程控制块 TCB。但是只是创建线程还没有启动调度器并不会运行。main_thread_entry 是 main 线程真正入口函数进入这个函数后会调用rt_components_init()依次执行INIT_DEVICE_EXPORT、INIT_COMPONENT_EXPORT等宏导出的函数ADC/PWM 等外设驱动就在这里自动初始化、注册到设备模型所有组件初始化完成之后才调用 $Super$$main()最终进入我们用户编写的main()业务函数。所以我们平时见到的main函数不是一个线程只是main线程调用的一个函数。第八步rt_system_timer_thread_init()初始化并创建 timer 线程线程入口是rt_thread_timer_entry。第九步rt_thread_idle_init ()创建 idle 线程优先级最低。到这一步main 线程、timer 线程、idle 线程三个系统核心线程全部创建完成全部挂入就绪队列。但调度器仍未启动所有线程都不会跑。第十步rt_system_scheduler_start ()最后一步在函数内部会打开全局中断然后启动调度器开始触发线程切换。自动初始化宏前面大家可能看到INIT_BOARD_EXPORT或者INIT_DEVICE_EXPORT、INIT_COMPONENT_EXPORT会不懂这是什么意思其实这叫做自动初始化宏。以INIT_BOARD_EXPORT为例如果我在一个函数的后面标记上了INIT_BOARD_EXPORT“填你要标记的函数名”意思就是我把这个函数标记成了板级初始化函数当系统启动到了板级初始化也就是上面的第二步就会自动调用被INIT_BOARD_EXPORT标记的函数方便初始化板子最基础的硬件。同理有很多这种类似的用法。只需要了解有这个东西即可。宏执行时机用途INIT_BOARD_EXPORT(fn)rt_components_board_init ()调度器启动前板级基础硬件时钟、调试串口、pinINIT_PREV_EXPORT(fn)rt_components_init ()main 线程内纯软件前置初始化INIT_DEVICE_EXPORT(fn)rt_components_init ()main 线程内ADC/PWM/UART/SPI 外设驱动注册初始化INIT_COMPONENT_EXPORT(fn)rt_components_init ()main 线程内文件系统、lwip 网络协议栈INIT_ENV_EXPORT(fn)rt_components_init ()main 线程内挂载文件系统、环境配置INIT_APP_EXPORT(fn)rt_components_init ()main 线程内应用层创建线程三、裸机的启动过程简单来说裸机和RTThread最开头的汇编启动步骤几乎一样栈初始化、数据段搬运、bss 清零这是芯片硬件要求的不管裸机还是 RTOS 都要做。裸机就是上电→汇编准备→直接进 main→死循环跑业务全程单线程RT-Thread 就是在裸机的基础上在进 main 之前先做了一整套操作系统内核初始化把单线程死循环变成了多线程调度还加了自动初始化、线程管理这些功能。