RT-Thread 启动过程
目录
RTT(RT-Thread)内核启动流程详解
前言
RTT 内核启动流程
启动流程概述
汇编阶段
C 阶段
1、entry 入口
2、进入 rtthread_startup 函数
3、创建主线程
RTT(RT-Thread)内核启动流程详解
前言
与STM32裸机启动流程一样,RT-Thread启动流程分为汇编阶段和C阶段。首先在汇编代码里面去创建好C语言执行的环境,然后调用系统初始化函数把我们的系统进行初始化(其中就包括了系统时钟的初始化),初始化完成以后就进入了C语言的main函数入口。不过RTT在进入main函数之前还做了对系统内核一些功能的初始化。
RTT 内核启动流程
RT-Thread 支持多种平台和多种编译器,而 rtthread_startup() 函数是 RT-Thread 规定的统一启动入口。一般执行顺序是:系统先从启动文件开始运行,然后进入 RT-Thread 的启动 rtthread_startup() ,最后进入用户入口 main(),如下图所示:(RT-Thread Studio使用的是GCC编译器)
启动流程概述
启动的第一阶段从启动汇编代码开始执行,我们的编译环境一共有三种
分别为 MDK(如 Keil 5)、IAR、GCC(如 VScode、CLion 等),不同开发工具调用的函数都是不一样的,不过它们最终的结果都是进入到 rtthread_startup 函数里执行。
我们使用的编译软件是 RT Thread Stduio,它使用的是 GCC 编译环境,它执行完启动文件,然后经过入口函数 entry ()以后,最终调用了 rtthread_startup 函数
在 rtthread_startup 函数里首先,执行 rt_hw_interrupt_disable,关闭所有的硬件中断;
然后分别执行
``
rt_hw_board_init:初始化板子相关的硬件外设
rt_show_version:调用显示版本函数
rt_system_timer_init:系统定时器初始化
rt_system_scheduler_init:系统线程调度器初始化
rt_system_signal_init:系统信号初始化
rt_application_init:应用层初始化
rt_system_timer_thread_init:定时器线程初始化
rt_thread_idle_init:空闲线程的初始化
``
最后执行 rt_system_scheduler_start,启动系统线程调度器,执行相关线程
在应用层初始化函数、系统定时器线程初始化函数、空闲线程函数中分别创建了三个线程,然后当我们的线程调度器工作以后就会调度这三个线程去执行(其中 idle 线程的优先级最低)
在我们的主线程入口,会对组件进行初始化,同时最终会跳转到用户定义的 main 函数中
汇编阶段
1 | Reset_Handler: //复位 |
主要过程:
- 从 Flash 中拷贝数据段到 SRAM 中
- 清空 BSS 段(BSS 段清零),创建好 C 语言的开发环境,由于 C 语言的全局未初始化的变量是放在 BSS 段的,因此打印未初始化的全局变量,值是0
- 初始化系统时钟(SystemInit)
我们首先在 board. h 中设置好时钟
最终调用 SystemInit 进行初始化
- 进入 entry 入口
C 阶段
【1】系统时钟初始化
system_stm 32 f 1 xx. c 中的系统初始化函数,参考之前章节内容
时钟系统配置文件 board.h
使用外部高速时钟,时钟源晶振 8 MHz,系统时钟 72 MHz
1、entry 入口
1 | int entry(void) |
2、进入 rtthread_startup 函数
1 | int rtthread_startup(void) |
主要过程:
初始化系统相关硬件
初始化系统内核对象、例如定时器、调度器、信号
创建主线程、定时器线程、idle 线程
启动调度器
其中:
rt_hw_board_init:初始化向量表,初始化时钟,始化板级硬件,初始化 console,初始化堆栈rt_show_version:打印 RT-Thread 版本信息rt_system_timer_init:定时器链表初始化rt_system_scheduler_init:初始化调度器,即线程优先级链表rt_application_init:创建开始 main 进程 (优先级 10,tick 10)rt_system_timer_thread_init:创建开始定时器进程(优先级 4,tick 10)
定时器线程代码:
1 | static void _timer_thread_entry(void *parameter) |
rt_thread_idle_init:创建开始空闲进程(最低优先级,tick 32)rt_system_scheduler_start:启动调度器,开始按照线程优先级链表执行调度
3、创建主线程
在应用层初始函数中调用线程创建函数创建主线程,其中通过条件编译,有两种创建线程的方法:如果使用堆,就用动态的方法来创建线程 (rt_thread_create ());如果不使用堆,就使用静态的方法来创建线程(rt_thread_init ())
第二个参数为函数指针
然后通过 rt_thread_startup ()启动线程
一旦主线程启动,就会执行 main_thread_entry 函数,最终就会跳转到用户自己定义的 main 函数中
线程函数入口:main_thread_entry
栈大小:2048
优先级:10
同等优先级时间片轮询时间:20 个 OS Tick rfconfig. h 中配置 :
1 |
Tick 每秒 1000 次,一次的时间为 1 ms
1 | //创建线程,线程函数main_thread_entry |
在主线程启动过程中,通过 rt_components_init 实现组件外设的[[自动初始化]],完成后跳转到用户 main 函数
#todo
#启动流程
#初始化
























