在使用keil开发较大的项目时常常存在驱动之间耦合性太大,增加或减少驱动会涉及到对工程中其他部分代码的更改,比如新增一个驱动需要把初始化代码放到main函数中执行,去除一个驱动又需要在main函数中去掉对应的函数调用,本例方法可降低驱动代码之间的耦合性。
一,设置keil为使用加载文件
二,编写链接脚本
LR_IROM1 0x08020000 0x001E0000 { ; load region size_region
ER_IROM1 0x08020000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
my_section0 +0 {
*.o(my_section0)
}
my_section1 +0{
*.o(my_section1)
}
my_section2 +0{
*.o(my_section2)
}
RW_IRAM1 0x20000008 0x0009FFF8 { ; RW data
.ANY (+RW +ZI)
}
}
三,定义module_exit module_init 宏
struct my_model_struct
{
void (*init)(void);
void (*exit)(void);
void (*enter_lp)(void);
void (*exit_lp)(void);
};
//定义节调用结构体
struct my_section_struct
{
char *name;
struct my_model_struct *model;
};
//定义总线节
#define bus_extern(model_,name_) \
const static struct my_section_struct model_##_extern __attribute__((used,section("my_section0"))) =\
{\
.name=name_,\
.model=(struct my_model_struct *)&model_,\
}
//定义驱动节
#define driver_extern(model_,name_) \
const static struct my_section_struct model_##_extern __attribute__((used,section("my_section1"))) =\
{\
.name=name_,\
.model=(struct my_model_struct *)&model_,\
}
//定义设备节
#define device_extern(model_,name_) \
const static struct my_section_struct model_##_extern __attribute__((used,section("my_section2"))) =\
{\
.name=name_,\
.model=(struct my_model_struct *)&model_,\
}
四,编写统一初始化函数
//声明初始化节的地址和长度
extern const unsigned int Load$$my_section0$$Base;
extern const unsigned int Load$$my_section0$$Length;
extern const unsigned int Load$$my_section1$$Base;
extern const unsigned int Load$$my_section1$$Length;
extern const unsigned int Load$$my_section2$$Base;
extern const unsigned int Load$$my_section2$$Length;
/******************************************************
在指定section中定义变量
#pragma arm section rodata = "my_init_start"
const static unsigned int g_my_init_start;
#pragma arm section
#pragma arm section rodata = "my_init_end"
const static unsigned int g_my_init_end;
#pragma arm section
*******************************************************/
//运行初始化节
void my_section_do_init (void)
{
//首先初始化总线
struct my_section_struct *start=(struct my_section_struct *)&Load$$my_section0$$Base;
int length=(unsigned int)&Load$$my_section0$$Length;
int num=length/sizeof (struct my_section_struct);
for (int i=0;i<num;i++)
{
struct my_model_struct *model=start->model;
if (model->init)
model->init();
start++;
}
//然后初始化驱动
start=(struct my_section_struct *)&Load$$my_section1$$Base;
length=(unsigned int)&Load$$my_section1$$Length;
num=length/sizeof (struct my_section_struct);
for (int i=0;i<num;i++)
{
struct my_model_struct *model=start->model;
if (model->init)
model->init();
start++;
}
//最后初始化设备
start=(struct my_section_struct *)&Load$$my_section2$$Base;
length=(unsigned int)&Load$$my_section2$$Length;
num=length/sizeof (struct my_section_struct);
for (int i=0;i<num;i++)
{
struct my_model_struct *model=start->model;
if (model->init)
model->init();
start++;
}
}
五,编写驱动时在文件中加入类似代码
void mymem_init (void)
{
mem_init ();
exmem_init( );
}
const static struct my_model_struct mymem_model=
{
.init=mymem_init,
};
device_extern(mymem_model,"mymem");
六,在main函数中调用
在main函数中调用 my_section_do_init () 函数即可对所有驱动进行初始化,实现驱动模块之间的去耦合。