Fork me on GitHub

RT-Thread学习1 —— RT-Thread的启动流程

RT-Thread学习1 —— RT-Thread的启动流程

1. 《RT-Thread 编程指南》中的启动流程图示:

image

2. 学习笔记:

1. 以GCC为例的理解记录——汇编阶段

​ 系统上电后先从汇编代码startup_stm32f403xe.s开始执行。文件目录如图:

image

根据《Cortex‐M3 权威指南 》中对向量表的描述所示,系统在开机的时候会通过 NVIC 中的一个重定位寄存器来指出向量表的地址。在复位后该寄存器的值为0,所以在地址0出必须包含一张向量表,用于初始化的异常分配。向量表结构:
image
image

开机后会把第一个MSP初始值赋值给指针SP,然后PC指向第二个地址内容。在startup_stm32f103xe.s中可以看到第二个地址指向Reset_Handle
image

跳转进Reset_Handle后看到

image

(坑1:汇编语言不太了解,后面补充),接着跳转到LoopCopyDataInit

image

(坑1:汇编语言不太了解,后面补充),接着跳转到LoopFillZerobss

image

(坑1:汇编语言不太了解,后面补充),接着先执行了SystemInit

image

这个函数进行一些系统时钟的配置,然后返回到LoopFillZerobss跳转到entry函数
image

然后跳转到了rtthread_startup函数进行main前的初始化工作
image

2. 以GCC为例的理解记录——C语言阶段

1. rt_hw_interrupt_disable()

rt_hw_interrupt_disable(); --> .global rt_hw_interrupt_disable(context_gcc.S)
image

PRIMASK特殊功能寄存器用于除能在 NMI 和硬 fault 之外的所有异常,它有效地把当前优先级改为 0(可编程优先级中的最高优先级) 这是个只有 1 个位的寄存器。当它置 1 时, 就关掉所有可屏蔽的异常,只剩下 NMI 和硬 fault 可以响应。它的缺省值是 0,表示没有关中断。《Cortex‐M3 权威指南 》

2. rt_hw_board_init()
rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END);

​ 初始化heap memory。组成链表结构的内存块。

hw_board_init(BSP_CLOCK_SOURCE, BSP_CLOCK_SOURCE_FREQ_MHZ, BSP_CLOCK_SYSTEM_FREQ_MHZ);

​ 初始化时钟,Pin,Usart。

rt_console_set_device(RT_CONSOLE_DEVICE_NAME);

​ 初始化console串口是不是一开始设置的口。

rt_components_board_init();

​ 便利所有INIT_BOARD_EXPORT(fn) 声明的函数进行初始化。

rt_show_version();

​ 显示编译的时间和版本信息等。

rt_system_timer_init();

​ 初始化_timer_list中的timer。 坑2:timer_list没看到在哪赋值

rt_system_scheduler_init();

​ 初始化rt_thread_priority_table中的内容。 坑3:rt_thread_priority_table没看到在哪赋值

rt_system_signal_init();

​ 初始化名叫“signal”的mempool。

rt_application_init();

​ 初始化“main”Task并且启动,但是在任务调度器开始前不会调度。

rt_system_timer_thread_init();

​ 初始化并启动软件定时器的Task。

rt_thread_idle_init();

​ 初始化IDLE的Task。

rt_system_scheduler_start(void);

​ 启动任务调度。main的Task执行rt_components_init();函数遍历所有申明的初始化函数。执行 main(void)函数

3. 学习函数
EXPORT_SYMBOL解析:

一般我们编写C程序时,要调用某个文件中的函数,需要在本文件中包含声明有被调用函数的头文件,然后编译连接后,方能找到调用函数。对于模块依赖的情况,不能简单的使用上面的方法,内核提供了一个机制,就是EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。您还可以手工修改内核源代码来导出另外的函数,用于重新编译并加载新内核后的测试。

3. 自动初始化机制

https://blog.csdn.net/sinat_31039061/article/details/104127274

posted @ 2022-03-07 13:40  一地鸡毛-  阅读(706)  评论(0编辑  收藏  举报