rtthread 自动初始化机制,隐式初始化

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

       以rtthread的can初始化为例:

int rt_hw_can_init(void)
{
    // 初始化can
    rt_hw_can_register(&drv_can1.device,
                       drv_can1.name,
                       &_can_ops,
                       &drv_can1);
}

INIT_BOARD_EXPORT(rt_hw_can_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

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

    按宏一层层展开:

INIT_EXPORT(rt_hw_can_init, "1");

RT_USED const init_fn_t __rt_init_rt_hw_can_init SECTION(".rti_fn." "1") =
    rt_hw_can_init;

__attribute__((used)) const init_fn_t __rt_init_rt_hw_can_init
    __attribute__((section(".rti_fn." "1"))) =
    rt_hw_can_init;

typedef int (*init_fn_t)(void);

     __attribute__((used))作用是告诉编译器该语句有用的,需要执行的,没有这个编译可能会优化掉,导致不执行。

    init_fn_t为函数指针类型,那么const init_fn_t __rt_init_rt_hw_can_init = rt_hw_can_init;这语句的意思是定义了一个函数指针类型的常量__rt_init_rt_hw_can_init,并初始化值为rt_hw_can_init。这样__rt_init_rt_hw_can_init就是指向rt_hw_can_init的函数指针,只要调用(*__rt_init_rt_hw_can_init)()既可以执行rt_hw_can_init函数。

    再看__attribute__((section(".rti_fn." "1"))),这个意思是将__rt_init_rt_hw_can_init放于".rti_fn.1"输入段中,由以下Map文件可看出

    这样我们就知道__rt_init_rt_hw_can_init所存放的地址,通过遍历".rti_fn.1"输入段就可执行该输入段中的所有初始化函数,rtthread中源码如下:

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");

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

     rtthread在系统启动过程中会调用到rt_components_board_init函数。INIT_EXPORT(rti_board_start, "0.end"); INIT_EXPORT(rti_board_end, "1.end"); 定义了__rt_init_rti_board_start和__rt_init_rti_board_end这两个函数指针,他们保存的地址刚好是输入段 ".rti_fn.1"前一个以及后一个。所以遍历即可得到".rti_fn.1"中的所有函数指针。通过函数指针就可以调用到can的初始化函数rt_hw_can_init,实现自动初始化,不需要显式调用rt_hw_can_init。

    所以想要被自动初始化,只需要通过INIT_BOARD_EXPORT这个宏声明即可。

        

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值