使用ADS1.2进行嵌入式软件开发(上)
发布时间:2008/5/27 0:00:00 访问次数:478
嵌入式应用程序通常都是在样机环境下调试与开发的,这种环境与最终产品之间并不完全相同。因此,在系统调试阶段就考虑应用程序在最终目标硬件中的运行情况是非常重要的。
本文旨在讨论如何将一个开发/调试环境下的嵌入式应用程序转移到最终独立运行的目标系统中去,并提到了arm ads1.2开发工具包的一些功能特性及其在这个过程中所起到的作用。
使用ads开发嵌入式程序时,需要着重考虑以下几个问题:
与硬件相关的c语言库函数的使用;
某些c语言库函数使用了调试环境中的资源,要把这些使用的资源重定向到目标系统中的硬件上来;
可执行映象文件的存储器映射必须根据目标硬件的存储器分布进行裁剪;
在主程序执行前,嵌入式应用程序必须先完成系统的初始化。一个完整的初始化包括用户的启动执行代码和ads中c库函数的初始化过程。
图1 semihosting的实现举例
图2 c语言库函数结构
图3 缺省的存储器映射
图4 连接器布局规则
缺省的工程项目设置
刚开始一个嵌入式应用软件开发时,ads用户可能并不完全清楚目标硬件的一些参数指标。比如有关外设、存储器地址分布,甚至处理器类型等一些细节,可能还没有最终确定。为了在所有这些细节全部就绪前就能进行软件开发,ads工具有一套程序构建和调试的缺省设置。了解这套缺省的工程项目设置方法,对于掌握最终的移植步骤非常有好处。
ads1.2c语言函数库
semihosting
在ads的c语言函数库中,某些ansic的功能是由主机的调试环境来提供的,这套机制有一个专门术语叫semihosting。semihosting通过一组软件中断(swi)指令来实现。如图1所示,当一个semihosting软中断被执行时,调试系统先识别这个swi请求,然后挂起正在运行的程序,调用semihosting的服务,完成后再恢复原来的程序执行。因此,主机执行的任务对于程序来说是透明的。
c语言库函数结构
从概念上来讲,c语言库函数可以被分成两部分,一是ansic语言规范本身的一部分,一是只受某一特定ansic层次支持的函数,如图2所示。
其中一些ansic的功能是由主机调试环境调用驱动程序级的函数完成的。例如,ads的库函数printf()把输出信息输出到调试器的控制台窗口,这个功能通过调用__sys_write()实现,__sys_write()执行了一个把字符串输出到主机控制台的semihosting软中断服务程序。
缺省的存储器映射
如果用户在程序编译时没有指定映象的存储器映射分布,ads将为生成的目标代码和数据分配一个缺省的存储器映射图,如图3所示。
目标印象被连接至地址0x8000,存储和执行区域都位于该地址开始的空间。ro(只读)部分放在前面,接着是rw(读写)部分,最后是zi(零初始化)部分。
在zi部分之上紧跟着heap,所以heap的确切地址要在连接时才能确定。
stack的基地址是在应用程序启动时由一个semihosting操作提供。这项semihosting操作返回的地址值视不同调试环境而定:
armulator返回配置文件peripherals.ami中的设置值;缺省为0x08000000。
multi-ice返回的是调试器内部变量$top_of_memory的值;缺省为0x00080000。
连接器布局规则
连接器对代码和数据在存储器系统中的分配,遵循一套规则,如图4所示。
映象首先按照属性以ro-rw-zi的次序进行排列,在同一种属性里面代码先于数据。然后连接器将输入段根据名字的字母顺序进行排列,输入段的名字与汇编代码里面的块名字指示一致(在汇编程序中用area关键字)。在输入段中,来自不同对象的代码和数据放置次序与在连接器命令行中指定的对象文件次序一致。
在需要灵活分配代码和数据放置位置的情况下,建议用户不要简单地依靠这些规则。后面会介绍一种如何控制代码和数据布局的机制scatterloading。
图5 缺省的ads初始化过程
图6 c库函数重定向
图7 scatter文件语法
图8 分散加载的简单样例
启动应用程序
大多数嵌入式系统在进入应用主程序之前有一个初始化的过程,该过程完成系统的启动和初始化功能。缺省的ads初始化过程如图5所示。
总体上,初始化过程可以分成两部分来看:
_main负责设置运行映像存储器映射;
_rt_entry负责库函数的初始化。
_main完成代码和数据的复制,并把zi数据区清零。这一步只有当代码和数据区在存储和运行时处于不同的存储器位置时才有意义。接着_main跳进_rt_entry,进行stack和heap
嵌入式应用程序通常都是在样机环境下调试与开发的,这种环境与最终产品之间并不完全相同。因此,在系统调试阶段就考虑应用程序在最终目标硬件中的运行情况是非常重要的。
本文旨在讨论如何将一个开发/调试环境下的嵌入式应用程序转移到最终独立运行的目标系统中去,并提到了arm ads1.2开发工具包的一些功能特性及其在这个过程中所起到的作用。
使用ads开发嵌入式程序时,需要着重考虑以下几个问题:
与硬件相关的c语言库函数的使用;
某些c语言库函数使用了调试环境中的资源,要把这些使用的资源重定向到目标系统中的硬件上来;
可执行映象文件的存储器映射必须根据目标硬件的存储器分布进行裁剪;
在主程序执行前,嵌入式应用程序必须先完成系统的初始化。一个完整的初始化包括用户的启动执行代码和ads中c库函数的初始化过程。
图1 semihosting的实现举例
图2 c语言库函数结构
图3 缺省的存储器映射
图4 连接器布局规则
缺省的工程项目设置
刚开始一个嵌入式应用软件开发时,ads用户可能并不完全清楚目标硬件的一些参数指标。比如有关外设、存储器地址分布,甚至处理器类型等一些细节,可能还没有最终确定。为了在所有这些细节全部就绪前就能进行软件开发,ads工具有一套程序构建和调试的缺省设置。了解这套缺省的工程项目设置方法,对于掌握最终的移植步骤非常有好处。
ads1.2c语言函数库
semihosting
在ads的c语言函数库中,某些ansic的功能是由主机的调试环境来提供的,这套机制有一个专门术语叫semihosting。semihosting通过一组软件中断(swi)指令来实现。如图1所示,当一个semihosting软中断被执行时,调试系统先识别这个swi请求,然后挂起正在运行的程序,调用semihosting的服务,完成后再恢复原来的程序执行。因此,主机执行的任务对于程序来说是透明的。
c语言库函数结构
从概念上来讲,c语言库函数可以被分成两部分,一是ansic语言规范本身的一部分,一是只受某一特定ansic层次支持的函数,如图2所示。
其中一些ansic的功能是由主机调试环境调用驱动程序级的函数完成的。例如,ads的库函数printf()把输出信息输出到调试器的控制台窗口,这个功能通过调用__sys_write()实现,__sys_write()执行了一个把字符串输出到主机控制台的semihosting软中断服务程序。
缺省的存储器映射
如果用户在程序编译时没有指定映象的存储器映射分布,ads将为生成的目标代码和数据分配一个缺省的存储器映射图,如图3所示。
目标印象被连接至地址0x8000,存储和执行区域都位于该地址开始的空间。ro(只读)部分放在前面,接着是rw(读写)部分,最后是zi(零初始化)部分。
在zi部分之上紧跟着heap,所以heap的确切地址要在连接时才能确定。
stack的基地址是在应用程序启动时由一个semihosting操作提供。这项semihosting操作返回的地址值视不同调试环境而定:
armulator返回配置文件peripherals.ami中的设置值;缺省为0x08000000。
multi-ice返回的是调试器内部变量$top_of_memory的值;缺省为0x00080000。
连接器布局规则
连接器对代码和数据在存储器系统中的分配,遵循一套规则,如图4所示。
映象首先按照属性以ro-rw-zi的次序进行排列,在同一种属性里面代码先于数据。然后连接器将输入段根据名字的字母顺序进行排列,输入段的名字与汇编代码里面的块名字指示一致(在汇编程序中用area关键字)。在输入段中,来自不同对象的代码和数据放置次序与在连接器命令行中指定的对象文件次序一致。
在需要灵活分配代码和数据放置位置的情况下,建议用户不要简单地依靠这些规则。后面会介绍一种如何控制代码和数据布局的机制scatterloading。
图5 缺省的ads初始化过程
图6 c库函数重定向
图7 scatter文件语法
图8 分散加载的简单样例
启动应用程序
大多数嵌入式系统在进入应用主程序之前有一个初始化的过程,该过程完成系统的启动和初始化功能。缺省的ads初始化过程如图5所示。
总体上,初始化过程可以分成两部分来看:
_main负责设置运行映像存储器映射;
_rt_entry负责库函数的初始化。
_main完成代码和数据的复制,并把zi数据区清零。这一步只有当代码和数据区在存储和运行时处于不同的存储器位置时才有意义。接着_main跳进_rt_entry,进行stack和heap
上一篇:嵌入式系统离线测试