RT-Thread 自动初始化机制 理解

自动初始化机制是指初始化函数不需要被显式调用,只需要在函数定义处通过宏定义的方式进行申明,就会在系统启动过程中被执行。

这里的最主要的看点就是RT-Thread,在flash中开辟了一片区域用来存放需要设备初始化的函数地址,使用宏定义的方式把需要执行初始化的函数加入到这片区域中,这篇区域主要分为两部分。

第一部分为rt_components_board_init()函数中执行,通过使用INIT_BOARD_EXPORT(fn)宏定义把需要的初始化函数加入到初始化队列中。

第二部分为 rt_components_init()函数中执行,通过 INIT_PREV_EXPORT(fn)、INIT_DEVICE_EXPORT(fn) 申明的初始化函数、INIT_COMPONENT_EXPORT(fn)申明的初始化函数、INIT_ENV_EXPORT(fn) 申明的初始化函数、 INIT_APP_EXPORT(fn)申明的初始化函数。

下面使用串口初始化作为例子讲解

这是串口初始化的函数,使用INIT_BOARD_EXPORT(rt_hw_usart_init),把函数地址写到flash初始化区

int rt_hw_usart_init(void)  /* 串口初始化函数 */
{
     ... ...
     /* 注册串口 1 设备 */
     rt_hw_serial_register(&serial1, "uart1",
                        RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
                        uart);
     return 0;
}
INIT_BOARD_EXPORT(rt_hw_usart_init);    /* 使用组件自动初始化机制 */

具体实现步骤:

INIT_BOARD_EXPORT(rt_hw_usart_init)找到

#define INIT_BOARD_EXPORT(fn)           INIT_EXPORT(fn, "1")

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

通过这两条宏定义替换INIT_BOARD_EXPORT(rt_hw_usart_init)就是等价于执行RT_USED const init_fn_t   __rt_init_rt_hw_usart_init SECTION(".rti_fn."1) = rt_hw_usart_init

PS:__rt_init_##fn中的##就是一个字符串连接符

关于 SECTION的详细介绍,可以看这篇文章:linkhttps://blog.csdn.net/mloves0729/article/details/14519485

大致的意思就是分配一个section用来存放数据,以".rti_fn.1”作为section名字,程序中使用section名字直接访问对应的flash内存

RT_USED const init_fn_t   __rt_init_rt_hw_usart_init SECTION(".rti_fn."1) = rt_hw_usart_init

翻译过来就是把 rt_hw_usart_init的函数地址放在.rti_fn.1section段中

调用同一个宏定义会把几个函数的地址放在同一个section段中

比如:INIT_BOARD_EXPORT(rt_hw_pin_init)和INIT_BOARD_EXPORT(rt_hw_usart_init)都放在.rti_fn.1section段中

RT-Thread 自动初始化机制 理解_第1张图片

从map文件中比较直观能看出来,主要分为两段,一个是.rti_fn.1,另一个就是剩下的初始化段

RT-Thread 自动初始化机制 理解_第2张图片

在__rt_init_rt_hw_usart_init这个地址中存放着rt_hw_usart_init函数的地址。

自动初始化的执行

 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)();
    }

__rt_init_rti_board_start flash地址是0x0800f5f4,里面存放初始化启动函数的地址,通过函数指针历遍需要初始化的函数,从__rt_init_rti_board_start 到 __rt_init_rt_hw_pin_init   再到__rt_init_rt_hw_usart_init 。

PS:section的排序是同一section放一起,按函数名字排序,不同section按名字排序,

你可能感兴趣的:(RT-Thread学习,RT-Thread,C,单片机,源码,嵌入式)