嵌入式软件开发之:编译器的缺省行为
代码和数据。默认的存储器映射如图13.3所示。
图13.3 默认存储器映射
结合图13.3,可以看出默认的存储器映射使用以下规则:
· 链接映像,在地址0x8000加载并运行。首先放置所有的RO(只读)段,其次是RW(读写)段,然后是ZI(零初始化)段。
· 堆(Heap)直接从ZI段的顶端地址算起,因此,其准确位置在链接时决定。
· 栈(Stack)的起始地址在应用程序启动过程时由Semihosting操作提供。具体Semihosting操作设置的值由调试系统的不同而不同。
① RealView ARMulator ISS(RVISS)设置为配置文件peripherals.ami中设定的值。默认值是0x08000000。
② Multi-ICE将该地址设置为调试器内部变量top_of_memory的值。默认值是0x00080000。
13.2.4 链接程序放置规则
链接程序遵守一组规则,以决定代码和数据位于存储器中的什么位置,如图13.4所示。
链接程序放置遵循以下规则:
① 映像首先按属性组织:RO段在最低的存储器地址,其次是RW段,然后是ZI段。每一种属性中,代码在数据之前。
② 链接程序按名称的字母顺序放置输入段(Section)。输入段名称即汇编程序AREA伪操作定义的名称。
图13.4 链接程序放置规则
③ 在输入段中,独立对象的代码和数据,按照对象文件在链接程序命令行中被指定的顺序放置。
要精确放置代码和数据,ARM公司建议不要过分依靠这些规则。相反,必须使用分散加载机制来完全控制代码和数据的放置。请参阅下一章的调整映像存储器映射以适应目标系统硬件存储器的实际要求。
13.2.5 应用程序启动
多数嵌入式系统中,执行主任务前,执行初始化序列来设置系统。默认的RVCT初始化序列如图13.5所示。
图13.5 默认RVCT初始化序列
在进入用户代码(main())前,初始化序列可分成三个功能块:__main直接跳转到__scatterload;__scatterload负责建立运行时的映像存储器映射,而__rt_entry(运行时的入口)则负责初始化C库。
__scatterload执行代码和数据复制以及ZI数据的清零。对于ZI数据的清零和未改变的RW数据来说,这一步总是要做的。
__scatterload跳转到__rt_entry。它设置应用程序的栈和堆,初始化库函数及其静态数据,并调用任何全局声明的对象的构造函数(仅C++)。
然后__rt_entry跳转到应用程序入口main()。主应用程序结束执行时,__rt_entry将库关闭,然后把控制权交还给调试器。
RVCT中,函数main()有一个特殊含意。main()函数的存在强制链接程序链接到__main和__rt_entry中的初始化代码。没有main()函数,就不会链接到初始化进程,那么一些标准C库功能就不会得到支持。
[1] 在一些ARM的中文参考文献中,将Semihosting译为半主机。
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于Winodws CE的嵌入式网络监控系统的设计与实现(03-05)
- 嵌入式系统实时性的问题(06-21)
- 嵌入式实时系统中的优先级反转问题(06-10)
- 嵌入式Linux系统中MMC卡驱动管理技术研究(06-10)
- FPGA的DSP性能揭秘(06-16)