Rtthread INIT_EXPORT宏的使用
在rtthread源码中可以通过INIT_EXPORT宏实现函数自动被调用,其具体实现如下:
补充一点,SECTION的段应该要在ld文件中定义好,否则会因为没有定义该段而调用失败。
/* section information for initial. /
__rt_init_start = .;
KEEP((SORT(.rti_fn*)))
__rt_init_end = .;
. = ALIGN(4);
因为是const 常量函数指针,定义在ld文件中的ro data段即可。
/* 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) //这里不使用VC++编译器
#else
#if RT_DEBUG_INIT //定义该宏
struct rt_init_desc
{
const char* fn_name; //函数名称
const init_fn_t fn; //函数指针
};
//INIT_EXPORT(func, "0")宏展开如下:
//const struct rt_init_desc __rt_init_desc_func __attribute__((section(".rti_fn." "0"))) = \
//{"func", func}
// SECTION这个宏定义,这个宏可以将变量添加到某个输入段中,上面example就是将__rt_init_desc_func
//这个结构体对象放在.rti_fn.0这个段中,编译后打开.map文件也可以查到
#define INIT_EXPORT(fn, level) \
const char __rti_##fn##_name[] = #fn; \
RT_USED const struct rt_init_desc __rt_init_desc_##fn 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
#endif
#endif
#else
#define INIT_EXPORT(fn, level)
#endif
//下面是Rtthread源码中INIT_EXPORT的使用
#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"); //将rti_start函数放在了.rti_fn.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;
//__rt_init_desc_rti_board_start 就是上面 rti_board_start函数存放的位置,将这部分的函数全部初始化
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
volatile 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
volatile 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 */