仿照RT-Thread的自动初始化机制,写了一个自动初始化的模块,整个代码仅52字节。
好处:可以实现自动初始化,不用在外部显式地调用。
缺点:初始化逻辑较显式调用的方式模糊,容易引入BUG。
以下是对应的头文件和源文件,初始化顺序分为9级,LOADER_BOARD_EARLY_EXPORT最早,LOADER_APP_LATE_EXPORT最迟。使用方法可以看最后面的Demo。
#ifndef _LOADER__H
#define _LOADER__H
#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */
#define LOADER_USED __attribute__((used))
#define SECTION(x) __attribute__((section(x)))
#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
#define LOADER_USED __root
#define SECTION(x) @ x
#elif defined (__GNUC__) /* GNU GCC Compiler */
#define LOADER_USED __attribute__((used))
#define SECTION(x) __attribute__((section(x)))
#endif
typedef int (*init_func_t)(void);
#define LOADER_EXPORT(fn, level) \
LOADER_USED const init_func_t init_##fn SECTION(".loader_fn."level) = fn
#define LOADER_BOARD_EARLY_EXPORT(fn) LOADER_EXPORT(fn, "1")
#define LOADER_BOARD_EXPORT(fn) LOADER_EXPORT(fn, "2")
#define LOADER_BOARD_LATE_EXPORT(fn) LOADER_EXPORT(fn, "3")
#define LOADER_COMPONENT_EARLY_EXPORT(fn) LOADER_EXPORT(fn, "4")
#define LOADER_COMPONENT_EXPORT(fn) LOADER_EXPORT(fn, "5")
#define LOADER_COMPONENT_LATE_EXPORT(fn) LOADER_EXPORT(fn, "6")
#define LOADER_APP_EARLY_EXPORT(fn) LOADER_EXPORT(fn, "7")
#define LOADER_APP_EXPORT(fn) LOADER_EXPORT(fn, "8")
#define LOADER_APP_LATE_EXPORT(fn) LOADER_EXPORT(fn, "9")
int LoaderExec(void);
#endif
#include "Loader.h"
static int loader_start(void)
{
return 0;
}
LOADER_EXPORT(loader_start, "0");
static int loader_end(void)
{
return 0;
}
LOADER_EXPORT(loader_end, "9.end");
int LoaderExec(void)
{
int res = 0;
const init_func_t *fn_ptr;
for (fn_ptr = &init_loader_start; fn_ptr < &init_loader_end; fn_ptr++)
{
res += (*fn_ptr)();
}
return res;
}
/* Loader Demo */
/********************** led.c **********************/
#include "Loader.h"
int led_init(void)
{
/* GPIO初始化 */
return 0;
}
LOADER_APP_EXPORT(led_init);
/********************** main.c **********************/
#include "Loader.h"
int main(void)
{
HAL_Init(); /* 初始化芯片底层,实际上该函数也可以通过loader导出 */
LoaderExec(); /* 加载Loader,里面会调用led_init */
while(1)
{
/* do something */
}
}