一、OpenJTAG 套件简介
在嵌入式开发中,有很多优秀的调试、仿真工具,比如 Keil、IAR、Rowley Associates 等。
它们的安装、使用都很便利,功能强大,但是价格昂贵(几百美元甚至更多);还要购买相应
的硬件,比如 J-Link、U-Link 等 USB 到 JTAG 的转换盒,这也是一笔不小的开支。
对于学生,或者是开发预算有限的工程师来说,完全可以使用免费的开发工具 Eclipse、
OpenOCD,然后通过一些便宜的 JTAG 转接器(比如并口 JTAG 等)就可以达到接近、甚至超
越上述商业软件的效果。
并 口 JTAG 速率太低,一般很少使用。本教程使用 OpenJTAG 转换器,配合
Eclipse,OpenOCD 等开源软件,就可以完成下载、烧写、调试等任务。
OpenJTAG 的外观及性能见图 1.1、表 1.1,它含有 3 大功能:USB 转串口,USB 转 JTAG,
在线调试。无论是台式机,还是缺乏串口、并口的笔记本,都可以使用
二、嵌入式软件的交叉开发系统
一套完整的交叉开发系统从上到下,可以分为 4 个部件:
- 集成开发环境(IDE,IntegratedDevelopment Environment,比如 Eclipse)、
- 交叉编译工具链、
- 一个接收各种操作命令(复位、暂停、读/写等)的守护进程(Daemon program,如 OpenOCD)、
- 用来连接 PC 与单板的 JTAG 接口板。
1-交叉编译工具链
交叉编译工具链是嵌入式开发中最核心的工具,它被用来编译、链接、调试程序。在集成开发环境出现之前,我们通常是先使用其他编辑工具(比如记事本、Source Insight 等)写好代码,然后通过命令行进行编译、链接。
2-集成开发环境
集成开发环境将各种命令“封装”起来,通过各种按钮就可以编译、调试程序;它还提供一个现代化的软件编辑器。Eclipse 的操作界面如图 1.3 所示
下面以一个例子来看看 Eclipse 是如何与交叉编译工具链协同,来编译、链接程序的。
在图 1.3 的“工程窗口”中有一个“Makefile”文件,Eclipse 根据它来调用交叉编译工具链。Makefile 内容如下:
- 当在 Eclipse 里按下“Build All”、“Build Project”按钮时,就相当于在命令行里执行“make all”命令,它根据 Makefile 的指示编译出 head.o、init.o、leds.o,然后链接成 elf 格式的可执行文件 mmu_elf,最后制作二进制可执行文件 mmu.bin、制作反汇编文件 mmu.dis。
- 当点击 Eclipse 的菜单“Project -> Clear…”时,就相当于在命令行里执行“make clean”命令,它根据 Makefile 的指示删除 mmu.bin、mmu_elf、mmu.dis、head.o、init.o、leds.o。
- 当在 Eclipse 里按下“External Tools”按钮时,它将根据当前工程的配置信息启动OpenOCD,这将在后面说明。
- 当在 Eclipse 里按下“Debug”按钮时,它将根据当前工程的配置信息启动 GNU 源码级别的调试器 arm-elf-gdb.exe(Windows 下)或 arm-linux-gdb(Linux)下,这将在后面说明。
可见,Eclipse 就是一个提供友好操作界面的图形程序,它最终还是根据 Makefile 来编译、链接、清除程序,根据配置信息启动守护进程 OpenOCD、调试器(arm-elf-gdb.exe 或arm-linux-gdb)来调试程序。
Eclipse 的作用并不仅仅是提供按钮来启动其他程序,它的更大用处在于使调试程序更加便利:直接在源码中双击即可设置断点、将鼠标放到某个变量上即可看到它的值、查看内存、查看 CPU 寄存器、点击按钮即可暂停/重新运行程序等等。其实这些功能也是调试器(arm-elf-gdb.exe 或 arm-linux-gdb)实现的,但是 Eclipse 再次把它们“封装”起来,使得“傻
瓜都会用”。
三、4 个部件的相互作用
下面介绍调试程序时,这 4 个部件的相互作用。
使用 Eclipse 进行调试时,它会自动启动调试器(arm-elf-gdb.exe 或 arm-linux-gdb)。请参考图 1.2,Eclipse 使用 GDB/MI 协议与调试器进行通信。
举个例子,当你把鼠标放在 i 上时,Eclipse 就会发出“print i”的命令给 GDB,如图 1.4所示。
调试器根据前面编译出来的 mmu_elf 文件(里面包含指令和符号信息)得知变量 i 的类型是“unsigned long”,地址是 0xb2ffffec。
于是它向守护进程 OpenOCD 发出一个“读内存”的命令“$m0xb2ffffec,4#cs”,这个命令遵循 RSP 协议(Remote Serial Protocol),表示从内存地址0xb2ffffec 处读出 4 字节,如图 1.5 所示。
调试器 OpenOCD 接收到 GDB 的命令后,将它通过 USB 协议发送给 JTAG 接口板,如图1.6 所示。
最后一步就是 JTAG 接口板与 CPU 的交互了。ARM7、ARM9 等 CPU 核里有一个被称为“嵌入式 ICE 宏单元”(Embedded ICE macrocell)的部件,借助它可以对系统进行实时仿真和跟踪调试,要通过 JTAG 接口来访问它。JTAG 接口板完成 USB 协议到 JTAG 协议的转换,如图 1.7 所示。
参考资料:
《Eclipse,OpenOCD,OpenJTAG教程》