一文详解RT-thread自动初始化

文章目录

    • 1. RT-thread启动流程
    • 2. 自动初始化原理
      • 2.1 基本原理
      • 2.2 段内存布局
      • 2.3 定义初始化内存段
      • 2.4 自启动初始化函数注册
    • 3. 自启动初始化是如何按等级依次进行的?
    • 4. 自启动初始化函数什么时候调用?
      • 4.1 第1步(系统调度器启用前)
      • 4.2 第2步(系统调度器启用后)
    • 关注我

1. RT-thread启动流程

      我们先来看RT-thead的启动流程,其在rt_components_board_init()和rt_components_init()分别对RT-Thread定义的7个等级的初始化函数按顺序进行了自动初始化。
一文详解RT-thread自动初始化_第1张图片

2. 自动初始化原理

2.1 基本原理

      自动初始化的实现方式是通过将初始化函数放在同一个内存段,内存段内存储类型一致的全局变量,全局变量保存有初始化函数入口(如全局变量为一个函数指针变量),然后在逐个遍历该内存段中的全局变量(函数指针)来调用初始函数。
一文详解RT-thread自动初始化_第2张图片

2.2 段内存布局

我们使用keil编译成功,打开内存布局文件*.map,从里面我们可以看到rtt等级0初始化的内存段布局。map内存布局文件目录位于:board\build\keil\List
在这里插入图片描述

2.3 定义初始化内存段

       如下代码定义了一个全局变量,该全局变量为一个类型为 init_fn_t的函数指针变量,放置在.rti_fn.xxx段。

  RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn." level) = fn

2.4 自启动初始化函数注册

      RT-thread根据系统启动阶段不同,将初始化划分为7个等级,用户可使用的等级1-6,其具体注册接口如下,我使用对应的注册接口即可将自定义初始化函数进行注册
一文详解RT-thread自动初始化_第3张图片

3. 自启动初始化是如何按等级依次进行的?

       RT-thread巧妙利用了编译器默认按单词顺序,在内存布局中对各内存段进行链接排序,keil中我们也可以使用–sort=algorithm进行配置,RT-thread各等级初始化内存段布局如下:
一文详解RT-thread自动初始化_第4张图片

4. 自启动初始化函数什么时候调用?

从RT-thread官文文档或代码我们可以知道,自启动初始函数分成了两步调用:

4.1 第1步(系统调度器启用前)

在系统调度器启动前,先进行等级0,等级1(板级硬件)的初始化,代码如下:

void rt_components_board_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;
    for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    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)();
    }
#endif
}

4.2 第2步(系统调度器启用后)

系统启动后,系统按等级顺序依次进行初始化,代码如下:

void rt_components_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;

    rt_kprintf("do components initialization.\n");
    for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
    {
        (*fn_ptr)();
    }
#endif
}

关注我

一文详解RT-thread自动初始化_第5张图片

你可能感兴趣的:(RT-thread,rtt,thread,嵌入式)