外设或应用程序的初始化函数在编译链接的时候,存在到指定的INIT段,在主函数中,只需要调用并遍历INIT段所在的地址,执行地址所指向的函数指针即完成初始化过程。
原理见大神帖:http://mp.weixin.qq.com/s/mhGt798BhAQHXiuTokxKLA
思维导图:http://mp.weixin.qq.com/s/jFOFW3UrzQMsJCjRoKXrAA
但帖子内容为基于嵌入式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官网的帮助文件
http://www.keil.com/support/man/docs/armlink/armlink_pge1362075498955.htm
因为外设.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。