如题,我写了个简单的设备管理器,
每个设备,写完之后,应该有个注册函数,
我想让这个注册函数自动被管理器调用。
参考到了RTT的宏,指定这些函数在某一个特定的代码段,
按顺序排列起来,然后从头到尾,逐个调用。
#define INIT_EXPORT(fn, level) \
const init_fn_t __rt_init_##fn RT_SECTION(".rti_fn."level) = fn
#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")
#define INIT_CPU_EXPORT(fn) INIT_EXPORT(fn, "2")
#define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3")
#define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4")
#define INIT_FS_EXPORT(fn) INIT_EXPORT(fn, "5")
#define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6")
参考这篇文章: RT-Thread 学习笔记(七)
我从中抄袭了这些代码
(1)头文件代码
/*自动初始化模块*/
#define RT_SECTION(x) __attribute__((section(x)))
#define RT_UNUSED __attribute__((unused))
#define RT_USED __attribute__((used))
typedef int (*init_fn_t)(void);
#define INIT_EXPORT(fn, level) \
const init_fn_t __rt_init_##fn RT_SECTION(".rti_fn."level) = fn
#define INIT_BOARD_EXPORT(fn) INIT_EXPORT(fn, "1")
#define INIT_CPU_EXPORT(fn) INIT_EXPORT(fn, "2")
#define INIT_DEVICE_EXPORT(fn) INIT_EXPORT(fn, "3")
#define INIT_COMPONENT_EXPORT(fn) INIT_EXPORT(fn, "4")
#define INIT_FS_EXPORT(fn) INIT_EXPORT(fn, "5")
#define INIT_APP_EXPORT(fn) INIT_EXPORT(fn, "6")
(2)c文件代码
static int rti_start(void)
{
return 0;
}
INIT_EXPORT(rti_start, "0");
static int rti_end(void)
{
return 0;
}
INIT_EXPORT(rti_end,"7");
void rt_components_init(void)
{
const init_fn_t* fn_ptr;
for (fn_ptr = &__rt_init_rti_start; fn_ptr < &__rt_init_rti_end; )
{
(*fn_ptr)();
fn_ptr ++;
}
}
(3)调用:
①初始化设备管理器的时候,调用rt_components_init()函数,
②修饰注册函数
INIT_COMPONENT_EXPORT(register_hw_dev_led);
(4)串口打印,没有看到register_hw_dev_led()函数的调用打印。
最近编辑记录 LinjieGuo (2021-12-28 17:22:55)
离线
编译环境:Keil 5
(1)map文件关键信息
__rt_init_rti_start 0x08011ce0 Data 4 hw_action.o(.rti_fn.0)
__rt_init_rti_end 0x08011ce4 Data 4 hw_action.o(.rti_fn.7)
hw_action.o(.text) refers to hw_action.o(.rti_fn.0) for __rt_init_rti_start
hw_action.o(.text) refers to hw_action.o(.rti_fn.7) for __rt_init_rti_end
hw_action.o(.rti_fn.0) refers to hw_action.o(.text) for rti_start
hw_action.o(.rti_fn.7) refers to hw_action.o(.text) for rti_end
hw_dev_led.o(.rti_fn.4) refers to hw_dev_led.o(.text) for register_hw_dev_led
Removing hw_dev_led.o(.rti_fn.4), (4 bytes).
0x08011ce0 0x08011ce0 0x00000004 Data RO 2106 .rti_fn.0 hw_action.o
0x08011ce4 0x08011ce4 0x00000004 Data RO 2107 .rti_fn.7 hw_action.o
离线
继续描述场景
(1)优化等级-O0
(2)不勾选One ELF Section per Function
编译后,想要自动调用的宏还是没有被调用。
因为是公司代码,不方便上传,先上次map文件:
CMSIS-RTOS2-free_map.zip
如果大神们不好诊断,明天,我可以用其他单板实现这个框架,发代码出来。
离线
问题已经解决,在keil下,关键代码如下:
(1)h文件
/*自动初始化模块*/
#define RT_SECTION(x) __attribute__((section(x)))
#define RT_UNUSED __attribute__((unused))
#define RT_USED __attribute__((used))
typedef int (*init_fn_t)(void);
#ifdef _MSC_VER /* we do not support MS VC++ compiler */
#pragma section("rti_fn$f",read)
struct rt_init_desc
{
const char* level;
const init_fn_t fn;
};
#define INIT_EXPORT(fn, level) \
const char __rti_level_##fn[] = level"__rt_init_"#fn; \
__declspec(allocate("rti_fn$f")) \
RT_USED const struct rt_init_desc __rt_init_msc_##fn = \
{__rti_level_##fn, fn };
#else
#define INIT_EXPORT(fn, level) \
RT_USED const init_fn_t __rt_init_##fn RT_SECTION(".rti_fn." level) = fn
#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")
(2)c文件
static int rti_start(void)
{
return 0;
}
INIT_EXPORT(rti_start, "0");
static int rti_end(void)
{
return 0;
}
INIT_EXPORT(rti_end,"7");
void rt_components_init(void)
{
const init_fn_t* fn_ptr;
for (fn_ptr = &__rt_init_rti_start; fn_ptr < &__rt_init_rti_end; )
{
(*fn_ptr)();
fn_ptr ++;
}
}
以上代码源自RTT bsp,以及1楼参考的文章。
成功的工程:ITX_190_HWA.zip
最近编辑记录 LinjieGuo (2021-12-31 13:51:23)
离线