RT-Thread 自动初始化机制
1、自动初始化机制简介
在系统启动流程图中,有两个函数:rt_components_board_init() 与 rt_components_init(),其后的带底色方框内部的函数表示被自动初始化的函数,其中:
“board init functions” 为所有通过 INIT_BOARD_EXPORT(fn) 申明的初始化函数。 “pre-initialization functions” 为所有通过 INIT_PREV_EXPORT(fn)申明的初始化函数。 “device init functions” 为所有通过 INIT_DEVICE_EXPORT(fn) 申明的初始化函数。 “components init functions” 为所有通过 INIT_COMPONENT_EXPORT(fn)申明的初始化函数。 “enviroment init functions” 为所有通过 INIT_ENV_EXPORT(fn) 申明的初始化函数。 “application init functions” 为所有通过 INIT_APP_EXPORT(fn)申明的初始化函数
用来实现自动初始化功能的宏接口定义详细描述如下表所示:
2、自动初始化机制原理
RT-Thread 的自动初始化机制使用了自定义 RTI 符号段,将需要在启动时进行初始化的函数指针放到了该段中,形成一张初始化函数表,在系统启动过程中会遍历该表,并调用表中的函数,达到自动初始化的目的。
进入任意一个宏定义,可以查看源码中的宏定义如下:
继续展开INIT_EXPORT(fn, level) 如下:
其中##代表连接符,把__rt_init_与fn这个形参名字链接起来,即__rt_init_fn
查看init_fn_t的定义如下:
表示用typedef 定义了一个函数指针类型,init_fn_t _rt_init##fn SECTION(".rti_fn." level) = fn表示定义了一个函数指针变量,并初始化,把fn这个函数的地址赋给__rt_init_fn这个函数指针。
其中SECTION(".rti_fn." level)展开如下:
_attribute_((section(“name”))) :将作用的函数或数据放入指定名为"name"的输入段中。(在不同的编译器中实现的方式也有所不同。)
总结:作用就是将函数 fn 的地址赋给一个 __rt_init_fn 的指针,然后放入相应 level 的数据段中。所以函数使用自动初始化宏导出后,这些数据段中就会存储指向各个初始化函数的指针。
3、自动初始化机制过程
在程序启动后,会分别运行 rt_components_board_init() 与 rt_components_init() 函数,其中 rt_components_board_init()完成了第1段的初始化,rt_components_init()完成了2到6段的初始化。
1、第一个函数 rt_components_board_init() 的实现:
2、第二个函数 rt_components_board_init() 的实现:
其中__rt_init_rti_board_start,__rt_init_rti_board_end,__rt_init_rti_end表示不同的区间段。
在系统中,定义了这几个空函数:rti_start、rti_board_start、rti_board_end、rti_end。划分成不同的段:0、 0.end 、 1.end 、6.end。
自定义的初始化函数就夹裹在这些段内。
这几个函数的导出,加上上面 6 个初始化宏的导出,就有了这样一个表格:
查看map文件可知:
其中__rt_init_finsh_system_init 为内核shell的初始化:
|