博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RT-Thread 进阶笔记之自动初始化机制
阅读量:4092 次
发布时间:2019-05-25

本文共 6117 字,大约阅读时间需要 20 分钟。

RT-Thread 自动初始化机制

1、自动初始化机制简介

在这里插入图片描述

在系统启动流程图中,有两个函数:rt_components_board_init() 与 rt_components_init(),其后的带底色方框内部的函数表示被自动初始化的函数,其中:

  1. “board init functions” 为所有通过 INIT_BOARD_EXPORT(fn) 申明的初始化函数。
  2. “pre-initialization functions” 为所有通过 INIT_PREV_EXPORT(fn)申明的初始化函数。
  3. “device init functions” 为所有通过 INIT_DEVICE_EXPORT(fn) 申明的初始化函数。
  4. “components init functions” 为所有通过 INIT_COMPONENT_EXPORT(fn)申明的初始化函数。
  5. “enviroment init functions” 为所有通过 INIT_ENV_EXPORT(fn) 申明的初始化函数。
  6. “application init functions” 为所有通过 INIT_APP_EXPORT(fn)申明的初始化函数
    用来实现自动初始化功能的宏接口定义详细描述如下表所示:
    在这里插入图片描述

2、自动初始化机制原理

RT-Thread 的自动初始化机制使用了自定义 RTI 符号段,将需要在启动时进行初始化的函数指针放到了该段中,形成一张初始化函数表,在系统启动过程中会遍历该表,并调用表中的函数,达到自动初始化的目的。

进入任意一个宏定义,可以查看源码中的宏定义如下:

/* board init routines will be called in board_init() function */#define INIT_BOARD_EXPORT(fn)           INIT_EXPORT(fn, "1")/* pre/device/component/env/app init routines will be called in init_thread *//* components pre-initialization (pure software initilization) */#define INIT_PREV_EXPORT(fn)            INIT_EXPORT(fn, "2")/* device initialization */#define INIT_DEVICE_EXPORT(fn)          INIT_EXPORT(fn, "3")/* components initialization (dfs, lwip, ...) */#define INIT_COMPONENT_EXPORT(fn)       INIT_EXPORT(fn, "4")/* environment initialization (mount disk, ...) */#define INIT_ENV_EXPORT(fn)             INIT_EXPORT(fn, "5")/* appliation initialization (rtgui application etc ...) */#define INIT_APP_EXPORT(fn)             INIT_EXPORT(fn, "6")

继续展开INIT_EXPORT(fn, level) 如下:

#define INIT_EXPORT(fn, level)                                                       \            RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn." level) = fn

其中##代表连接符,把__rt_init_与fn这个形参名字链接起来,即__rt_init_fn

查看init_fn_t的定义如下:

typedef int (*init_fn_t)(void);

表示用typedef 定义了一个函数指针类型,init_fn_t _rt_init##fn SECTION(".rti_fn." level) = fn表示定义了一个函数指针变量,并初始化,把fn这个函数的地址赋给__rt_init_fn这个函数指针。

其中SECTION(".rti_fn." level)展开如下:

#define SECTION(x)                  __attribute__((section(x)))

_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() 的实现:

void rt_components_board_init(void){
const init_fn_t *fn_ptr; for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++) {
(*fn_ptr)(); }}

2、第二个函数 rt_components_board_init() 的实现:

void rt_components_init(void){
const init_fn_t *fn_ptr; for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++) {
(*fn_ptr)(); }}

其中__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。
自定义的初始化函数就夹裹在这些段内。

static int rti_start(void){
return 0;}INIT_EXPORT(rti_start, "0");static int rti_board_start(void){
return 0;}INIT_EXPORT(rti_board_start, "0.end");static int rti_board_end(void){
return 0;}INIT_EXPORT(rti_board_end, "1.end");static int rti_end(void){
return 0;}INIT_EXPORT(rti_end, "6.end");

这几个函数的导出,加上上面 6 个初始化宏的导出,就有了这样一个表格:

在这里插入图片描述
查看map文件可知:
在这里插入图片描述
其中__rt_init_finsh_system_init 为内核shell的初始化:

int finsh_system_init(void){
rt_err_t result = RT_EOK; rt_thread_t tid;#ifdef FINSH_USING_SYMTAB#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM C Compiler */ extern const int FSymTab$$Base; extern const int FSymTab$$Limit; extern const int VSymTab$$Base; extern const int VSymTab$$Limit; finsh_system_function_init(&FSymTab$$Base, &FSymTab$$Limit);#ifndef FINSH_USING_MSH_ONLY finsh_system_var_init(&VSymTab$$Base, &VSymTab$$Limit);#endif#elif defined (__ICCARM__) || defined(__ICCRX__) /* for IAR Compiler */ finsh_system_function_init(__section_begin("FSymTab"), __section_end("FSymTab")); finsh_system_var_init(__section_begin("VSymTab"), __section_end("VSymTab"));#elif defined (__GNUC__) || defined(__TI_COMPILER_VERSION__) /* GNU GCC Compiler and TI CCS */ extern const int __fsymtab_start; extern const int __fsymtab_end; extern const int __vsymtab_start; extern const int __vsymtab_end; finsh_system_function_init(&__fsymtab_start, &__fsymtab_end); finsh_system_var_init(&__vsymtab_start, &__vsymtab_end);#elif defined(__ADSPBLACKFIN__) /* for VisualDSP++ Compiler */ finsh_system_function_init(&__fsymtab_start, &__fsymtab_end); finsh_system_var_init(&__vsymtab_start, &__vsymtab_end);#elif defined(_MSC_VER) unsigned int *ptr_begin, *ptr_end; if(shell) {
rt_kprintf("finsh shell already init.\n"); return RT_EOK; } ptr_begin = (unsigned int *)&__fsym_begin; ptr_begin += (sizeof(struct finsh_syscall) / sizeof(unsigned int)); while (*ptr_begin == 0) ptr_begin ++; ptr_end = (unsigned int *) &__fsym_end; ptr_end --; while (*ptr_end == 0) ptr_end --; finsh_system_function_init(ptr_begin, ptr_end);#endif#endif#ifdef RT_USING_HEAP /* create or set shell structure */ shell = (struct finsh_shell *)rt_calloc(1, sizeof(struct finsh_shell)); if (shell == RT_NULL) {
rt_kprintf("no memory for shell\n"); return -1; } tid = rt_thread_create(FINSH_THREAD_NAME, finsh_thread_entry, RT_NULL, FINSH_THREAD_STACK_SIZE, FINSH_THREAD_PRIORITY, 10);#else shell = &_shell; tid = &finsh_thread; result = rt_thread_init(&finsh_thread, FINSH_THREAD_NAME, finsh_thread_entry, RT_NULL, &finsh_thread_stack[0], sizeof(finsh_thread_stack), FINSH_THREAD_PRIORITY, 10);#endif /* RT_USING_HEAP */ rt_sem_init(&(shell->rx_sem), "shrx", 0, 0); finsh_set_prompt_mode(1); if (tid != NULL && result == RT_EOK) rt_thread_startup(tid); return 0;}INIT_APP_EXPORT(finsh_system_init);

转载地址:http://jdnii.baihongyu.com/

你可能感兴趣的文章
编程差的程序员,90%都是吃了数学的亏!骨灰级开发:方法不对,努力也白费...
查看>>
编程差的程序员,90%都是吃了数学的亏!骨灰级开发:方法不对,努力也白费...
查看>>
都无代码了,还要程序员吗?
查看>>
程序员:凭自己能力吃饭,有什么理由瞧不起?
查看>>
面试想拿 10K,HR 说我只配7k?
查看>>
副业过万的程序员都知道的网站有哪些
查看>>
那些人生“开挂”的程序员,都在干什么?
查看>>
影响科学圈的那些计算机代码
查看>>
乐视视频 App 图标改为“欠 122 亿”,网友:我在别家分红包,却在你家随份子!...
查看>>
乔布斯18岁求职信拍卖价22.24万美元,值吗?
查看>>
为何程序员总喜欢写技术博客,看完恍然大悟...
查看>>
大学辍学、自学编程,GitHub 创始人是怎么号召 2800 万程序员的?
查看>>
为什么我抛弃了 Ubuntu?
查看>>
GitHub 标星 2.7w+!超全大厂面试笔记整理!
查看>>
牛逼!这款神器能在浏览器跑 VS Code,让你随时随地写代码!
查看>>
推荐一位 10w+ 粉丝的 Python 工程师
查看>>
假如计算机是中国人发明的,那代码应该这么写
查看>>
科技公司最爱的 50 款开源工具,你都用过吗?
查看>>
触目惊心:比特币到底消耗了多少能源?
查看>>
面试官:简历上敢写技术精通?那我就不客气了!
查看>>