通过学习宋宝华老师的课程《C语言大型软件设计的面向对象》,其中有个要点是各个模块的初始化函数应该是内部函数而不是外部函数。
外设或应用程序的初始化函数在编译链接的时候,存在到指定的INIT段,在主函数中,只需要调用并遍历INIT段所在的地址,执行地址所指向的函数指针即完成初始化过程。
原理见大神帖:
思维导图:
但帖子内容为基于嵌入式linux的gcc链接文件lds的。
对于MDK下的arm体系,采用的是分散链接脚本实现,即scatter file。通常我们不需要,也尽量不要去修改,除了你对scatter语法了解,并且实际应用上需要对flash及memory有特殊划分需求。
参照大神的实现原理,并参考rtthread的rtdef.h和component.c,将代码堆进自己的工程。通过仿真调试,结果怎么都无法调用到外设的初始化函数。苦思无果……
接着对比了rtthread和自己工程的map文件,发现自己的外设初始化函数,始终都不在自己设想的section内。。。。。
这个是正确的section
0x00000b4c 0x00000b4c 0x00000004 Data RO 10 .rti_fn.0.end main.o
0x00000b50 0x00000b50 0x00000004 Data RO 180 .rti_fn.1 peripherals.o
0x00000b54 0x00000b54 0x00000004 Data RO 11 .rti_fn.1.end main.o
搞懂之前,从来都不是这个样子的。。。。。
当时就想问题在哪里,是如何让MDK的链接器知道把.rti_fn.相关的段放在一起并按顺序排列。
这么想着就去对比了MDK的Option的Linker页面,其中的Misc controls字段有“--keep *.o(.rti_fn.*)”
看着字面就知道肯定是症结所在了。
接着分析为什么,找到MDK官网的帮助文件
因为外设.c文件的初始化函数,在这个低耦合的方式下,没有被调用到,所以编译器默认会将其在image文件的remove掉,
Removing Unused input sections from the image.
Removing peripherals.o(i.Peripherals_gpio_init), (32 bytes).
“--keep *.o(.rti_fn.*)”指定所有.o文件中的包含.rti_fn.字段的section不被remove。
阅读(3126) | 评论(0) | 转发(0) |