rt_thread 自动初始化组件分析记录

       rt_thread有一个开机不用显示调用函数,可以自动进行初始化函数调用的功能。前提是需要在定义函数处通过INIT_BOARD_EXPORT(fn)、 INIT_PREV_EXPORT(fn)、INIT_DEVICE_EXPORT(fn) 、INIT_COMPONENT_EXPORT(fn)、 INIT_ENV_EXPORT(fn)、INIT_APP_EXPORT(fn) 等宏定义进行声明;

比如我们定义一个函数:

void   my_test_fun(void)

{

     printf("HelloWorld");

}

通过添加如下声明后:

INIT_BOARD_EXPORT(my_test_fun);

my_test_fun函数将在系统启动阶段自动完成调用。

我们先说该机制的实现原理:

原理就是在进行INIT_BOARD_EXPORT(my_test_fun);这种声明时其实是定义了一个函数指针变量,并将该变量放到某个特定的section区域,在启动阶段从该section的起始地址到结束地址进行遍历,将遍历到的函数都进行一次调用,从而达到自动化初始化函数的目的。

涉及到的源码:

/* 定义该宏开启自动初始化机制,未定义则关闭 */
#define RT_USING_COMPONENTS_INIT

/* 定义该宏开启自动初始化机制,未定义则关闭 */
#define RT_USING_COMPONENTS_INIT


/* initialization export */
#ifdef RT_USING_COMPONENTS_INIT    //注释:/* 定义该宏开启自动初始化机制,未定义则关闭 */
typedef int (*init_fn_t)(void);
#ifdef _MSC_VER /* we do not support MS VC++ compiler */
    #define INIT_EXPORT(fn, level)
#else
    #if RT_DEBUG_INIT
        struct rt_init_desc
        {
            const char* fn_name;
            const init_fn_t fn;
        };
        #define INIT_EXPORT(fn, level)                                                       \
            const char __rti_##fn##_name[] = #fn;                                            \  //定义一个静态字符数组,初始值为函数名对应的字符串字面量。数组名字为由__rti_、fn的字符串字面量,_name拼接而成,这里使用了宏中的 ## 运算符来连接字符串。#fn中#是一个预处理器操作符,它把宏参数 fn 转换成一个字符串字面量。
            RT_USED const struct rt_init_desc __rt_init_desc_##fn SECTION(".rti_fn." level) = \ //定义一个struct rt_init_desc类型的静态变量,变量名通过宏##运算符拼接__rt_init_desc_和fn名而成,变量初始化值有两个值,第一个值是由__rti_和fn名称和_name拼接的字符串,第二个值是fn函数指针。RT_USED 用来告诉链接器不要优化掉该变量。SECTION(".rti_fn." level)告诉链接器将这个变量放置到一个特定的段(section)中。段名由 .rti_fn. 加上 level 的值组成。
            { __rti_##fn##_name, fn};
    #else
        #define INIT_EXPORT(fn, level)                                                       \
            RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn." level) = fn               //定义一个函数指针变量变量,初始值为fn,变量名由__rt_init_和fn名称拼接而成。RT_USED 用来告诉链接器不要优化掉该变量。SECTION(".rti_fn." level)告诉链接器将这个变量放置到一个特定的段(section)中。段名由 .rti_fn. 加上 level 的值组成。
    #endif
#endif
#else
#define INIT_EXPORT(fn, level)
#endif

/* 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")

#if !defined(RT_USING_FINSH)
/* define these to empty, even if not include finsh.h file */
#define FINSH_FUNCTION_EXPORT(name, desc)
#define FINSH_FUNCTION_EXPORT_ALIAS(name, alias, desc)
#define FINSH_VAR_EXPORT(name, type, desc)

#define MSH_CMD_EXPORT(command, desc)
#define MSH_CMD_EXPORT_ALIAS(command, alias, desc)
#elif !defined(FINSH_USING_SYMTAB)
#define FINSH_FUNCTION_EXPORT_CMD(name, cmd, desc)
#endif
#ifdef RT_USING_COMPONENTS_INIT
/*
 * Components Initialization will initialize some driver and components as following
 * order:
 * rti_start         --> 0
 * BOARD_EXPORT      --> 1
 * rti_board_end     --> 1.end
 *
 * DEVICE_EXPORT     --> 2
 * COMPONENT_EXPORT  --> 3
 * FS_EXPORT         --> 4
 * ENV_EXPORT        --> 5
 * APP_EXPORT        --> 6
 *
 * rti_end           --> 6.end
 *
 * These automatically initialization, the driver or component initial function must
 * be defined with:
 * INIT_BOARD_EXPORT(fn);
 * INIT_DEVICE_EXPORT(fn);
 * ...
 * INIT_APP_EXPORT(fn);
 * etc.
 */
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");

/**
 * RT-Thread Components Initialization for board
 */
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
}

/**
 * RT-Thread Components Initialization
 */
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
}
#endif   /* RT_USING_COMPONENTS_INIT */

从map中看到:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值