现在想实现一个类似想Lib库文件一样的技术,Lib是和自身的工程文件结合起来,一起编译并烧进Flash里面去的,我现在想使用两个步骤,APP程序 和 Lib库的程序分别编译出各自的hex文件,通过设置各自在flash里面的地址,使用绝对地址的调用LIB里面的函数,下面图为我存放APP和Lib在Flash里面的分布
APP的scatter文件:
- LR_1 0x00000000
- {
- FLASH 0x00000000 0x00001000
- {
- *.o (RESET, +First)
- * (+RO)
- }
-
- SRAM 0x10000000 0x00000200
- {
- * (+RW, +ZI)
- }
- }
LIB的scatter文件:
- LR_1 0x00001000
- {
- FLASH 0x00001000 0x00001000
- {
- *.o (RESET, +First)
- * (+RO)
- }
-
- SRAM 0x10000200 0x00000200
- {
- * (+RW, +ZI)
- }
- }
我在LIB工程里面定义了一些公共的函数,我把代码贴出来:
- uint8_t get_uint8_t_data(void)//在FLASH实际测试的地址为 0x000011B6
- {
- return 8;
- }
-
- uint16_t get_uint16_t_data(void)//在FLASH实际测试的地址为 0x000011AE
- {
- return 16;
- }
-
- uint32_t get_uint32_t_data(void)//在FLASH实际测试的地址为 0x000011B2
- {
- return 32;
- }
-
- const uint32_t addr_point[] __attribute__((at(0x1A00))) =//再次把各个函数的地址定义到 Flash里面 0x00001A00,这样有利于在APP里面寻址操作
- {
- (uint32_t)get_uint8_t_data,
- (uint32_t)get_uint16_t_data,
- (uint32_t)get_uint32_t_data
- };
下面,我再上传个APP的工程文件,一看就很明白了:
- int main(void)
- {
- uint8_t value_8;
- uint16_t value_16;
- uint32_t value_32;
-
- uint32_t addr;
- addr = (uint32_t)*((uint32_t*)0x1A00);//这里先获取Flash 地址0x00001A00里面存放的4个字节的地址,这其实存的是get_uint8_t_data的函数地址
- value_8 = (uint8_t)((uint8_t (*)(void))addr)();//这里再根据获取的函数地址,进行转换为函数的操作,就可以调用LIB里面的函数了
- //下面的跟上2句解析式一样的
- addr = (uint32_t)*((uint32_t*)0x1A04);
- value_16 = (uint16_t)((uint16_t (*)(void))addr)();
-
- addr = (uint32_t)*((uint32_t*)0x1A08);
- value_32 = (uint32_t)((uint32_t (*)(void))addr)();
- return 0;
- }
这样的做法比Lib库有几个优点:
1.把LIB的分开编译和烧写,可以是其他多个应用程序都可以对他进行操作,如果使用的是Lib库的形式,只能是跟他同一个工程文件的才能进行操作。
2.可以分开进行升级,而且使用寻指针的函数指针的方式,有利于以后的扩展,只需要计算相应的偏移地址即可。
3.比如LIB是文件系统时,即可以让APP的代码使用,同时也可以让bootloader使用文件系统,双重复用,节省代码量和开发维护工作
其实这些都是我个人的观点,有不对的地方请大家多多指点!!