RT-Thread启动过程分析RT-Thread自动初始化机制分析
我相信,在阅读与RT-Thread相关的源代码时,许多工程师经常会看到下图所示的宏定义。
根据宏定义的命名,这些宏定义似乎对某些初始化函数进行了某些声明。
。
如上图所示,通过跟踪源代码,发现INIT_XXX_EXPORT的这些宏定义最终调用了INIT_EXPORT的宏定义,该宏定义是将初始化函数放在自定义rti_fn符号部分中,即源代码位于rtdef.h头文件中,如下图所示。
将初始化功能放在自定义符号部分有什么作用?答案是,可以通过这种方式隐式调用这些初始化函数,而不是将其手动添加到RT-Thread初始化过程中。
什么是隐式调用?隐式调用意味着当我们将系统组件或外部设备添加到项目代码中时,需要初始化该组件或设备,并且使用此初始化函数,我们不需要直接在其中启动主函数或RT-Thread Add调用。
该函数,这样就可以避免修改RT-Thread启动过程代码。
首先让我们看一下RT-Thread的启动函数调用流程,注意红色框中的内容,如下图所示。
在启动函数中,两个函数rt_components_board_init()和rt_components_init()特别用于处理自动初始化。
下图显示了这两个函数的原型和注释。
从上面的函数原型可以看出,这两个函数是从符号段间隔开始的,通过for循环遍历符号段中的初始化函数,并获取这些初始化函数的指针,然后调用来实现设备或组件初始化的目的。
首先执行rt_components_board_init()函数。
此功能用于初始化与芯片相关的硬件。
该函数将遍历用INIT_BOARD_EXPORT(fn)声明的函数列表。
系统启动后,将在主线程中调用并执行rt_components_init()函数。
该函数用于初始化用INIT_XXX_EXPORT(fn)声明的其他函数的列表。
当前,下图显示了用于在RT-Thread内核中实现自动初始化功能的宏定义接口。
综上所述,要使用RT-Thread的自动初始化过程,可以概括为以下步骤,如图所示。
为什么在添加符号部分后可以自动调用初始化函数?什么是符号段?使用此方法有什么好处?向符号部分添加函数实际上是使用MDK编译器的__attribute __((section(x)))关键字来声明该函数。
当链接编译器时,将使用通过section关键字声明的函数。
这些功能将被自动收集并将其放置在集中区域,请检查以下.map文件以了解这些功能。
如上面的红色框所示,rt_hw_pin_init和rt_hw_usart_init都是使用INIT_BOARD_EXPORT(fn)声明的函数。
因此,它们存储在橙色垂直线所在的间隔中。
使用rt_components_board_init()函数可以遍历此间隔。
如上面的蓝色和绿色框所示,它们分别是用INIT_COMPONENT_EXPORT(fn)和INIT_APP_EXPORT(fn)声明的函数。
这些功能存储在红色垂直线所在的间隔中。
您可以使用rt_components_init()函数来控制此间隔。
遍历。
从以上分析可以看出,使用符号段存储初始化函数的优点是,当我需要添加某个初始化函数时,无需直接通过以下方式更改RT-Thread启动代码。
section关键字,将初始化函数添加到相应的符号部分。
以上是对RT-Thread自动初始化机制的分析。
由于这种机制,当我们定制内核或组件时,我们不需要修改RT-Thread的初始化功能,而是可以初始化组件。
。