乐趣区

关于操作系统:RTThread学习笔记-3RTThread自动初始化机制分析

置信不少工程师在浏览 RT-Thread 相干源代码的时候,都会常常看到如下图所示的宏定义,依照宏定义的命名来了解,这些宏定义仿佛都是对一些初始化函数进行某些申明工作。

如上图所示,通过对源码的跟踪发现,这些 INIT_XXX_EXPORT 的宏定义,最终都是调用了 INIT_EXPORT 这个宏定义,而这个宏定义,就是把该初始化函数放在自定义的 rti_fn 符号段外面,源码在 rtdef.h 头文件外面,如下图所示。

把初始化函数放到自定义的符号段外面,有什么作用呢?答案就是,能够通过这种形式,让这些初始化函数被隐式调用,不必手动往 RT-Thread 的初始化过程外面增加该函数。

什么是隐式调用?隐式调用的意思就是,当咱们往工程代码外面增加某个零碎组件或外接设备的时候,这个组件或设施都须要进行初始化,而这个初始化函数,咱们不须要在 main 函数或 RT-Thread 的启动函数外面间接增加调用,这样能够防止批改 RT-Thread 的启动过程代码。

先来看一下 RT-Thread 的启动函数调用流程,注意红色方框外面的内容,如下图所示。

启动函数外面,有两个函数:rt_components_board_init() 与 rt_components_init() 是专门用来解决主动初始化的,这两个函数的原型和正文,如下图所示。

从下面的函数原型能够看出,这两个函数都是从符号段区间外面,通过 for 循环不断遍历符号段外面的初始化函数,并获取这些初始化函数的指针,而后进行调用,以达到对设施或组件初始化的目标。

rt_components_board_init() 函数最先执行,这个函数是用来初始化芯片相干的硬件的,这个函数会遍历用 INIT_BOARD_EXPORT(fn) 申明的函数列表。

rt_components_init() 函数是在系统启动后,在 main 线程外面被调用执行,这个函数是用来初始化其余用 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 关键字,把初始化函数增加到相应的符号段即可。
https://club.rt-thread.org/as…
感激浏览!

原文链接:https://club.rt-thread.org/as…

退出移动版