RT-Thread 自动初始化代码片段
C语言#语法
一个#号: 将宏参数转变为字符串 例如: #define STR(s) #s
两个#号: 把两个宏参数连接到一起 例如: #define CONS(a,b) int(a##e##b)
#define STR(s) #s
#define CONS(a,b) int(a##e##b)
int main()
{
printf(STR(vck)); // 输出字符串"vck"
printf("%d\n", CONS(2,3)); // 2e3 输出:2000
return 0;
}
代码片段
// 用户自动初始化的函数, 通过如下宏定义执行
/* 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")
//定义导入初始化函数, 将函数fn存放到代码块儿level(为1-6代码片段)位置
#define INIT_EXPORT(fn, level) \
// 定义字符串__rti_##fn##_name 为fn的函数名
const char __rti_##fn##_name[] = #fn; \
// 创建以fn函数名命名的结构体 __rt_init_desc_##fn 并将结构体内容放到指定位置
RT_USED const struct rt_init_desc __rt_init_desc_##fn SECTION(".rti_fn." level) = \
// 将__rti_##fn##_name函数名和fn函数放到 .rti_fn.level的数据段中
{__rti_##fn##_name, fn};
- 关于代码片段地址的定义在link.lds文件中定义(内存分布)
/* section information for initial. */
. = ALIGN(4);
__rt_init_start = .;
KEEP(*(SORT(.rti_fn*)))
__rt_init_end = .;
/*注:
. :点代表当前内存位置
KEEP() :告诉编译器,这部分不要被垃圾回收
SORT() :对满足字符串模式的所有名字进行递增排序
*/
- 通过如下函数实现内存分段
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");
/*
* 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.
*/
- 通过如下函数实现内存片段内的函数遍历并执行
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
}