从 ADS 到 RealView MDK

1  ARM 微控制器开发的新工具

   Keil 是颇受业界欢迎的 51 单片机开发工具,它拥有流畅的用户界面与强大的仿真功能。 ARM Keil 公司收购之后,正式推出了针对 ARM 微控制器的开发工具 RealView Microcontroller Development Kit (简称 RealView MDK 或者 MDK ),它将 ARM 开发工具 RealView Development Suite (简称 RVDS )的编译器 RVCT Keil 的工程管理、调试仿真工具集成在一起,是一款非常强大的 ARM 微控制器开发工具。

  很多嵌入式系统开发工程师对 ARM 的老版本开发工具 ADS 非常熟悉,而 RealView MDK ADS 相比较,从外观、仿真流程以及内部二进制编译、链接工具上都有了不少改进,用法稍有不同。本文的主旨是介绍通用的流程以及一些注意事项,帮助 ADS 用户将老的、遗留的 ADS 工程转化成在 RealView MDK 中进行开发调试的工程。

  为了给国内嵌入式 ARM 开发工程师提供高性价比的开发工具, 2007 5 22 日, ARM 公司和英蓓特公司正式联合推出 “RealView MDK 中国版 该新产品是特别为满足中国软件和系统开发厂商需求而推出的,起价低于 2 500 元人民币。专业人士认为,相比其他以欧美市场定价的开发工具,此款 RealView MDK 易于纳入设计工具的整体预算中。中国版 RealView MDK 即日起可通过 ARM 授权培训中心暨 ARM 在中国的工具分销商 —— 深圳市英蓓特信息技术有限公司(简称 英蓓特 )获得。 此外,有关中国版 RealView MDK 的特性和其他信息, ARM 公司专门设立了新的网站 http://www.realview.com.cn/ ,开发工程师可以进一步了解 RealView MDK 及其相关资讯。

工具结构的改进

  作为 ARM 的新一代微控制器开发工具, RealView MDK 不但包含 ARM 的最新版本编译、链接工具(即 RVDS3.0 的编译、链接工具),而且根据微控制器调试开发的特点采用了与 ADS RVDS 完全不同的调试、仿真环境 uVision debugger simulator 。因此, MDK ADS 在工具架构组成上有一些不同,这些区别包括:不同的工程管理器,不同版本的 ARM 编译器( compiler ),不同的调试器( debugger ),不同的仿真器( simulator ),以及不同的硬件调试单元,详见表 1

工具结构对比

2.1  编译工具例化形式

  在 ADS 中,当用户要将高级语言代码编译成目标文件时,需要根据目标机器码的不同( 16 位的 Thumb 代码或者 32 位的 ARM 代码),以及高级语言的不同( C 代码或者 C++ 代码)选择不同的编译器可执行文件; RVCT3.0 编译器则将它们全部统一为 armcc ,仅仅通过不同的编译选项进行区分。表 2 较为详细地列出了其中的差别。

2  MDK ADS 编译器的例化形式对比

2.2  POSIX 格式

   MDK 集成了 RVDS 的编译工具 RVCT ,与 ADS 相比,除去编译、链接工具的可执行二进制文件不同之外,两个不同版本编译器的很多编译、链接选项也有所不同。有关编译、链接选项的变化,用户可以参考 ARM 工具文档 “RVCT Compiler and Libraries Guide” 中的 Table E2 Mapping of compiler options

   RVCT 采用了 POSIX 格式的编译、链接选项,所有的多字符选项前必须使用双中划线。例如: ADS 的编译选项 -cpu ,在 MDK 中需要改写成 --cpu ,否则用户在 MDK 中直接使用 ADS makefile 时,工具会产生一个如下警告:

   Warning: L3910W: Old syntax, please use '--cpu'

2.3  ARM ABI 的变化 ARM

   ABI Application Binary Interface for the ARM Architecture 的简称,是一系列 ARM 体系架构标准的集合,囊括了 ARM 二进制代码交互、开发工具以及操作系统等方面。

  对目标文件进行链接之前, MDK 工具的链接器会严格检查各个目标文件( objects ),判断它们是否复合 ARM 体系结构的 ABI 标准。而 MDK ADS 编译、链接工具所遵循的 ARM ABI 是不同版本的,所以将 ADS 的遗留工程直接移植到 MDK 并进行链接时,用户可能会遇到如下的错误或者警告:

   Error: L6238E: foo.o(.text) contains invalid call from '~PRES8' function to 'REQ8' function
   Warning: L6306W: '~PRES8' section foo.o(.text) should not use the address of 'REQ8' function foobar

  这是因为新工具的 ABI 要求在函数调用时,系统必须保证堆栈指针 8 字节对齐,即每次进栈或者出栈的寄存器数目必须为偶数。这是为了能够更加高效地使用 STM LDR 指令对 “double” 或者 “long long” 类型的数据进行访问。而老的 ARM 开发工具 ADS 并没有考虑到新的 ARM 内核架构,其 ABI 对于堆栈的操作仅仅要求 4 字节对齐。所以当用户将在 ADS 中编译、链接成功的工程代码移植到 MDK 上,或者将老的、 ADS 遗留的目标文件、库文件在新工具 MDK 中进行链接时, MDK 的链接器就会报出以上的错误。

  对于以上情况,用户可以通过简单修改代码并重新编译、链接,或者使用特殊的编译选项来解决。

2.3.1  重新编译所有代码

  当用户拥有该 ADS 遗留工程的所有源代码时,使用 MDK 重新编译、链接全部代码是最好的解决方法。 MDK 中的新版本编译工具会重新生成满足堆栈 8 字节对齐要求的目标文件,避免由于堆栈不对齐引起的链接错误。

  当工程中包含汇编代码时,用户可能还需要做少量的代码修改。这些修改包括:

   ①  检查汇编源码中的指令,确保堆栈操作指令是 8 字节对齐的。

  例 1 中, ADS 的遗留代码一次性将 5 个寄存器压栈,由于 ARM 的指令寄存器宽度为 32 位(即 4 字节),显然 5 个寄存器入栈之后,堆栈指针不能够满足 64 位、 8 字节对齐。为了解决这种问题,可以将另外一个并不需要压栈的寄存器( R12 )同时压栈,这样当 6 32 位寄存器进栈之后,堆栈就能满足 64 位对齐了。

  例 1

   STMFD sp!, {r0r3, lr} ; R0,R1,R2,R3,LR (奇数)寄存器入栈
  
   STMFD sp!, {r0r3, r12, lr} ; 将偶数个寄存器入栈

   ②  在每个汇编文件的开头,添加 “PRESERVE8” 指令,见例 2

  例 2

   AREA Init, CODE, READONLY
  
   PRESERVE8

   AREA Init, CODE, READONLY

2.3.2  使用 --apcs /adsabi 编译选项

  当用户没有该 ADS 遗留工程的全部源码,只拥有库文件或者目标文件时,可以通过 --apcs/adsabi 编译选项强制 MDK 的编译器产生复合 ADS ABI 要求的目标文件,以达到与遗留的 ADS 库文件、目标文件兼容的目的。

  注意: ARM 新工具将不会继续支持 --apcs/adsabi 选项。建议用户及时更新工具到最新版本。

2.4  分散加载注意事项

   MDK 同样支持 ADS 的分散加载文件,但是当分散加载文件中涉及到必须被放置 ROOT Region 中的 C 库函数时,有时用户需要做少量修改。

   ROOT Region load address execution address 相同,所以这部分代码在系统初始化时无需进行搬移操作,很多库函数(如 __scatter*.o 或者 __dc*.o )必须被放置在 Root Region 中。

  例 3 分散加载文件的修改。

   ;ADS 中的分散加载文件
   ROM_LOAD 0x0 {
     ROM_EXEC 0x0 {
       vectors.o (Vect, +First)
       _ _main.o (+RO)
       * (Region $$ Table)
       * (ZISection $$ Table)
     }
     RAM_EXEC 0x100000 {
       *.o (+RO,+RW,+ZI)
     }
   }

   ;MDK 中的分散加载文件 1

   ROM_LOAD 0x0 {
     ROM_EXEC 0x0 {
       vectors.o (Vect, +First)
       * (InRoot $$ Sections)
     }
     RAM_EXEC 0x100000 {
       *.o (+RO,+RW,+ZI)
     }
   }

   ;MDK 中的分散加载文件 2

   ROM_LOAD 0x0 {
     ROM_EXEC 0x0 {
       vectors.o (Vect, +First)
       __main.o(*)
       * (Region $$ Table)
       __scatter*.o(*)
       __dc*.o(*)
     }
     RAM_EXEC 0x100000 {
       *.o (+RO,+RW,+ZI)
     }
   }

  在 ADS 中,用户必须在分散加载文件中明确地将特定 section 代码放置在 Root Region 中。而 MDK 为了支持新 RW 压缩机制,采用了新的 region table 格式,这种新的格式并不包含 ZISection $$ Table ,而且新的 scatterloading (__scatter*.o) decompressor (__dc*.o) 必须被放置在 root region 中。所以例 3 ADS 的分散加载文件应该被修改成新的形式。例 3 中提供了两种修改分散加载文件的方法,分散加载文件 1 通过 InRoot $$ Sections 自动将所有必需的库目标放置在 root region 中,而分散加载文件 2 则详细地注明了 __scatter*.o __dc*.o 的位置。

2.5  C 库函数的差异

  为了与新的 ABI 一致, MDK 中的库函数名称与 ADS 可能会不同。 ADS 中的 __rt_* 库函数被替换为 __aeabi_* 。如果用户的 ADS 工程中曾经重定义( retarget )过这些库函数,那么在移植到 MDK 时,需要重新实现这些函数,以满足新 ABI 的要求。表 3 列出了部分库函数的对应关系。

部分库函数对比

移植实例

  结合以上对 MDK ADS 差异的描述,本节将以实例的形式,叙述如何将 ADS1.2 上的遗留代码移植到 MDK 上。

  以 Philips 公司的 LPC2294 ARM7TDMI )为处理器,将一个在 ADS1.2 上开发的,由 LPC2294 控制 LED 闪烁的工程移植到 MDK 上来。从图 1 可以看出,该工程( Legacy_ADS.mcp )共有 4 个源文件( Startup.s tartget.c IRQ.s main.c ),以及 1 个分散加载文件( Scatterload )。

1  ADS 遗留工程

  使用 ADS1.2 编译器:

  编译选项为: -O1-g+
  链接选项为: -info totals -entry 0x00000000 -scatter ./src/Scatterload.scf -info sizes

  得到最终代码尺寸信息如下:

   Total RO Size(Code + RO Data)1640 (1.60kB)
   Total RW Size(RW Data + ZI Data)1128 (1.10kB)
   Total ROM Size(Code + RO Data + RW Data)1640 (1.60kB)

  为了能够使用 ARM 新工具 MDK 的一系列特性,我们需要把 ADS 中的遗留工程移植到 MDK 上来

  其具体步骤如下:

1   MDK 中新建工程

  打开 MDK ,在主菜单中选择 Project(New…(uVision Project ,并给新工程命名为 New_MDK.uv2 ,单击 保存 按钮,见图 2


MDK 中新建工程

  在 MDK 自动弹出的器件选择窗口( Select Device for Target )中选择该工程所对应的处理器型号 “LPC2294” ,并单击 确定 按钮,见图 3 。当 MDK 提示用户是否自动添加启动代码时,选择

2   添加源文件,并设置工程属性

  将 Legacy_ADS.mcp 工程中所有的源文件都添加到新的 New_MDK.uv2 工程中来,见图 4

  单击工程属性快捷键 ,打开工程属性设置窗口,并选择 C/C++ 标签页,设置编译器属性。用户可以根据以前 ADS 工程的编译属性设置,也可以根据当前具体需求重新设置编译属性。在本例中,将 ADS 遗留工程的编译属性 “O1g+” 修改为 “O1g W” 后,拷贝到 Misc Controls 文本框中,见图 5 。这是因为由于编译器版本的变化,其对应的编译选项也有所变化。

  注意: W 选项可以抑止所有的 warning


MDK 中选择合适的处理器

ADS 工程的遗留源代码全部添加到新工程中

编译选项的设置

  对 ADS 工程中的链接选项作适当修改如下,使其复合 POSIX 格式。

--info totals--entry 0x00000000--scatter ./src/Scatterload.scf --info sizes

  选择 Linker 标签,将修改过的链接选项拷贝至 MDK 工程属性的 Linker 属性中,并单击 确定 按钮,见图 6

链接选项的设置

3   Build 工程并适当修改代码

  当所有的工程属性都设置好之后,单击 “Build all target file” 快捷键 ,对整个工程进行编译、链接。在 MDK 窗口的 build 输出一栏中,我们会发现系统出现了一个链接错误 L6238E (见图 7 )。这是由于 MDK 中新版本编译、链接工具与 ADS 的老版本 build 工具采用不同的 ABI 造成的(详见 2.3 小节)。

  为此我们打开该工程中的汇编文件 startup.s ,在该程序第 55 行添加 PRESERVE8 指令,如下所示:

   CODE32
   PRESERVE8
   AREAvectors,CODE,READONLY

4   重新编译链接该工程

  代码修改完毕之后,单击 “Build all target file” 快捷键 ,对该工程进行二次编译、链接。 MDK 将成功生成 New_MDK.axf 文件,并显示其代码尺寸信息为:

   Program Size: Code=1576RO-data=64 RW-data=0 ZI-data=1128

  这些信息同样可以从链接生成的 New_MDK.map 文件中得到。

5   代码调试与固化

  与其他 ARM 开发工具相比较, MDK 拥有非常出色的仿真功能,可以帮助用户在纯软件平台上进行较为精确的调试。用户可以在工程属性设置窗口选择 Simulator 调试(见图 8 ),或者通过硬件调试工具( uLink )进行调试。


链接错误 L6238E


选择 uVision Simulator 作为调试平台

  当选择 Simulator 调试时,单击 debug 快捷键 ,打开 Simulator 调试窗口,见图 9 。为了验证该程序在 LPC2294 硬件平台上是否能够正确执行,通过 GPIO 口驱动 LED 进行循环闪烁,用户可以单击 Peripherals>GPIO>Port2 ,将 GPIO 端口 2 的仿真界面打开,见图 9


9  RVDMK 调试环境

  单击运行快捷键 ,可以看到在 GPIO 端口 2 的仿真调试窗口中, IO 口的输出在不停地循环变化。

  当程序通过了仿真调试之后,用户就可以通过 MDK 的硬件调试工具 uLink 将最终代码固化在非易失性的存储器中了。 uLink 的设置如图 10 和图 11 所示。

10  设置使用 uLink 调试


11  选择 MDK 默认的 LPC2294 Flash 烧写代码

总结

  作为 ARM 新推出的微控制器开发工具, MDK 集成了优秀的 ARM 编译、链接工具 RVCT ,拥有出色的仿真调试功能,集成了代码固化工具 Flash Programming Utilities ,支持 ARM7 ARM9 以及 CortexM3 等多种 ARM 内核,是 ARM 微控制器开发的首选。

原文地址:http://blog.chinaunix.net/u1/58640/showart_1673904.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值