Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4241676
  • 博文数量: 1148
  • 博客积分: 25453
  • 博客等级: 上将
  • 技术积分: 11949
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-06 21:14
文章分类

全部博文(1148)

文章存档

2012年(15)

2011年(1078)

2010年(58)

分类: 嵌入式

2011-04-04 20:19:20

http://www.ibm.com/developerworks/cn/linux/l-arm-toolchain/

如果您对在最普遍的微处理器上开发嵌入式系统感兴趣,那么 Advanced RISC Machines (ARM) 内核是您的最佳选择。本文通过描述一组常用的工具(GNU ARM 工具链),帮助您开始理解嵌入式系统开发的软件部分。

嵌入式系统开发人员最关注的问题之一是,如果通过最少的电能获得最大的处理能力。对于如何在处理器功率和电池消耗之间找到平衡点,ARM 处理器家族拥有最好的设计。

通过积累 20 多年来开发多个版本的经验,ARM 内核获得了最先进的技术。运行在移动电话上(比如 T-Mobile G1 Android)的最新芯片级系统 (SoC) 处理器组合了双核(ARM9 和 ARM11)处理器,从而改进了低功耗平台上的多媒体应用程序的性能。

最新的 ARM 内核支持两种操作状态:ARM 状态,其中内核执行 32 位整词对齐指令;和 THUMB 状态,其中内核执行 16 位半词对齐指令。ARM 模式为处理器提供最大的功率和寻址范围,而 THUMB 模式允许以紧凑、节省内存的方式编写应用程序的某些部分,从而节省内存开销。在这两种模式之间切换是很容易的,并且对很多算法而言,代码的行数可以大大减少。

ARM 处理器通过利用改进的 Harvard 架构 提升了性能。在这种架构中,处理器使用独立的数据和指令缓存,但它们通过相同的总线访问额外内存。另外,指令被装入分为 5 个阶段的 “管道”,从而使并行处理发生在最近加载到管道中的 5 个指令上。换句话说,这 5 个独立的行为(获取、解码、ALU、内存和写)涉及到并行发生的指令。只要管道的流通稳定,代码就能享受到并行带来的速度优势。但如果有一个分支在管道之 外编写代码,就必须重置整个管道,这会损害性能。所以在设计代码时要谨慎,尽量避免使用分支。

ARM 架构提供的一个独特特性是 —— 迫使程序员用全新的、独特的方式思考 —— 可以根据系统标志的当前状态选择执行每个指令。该特性能够避免在某些算法中使用分支,从而保持基于管道的指令和数据缓存机制以最佳的性能运行(因为分支导致不必要地清除缓存)。

大部分 ARM 系统编程发生在使用交叉编译工具的非 ARM 工作站上,其目标是在 ARM 平台上使用。GNU ARM 工具链是一种编程环境,它允许您在设计、开发和使用 ARM 模拟器进行测试时选择自己最喜欢的工作站环境。

GNU 工具链驻留在 CodeSourcery 上(见 参考资料 部分的链接),可以免费下载使用。它也被称为 Sourcery G++ Lite。 除了 GNU C Library 之外,其他所有工具都是根据标准的 GNU Public License version 3 (GPL3) 进行授权的。GNU C Library 根据 GPL version 2.1 进行授权。GNU 工具链中包含的工具有二进制实用程序(binutils)、GNU Compiler Collection (GCC)、GNU Remote Debugger (GDB)、GNU make 和 GNU 内核实用程序。

此外,Sourcery G++ Lite 包还包含大量关于 GNU 工具链的文档,其中包括 GNU Coding Standards 文档 —— 在 GNU 汇编程序文档下面,是很好的读物,因为您可以找到许多关于 ARM 的信息:代码、语法和指令等。

要下载 GNU 工具链,请访问 CodeSourcery 下载站点(见 参考资料)并选择 IA32 GNU/Linux TAR 文件:

arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

有针对主要客户机操作系统的各种 GNU 版本,但本文主要关注在 Linux® 下安装和使用工具链的 Lite 版本。

由于 ARM 设计在其发展过程中已经经历不同的版本,所以这个 Lite 包包含了处理器设计的 3 个最常见版本的不同 C 库,这 3 个版本是 ARM v4T、ARM v5T 和 ARM 7。

接下来,使用 bunzip2 命令将文件提取到您的主目录。




$ bunzip2 arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
$ tar -xvf arm-2008q3-72-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar
.
.
.
(Files listed while being extracted from the archive.)
.
.
.
$

现在,修改您的 PATH 环境变量以访问工具链的 bin 目录。这样,工具就可以使用了。

在工具链的下载页面,您还可以找到几个有用的 PDF 文件和一份详细的入门指南,它们归档了所包含的工具。本文仅提供精简的介绍,帮助您设置好并运行工具链。

如果从事的 ARM 编程超出 Intel® 处理器编程,另一种方法是将符号链接添加到您的 /usr/local/bin 目录,它引用工具链 bin 目录中的工具。通过这种方式,您可以使用快捷方式(比如 as)交互地运行 arm-none-linux-gnueabi-as 命令。清单 2 给出了如何设置这些符号链接的示例。




# cd /usr/local/bin
# which arm-none-linux-gnueabi-as
/home/bzimmerly/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-as
# ln -s /home/bzimmerly/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-as as
# ls -l as
lrwxrwxrwx 1 bzimmerly bzimmerly 76 2009-03-13 02:48 as -> /home/bzimmerly
/Sourcery_G++_Lite/bin/arm-none-linux-gnueabi-as
# ./as --version
GNU assembler (Sourcery G++ Lite 2008q1-126) 2.18.50.20080215
Copyright 2007 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-linux-gnueabi'.
#

使用 which 命令查找该命令的完整路径名,这样方便将其复制粘贴到 ln 命令。然后,使用 ln -s 命令创建符号链接。完成之后,列出符号链接并运行它,核实是否已经成功创建。通过创建引用 GNU 工具链 bin 目录中的所有工具的简单符号链接,您就不需要输入冗长的名字了。当然,每次运行汇编程序时,输入 as 总比输入 arm-none-linux-gnueabi-as 容易!

有许多关于用流行的 C 语言编写 ARM 程序的指南,但关于用汇编语言编写的指南却很少。在本文,我打算打破传统,用汇编语言编写程序 —— 这通常被认为是编程的 “邪端”。这是一个简单的 “Hello World” 类型的程序,其目标是针对特定的 ARM Linux 版本。

本文描述的示例程序被设计为运行在运行 Android Linux 的 T-Mobile G1 移动电话上。它是用通用的方式编写的,因此也可以运行在其他基于 ARM 的 Linux 平台上(仅进行标准的系统调用)。然而,您至少要使用 2.6.16 版本的 Linux 内核,它允许您使用新的 Embedded Application Binary Interface (EABI) 内核系统调用。

注意:要阅读有关为硬件进行 ARM 编程而不是在 Linux 下进行编程的文章,请查看 参考资料 小节提供的 Embedded.com 文章链接。

使用您最喜欢的编辑器,通过清单 3 中的代码创建一个称为 build 的脚本。这个脚本运行 GNU ARM 汇编程序,其后是一个连接器(linker)。创建这个程序的目的是实现一个非常小的可执行程序,所以我使用连接器开关 --strip-all 去除所有调试信息。创建该脚本之后,发出 chmod +x build 命令让它变成可执行脚本。




#!/bin/bash
echo Building the ARM Linux Hello World...
arm-none-linux-gnueabi-as -alh -o hw.o hw.S > hw.lst
arm-none-linux-gnueabi-ld --strip-all -o hw hw.o

接下来,创建名为 hw.S 的源模块,并将清单 4 中的代码添加到其中。




@filename: hw.S

.text
.align 2
.global _start

@ ssize_t sys_write(unsigned int fd, const char * buf, size_t count)
@ r7 r0 r1 r2

_start:
adr r1, msg @ Address
mov r0, #1 @ STDOUT
mov r2, #16 @ Length
mov r7, #4 @ sys_write
svc 0x00000000

@ int sys_exit(int status)
@ r7 r0

mov r0, #0 @ Return code
mov r7, #1 @ sys_exit
svc 0x00000000

.align 2

msg:
.asciz "Hello Android!\n\n"

在 GNU 汇编语言的语法中,“at” 符号 (@) 用于指定行注释。汇编语言忽略 @ 之后的任何内容,直至行末。

这个程序使用两个标准的 Linux 系统调用:sys_write 和 sys_exit。在这两个调用中,以上的汇编语言代码等效于 C 语言的注释形式。这样可以更加容易看到 ARM 寄存器如何恰当地映射到系统调用使用的调用参数。需要记住一个规则,参数是自左至右的,从 r0 到 r6。寄存器 r7 很特别,因为它存储使用的系统调用号码。

svc 0x00000000 指令告诉 ARM 处理器调用 “超级用户”,在本例中是 Linux 内核。

这个工具链为调试底层程序提供流行的 GDB。当程序的运行目标是带有 JTAT 或 ICE 单元的单板计算机时,您可以使用 Sourcery G++ Lite 调试器 (gdb) 远程调试 ARM 代码。

如果您希望像我一样测试代码 —— 在运行在移动电话上的 Android Linux 系统上 —— 您需要使用配套的 USB 连接线将电话连接到工作站,然后使用 Android 软件开发工具箱的 adb push 命令将该程序转移到移动电话中。在移动电话上,在一个包含可执行代码 (/data/local/bin) 的目录中,通过发出 chmod 555 hw 命令让程序变得可执行。(Android 上的 chmod 命令不使用 +x,所以 555 是必要的)。

最后,使用 adb shell 命令连接到电话,并使用 cd 切换到正确的目录,然后使用 ./hw 运行它。如果一切按计划进行,程序的响应应该和在我手机上的响应一样,会出现问候语 “Hello Android!”。

如果您对本文的 ARM 汇编编程感兴趣,可以通过 参考资料 小节提供的链接更多地了解这个处理器设计。深入学习 ARM 内核的最好资源是 ARM 开发宝典 ARM ARM,它是 ARM Architecture Reference Manual 的缩略。

从职业方面考虑:目前全球移动电话的数量十分庞大,并且逐年增加。现在,我们仅需在口袋中携带一个存储量为数 GB 的具有双核处理器的微型计算机,就可以完全访问 Internet,获取即时信息或进行娱乐。移动电话供应商对高级程序员存在巨大的需求。对于流行的 ARM,有很多有趣的工作可以做。您通常可以尽情使用这些工具,并从中享受快乐。编程是科学和艺术的结合,并且是一种最能获得乐趣的职业。


学习

获得产品和技术

  • 从 获取 Sourcery G++ Lite。

  • 下载并阅读 ARM 编程宝典 。

  • 使用可直接从 developerWorks 下载的 IBM 试用软件 构建您的下一个 Linux 开发项目。

阅读(1194) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~