跟我一起学OpenOCD(一)

1. 前言

当今开发环境中,嵌入式工程师都会十分熟悉自己项目用到的调试器和调试软件,但是你真的清楚,
- 所谓的JTAG、SWD是什么?
- 调试器又是怎样工作的?
- 为什么每一个厂家甚至每一款芯片都需要用到不同的调试器,大家都使用JTAG协议,用一款调试器不好嘛?
- CMSIS-DAP 又是什么鬼,和JTAG有什么不同么?
如果你真的清楚如上几个问题,那我相信,OpenOCD你一定听说过,并且很可能已经使用过,如果你并不了解如上几个问题,想来你在读完本文后,会找到满意的答案。

本文OpenOCD技术部分讲解大部分根据OpenOCD User’s Guide翻译所得,增加了自己的理解和一些演示的案例,如果英文能力好的同学可以直接阅读原文,笔者能力有限,如有问题欢迎各位侠士随时指正!

1.1. 什么是OpenOCD

OpenOCD(Open On-Chip Debugger)开源片上调试器,最初是由Dominic Rath同学还在大学期间发起的(2005年)项目。OpenOCD提供了嵌入式设备的调试、程序下载和边界扫描功能。

OpenOCD的功能是在仿真器的辅助下完成的,仿真器是能够提供调试目标的电信号的小型硬件单元。仿真器是必要的,因为调试主机(运行OpenOCD的主机)通常不具备这种电信号的直接解析功能。

仿真器支持一个或多个传输协议,每个协议涉及不同的电信号,且使用不同的协议栈进行消息传递。市面上有很多种仿真器,并且这些仿真器的命名没有统一的规律。

仿真器有时候会被封装成独立的加密狗,这种称为硬件接口加密狗。一些开发板上面直接集成了硬件接口加密狗,这样可以使开发板通过USB直接连到主机上进行调试。

例如,JTAG仿真器支持JTAG协议的信号,可以用来进行TAPs和目标板子之间符合JTAG协议(IEEE 1149.1)的通讯。TAP(Test Access Port)是处理特殊指令和数据的单元。TAPs在芯片与板子之间和之内以菊花链的形式进行连接。JTAG支持调试和边界扫描。

还有SWD仿真器,这种仿真器支持使用SWD(Serial Wire Debug)信号与一些比较新的ARM芯片进行通讯,而且还可以作为那些同时支持JTAG和SWD的芯片的仿真器。不过SWD仅支持调试,不支持边检扫描。

对于一些芯片,还有专门的编程下载器,这些下载器仅支持擦写FLASH的功能,不支持调试和边界扫描。对于此类专用下载器,OpenOCD暂时并不支持。

加密狗:OpenOCD目前支持多种类型的硬件加密狗:基于USB的,基于并行端口的,以及其他在内部运行OpenOCD的独立盒子。 请参见第2章[仿真器硬件],第5页。

GDB调试:它允许ARM7(ARM7TDMI和ARM720t),ARM9(ARM920T,ARM922T,ARM926EJ-S,ARM966E-S),XScale(PXA25x,IXP42x),Cortex-M3(Stellaris LM3,ST STM32和Energy Micro EFM32)和基于Intel Quark(x10xx)的内核使用GDB协议进行调试。

Flash编程:擦写FLASH支持外部CFI兼容NOR闪存(Intel和AMD / Spansion命令集)和几个内部闪存(LPC1700,LPC1800,LPC2000,LPC4300,AT91SAM7,AT91SAM3U,STR7x,STR9x,LM3,STM32x和EFM32)。包括各种NAND闪存控制器(LPC3180,Orion,S3C24xx等)的初步支持。

2. 安装

2.1. Linux 系统

  1. 到OpenOCD下载官网最新软件,本文撰写时最新软件版本为0.10.0。OpenOCD:https://sourceforge.net/projects/openocd/
  2. 解压后,进入openocd-0.10.0目录,右键在终端中打开,tomato@tomato-PC:~/Software/openocd-0.10.0$
  3. 英文好的同学可以直接点开INSTALL这个文件,根据指导一步步安装,英文不好的童靴可以继续往下看后面几步
  4. 运行 $ ./configure 命令,进行OpenOCD配置,可配置的项目可以通过 $ ./configure -h 命令查看帮助信息。 笔者的调试器是J-Link,所以还要运行如下命令进行使能 $ ./configure --enable-jlink
    • 此处注意,由于笔者使用的是deepin系统,基于Debian,使能jlink的时候系统提示configure: error: libusb-1.x or libjaylink-0.1 is required for the SEGGER J-Link Programmer,笔者选择安装libusb-1.x这个组件,使用如下命令进行安装 $ sudo apt-get install libusb-1.0.0-dev
  5. 运行 $ make 进行编译
    • 此处注意,OpenOCD可以使用gcc和clang两个编译器进行编译,但是笔者的系统默认编译器为 gcc 7.2,在编译过程中会由于报出warning而终止,到网上查了一下发现是OpenOCD的bug,后面有修改。为了保证当前顺利安装,笔者选择忽略warning,继续编译。运行 $ ./configure --disable-werror命令进行不把warning变成error的配置,并会生成相应的makefile。然后运行$ make 进行编译。
  6. 运行 $ sudo make install 进行软件安装
  7. 安装完成后,运行 $ openocd -V 命令,查看当前软件版本。我安装的环境当前会返回 Open On-Chip Debugger 0.10.0字样。

如果后续想要卸载OpenOCD,可以到OpenOCD的目录下,使用 $ make uninstall 进行卸载。

2.2. Windows 系统

TBD

3. 运行

安装好OpenOCD后,需要根据你的操作系统,设置访问debug适配器的权限。在Linux系统上,通常涉及/etc/udev/rules.d文件夹的操作。OpenOCD会附带一个通用规则文件60-openocd.rules,在OpenOCD解压后文件夹的contrib 目录中。按照文件中d的说明提示进行操作,OpenOCD 0.10.0版本的文件提示为 # Copy this file to /etc/udev/rules.d/ 。Windows系统需要针对每一个不同的外设,适配复杂的驱动配置。本文没有对此进行详细说明。

然后,可以通过不同选项来调用OpenOCD的服务。 --help选项会出现如下提示:

bash$ openocd --help
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Open On-Chip Debugger
Licensed under GNU GPL v2
--help       | -h   display this help
--version    | -v   display OpenOCD version
--file       | -f   use configuration file <name>
--search     | -s   dir to search for config files and scripts
--debug      | -d   set debug level <0-3>
--log_output | -l   redirect log output to file <name>
--command    | -c   run <command>

如果没有输入 -f-c 的选项命令,OpenOCD会试图读取openocd.cfg这个配置文件。如果定义了不同的配置文件,需要使用-f命令。示例如下:

openocd -f config1.cfg -f config2.cfg -f config3.cfg

配置文件和脚本按照如下目录进行顺序搜索:

  1. 当前工作目录
  2. 命令选项-s后面跟随的目录地址
  3. 使用 add_script_search_dir 命令定义的目录地址
  4. $HOME/.openocd(非Windows)
  5. OPENOCD_SCRIPTS环境变量设置
  6. $pkgdatadir/site站点中的脚本
  7. $pkgdatadir/scriptsOpenOCD支持的脚本库

需注意: 配置脚本的名字和路径中,不能包含 # 这个特殊字符,该字符为Tcl命令的起始标志。

3.1. 简单的启动(非用户自定义)

好的情况下,仅用两个库里自带的脚本就可以启动服务并连接JTAG适配器,达到开箱即用的效果。不过服用这些脚本虽然能够帮助你启动功能,距离功能完善还是需要进行一些自定义配置。这些可以参考 [OpenOCD Project Setup] 这一章。

如果找到了适用于 JTAG适配器或目标板子的脚本,可以通过如下几条命令连接上JTAG适配器,并启动调试功能。

openocd -f interface/ADAPTER.cfg -f board/MYBOARD.cfg
openocd -f interface/ftdi/ADAPTER.cfg -f board/MYBOARD.cfg

如果要进行复位信号的配置,可以使用 -c 'rreset_configtrst_and_srsteset_config'命令。如果一切正常,将会看到如下类似的反馈信息。

Info : JTAG tap: lm3s.cpu tap/device found: 0x3ba00477
(mfg: 0x23b, part: 0xba00, ver: 0x3)

如果看到了 “ap/device found” 反馈字样,并且没有 warning信息,则证明JTAG通讯已经建立。这是一个里程碑步骤,为了达到这一步还可能进行更多的项目设置。

3.2. OpenOCD 在启动时做了些什么

OpenOCD首先处理命令行上提供的配置命令,如果没有 -c-f 的命令,OpenOCD会处理名为 openocd.cfg 文件中的命令。可以查看[Configuration Stage]章节的介绍。在配置阶段最后,OpenOCD会使用配置好的命令参数验证JTAG扫描链,所以要确保配置正确。通常OpenOCD会作为server一直运行。OpenOCD的命令也可以提前终止配置阶段,执行其它工作(如烧写flash),此时不会作为server一直运行,工作任务结束后会自动关闭。

当OpenOCD作为Server运行时,会等待Telnet,GDB,RPC等进行连接,并且处理通过这些通道发出的指令。

如果遇到问题,可以通过 -d 命令开启内部调试信息输出。也可以使用-c来 开/关 Jim-Tcl的交叉配置命令脚本。

使用-d命令会将debug_level设为第3级,这会输出最多的调试信息。debug_level默认设为2,仅输出警告和错误的消息。也可同过telnet 或 gdb 的debug_level对其进行设置。(参考 [debug level])

可以使用 -l <logfile> 命令讲输出的调试信息保存至文件中。需要注意,无论是否能够和目标建立连接,OpenOCD会都运行GDB & telnet的服务。通常只有正确设置目标板子后,JTAG控制器才能有响应。GDB会执行GDB初始化脚本中的命令。

OpenOCD 工程启动

如果需要使用OpenOCD开发项目,首先要启动OpenOCD的服务,然后需要根据目标板和调试器进行配置。还可以通过 GDB,或Eclipse等一些GUI工具进行操作。

连接JTAG调试器

现在常见的情况是,一边是JTAG线束的加密狗(例如:有10针或20针IDC连接器的带状电缆),另外一边是USB线束。除了USB,还有一些是 网口、并口、串口等。


4. 附录1: OpenOCD当前支持的仿真器硬件

4.1. 加密狗

如果选择使用加密狗,如下几点是需要考虑的:
1. Transport: 是否支持所需要的通讯协议?OpenOCD主要关注的是JTAG协议。
2. Voltage: 目标是哪种电压,1.8, 2.8, 3.3, 5V?加密狗是否支持这些?是否需要转换器?
3. Pinout: 目标板的引脚定义?加密狗是否支持?是否需要转换器?
4. Connection: 计算机是否有所需要的USB、并行端口、网口?
5. RTCK: 是否期望将其使用到具有RTCK功能的芯片和板子上(自适应时钟)?

4.2. 独立的JTAG探测器

Ultimate Solutions的ZY1000在技术上不是加密狗,而是一个独立的JTAG探测器,与大多数加密狗不同,它不需要在开发人员的主机上运行任何驱动程序。 使用DHCP或静态IP分配安装在网络上后,用户可以从任何主机本地或远程访问ZY1000探针,并可访问分配给探针的IP地址。 ZY1000提供直观的Web界面,可直接访问OpenOCD调试器。 用户还可以直接在ZY1000上运行GDBSERVER,以充分利用GCC和GDB来调试目标上运行的嵌入式Linux或NetBSD的任何分发。 ZY1000支持RTCK和RCLK或自适应时钟,并具有内置继电器,可远程为目标供电。 有关更多信息,请访问: ZY1000

4.3. 基于 USB FT2232

市场上有许多USB JTAG加密狗,其中许多基于来自“Future Technology Devices International”(FTDI)的芯片,称为FTDI FT2232, 这是一个USB全速(12 Mbps)芯片。可以访问FT2232查看更所信息。 2009年第二季度,FTDI芯片的USB高速(480 Mbps)版本开始在JTAG适配器中推出。2012年左右,出现了一种新的变种 - FT232H--这是FT2232H的单通道版本。 (使用高速FT2232H或FT232H芯片的适配器可能支持自适应时钟RTCK。)

FT2232芯片非常灵活,可以支持其他一些传输选项,例如SWD协议,或用于下载某些芯片的特殊SPI协议。FT2232有两个信道,一个可用于UART适配器,另一个用于仿真器适配器。

此外,一些开发板集成了FT2232芯片,可用作内置低成本调试适配器和USB转串口解决方案。

如下为一些产品列举:
- usbjtag: http://elk.informatik.fh-augsburg.de/hhweb/doc/openocd/usbjtag/usbjtag.html
- jtagkey: http://www.amontec.com/jtagkey.shtml
- jtagkey2: http://www.amontec.com/jtagkey2.shtml
- oocdlink: http://www.oocdlink.com
- signalyzer: http://www.signalyzer.com
- Stellaris Eval Boards: http://www.ti.com
- TI/Luminary ICDI: http://www.ti.com
- olimex-jtag: http://www.olimex.com
- Flyswatter/Flyswatter2: http://www.tincantools.com
- turtelizer2: http://www.ethernut.de
- comstick: http://www.hitex.com/index.php?id=383
- stm32stick: http://www.hitex.com/stm32-stick
- axm0432 jtag: http://www.axman.com
- cortino: http://www.hitex.com/index.php?id=cortino
- dlp-usb1232h: http://www.dlpdesign.com/usb/usb1232h.shtml
- digilent-hs1: http://www.digilentinc.com/Products/Detail.cfm?Prod=JTAG-HS1
- opendous: http://code.google.com/p/opendous/wiki/JTAG
- JTAG-lock-pick Tiny 2: http://www.distortec.com/jtag-lock-pick-tiny-2
- GW16042: https://shop.gateworks.com/index.php?route=product/product&path=70_80&product_id=64

4.4. USB-JTAG/Altera USB-Blaster 兼容机

这些设备也显示为FTDI设备,但与FT2232设备不兼容,但是它们的协议是兼容的。USB-JTAG设备通常由遵循CPLD的FT245构成,CPLD可以理解特定协议,或者使用其他硬件模拟的协议。

它们可能出现在不同的USB VID/PID下,具体取决于特定产品。若使用OpenOCD进行配置连接,可以将驱动程序配置为搜索任何VID/PID。

如下为一些产品示例:
- USB-JTAG: http://ixo-jtag.sourceforge.net/
- Altera USB-Blaster: http://www.altera.com/literature/ug/ug_usb_blstr.pdf

4.5. 基于 USB J-Link

SEGGER J-Link适配器有很多不同的OEM版本。它是基于微控制器的JTAG调试器的一个示例,内部使用了AT91SAM764芯片。

如下为一些产品示例:
- SEGGER J-Link: http://www.segger.com/jlink.html
- Atmel SAM-ICE: http://www.atmel.com/tools/atmelsam-ice.aspx
- IAR J-Link: https://item.taobao.com/item.htm?spm=a230r.1.14.27.1eac49774LE8rV&id=560873858295&ns=1&abbucket=4#detail

4.6. 基于 USB RLINK

Raisonance有一个名为RLink的适配器。它在STM32 Primer上,永久性地连接到JTAG线。它也在STM32 Primer2上,但是Primer2上的连接的是SWD,而不是JTAG。

  • STM32 Primer: http://www.stm32circle.com/resources/stm32primer.php
  • STM32 Primer2: http://www.stm32circle.com/resources/stm32primer2.php

4.7. 基于 USB ST-LINK

ST(意法半导体)有一个名为ST-LINK的调试器。仅适用于ST 芯片,尤其是STM32和STM8。

  • ST-LINK: http://www.st.com/internet/evalboard/product/219866.jsp
  • ST-LINK/V2: http://www.st.com/internet/evalboard/product/251168.jsp

4.8. 基于 USB TI/Stellaris ICDI

德州仪器有一个称为ICDI的适配器。这与安装在评估板上的基于FTDI的调试器不同。ICDI适用于Stellaris LaunchPad系列。

4.9. 基于 USB CMSIS-DAP

ARM发布了一个名为CMSIS-DAP的接口标准,简化了将调试器连接到基于ARM Cortex的目标板上,具体可以到官网查看CMSIS-DAP

4.10. 其它 USB 仿真器

  • USBprog: http://shop.embedded-projects.net/
  • USB - Presto: http://tools.asix.net/prg_presto.htm
  • Versaloon-Link: http://www.versaloon.com
  • ARM-JTAG-EW: http://www.olimex.com/dev/arm-jtag-ew.html
  • Buspirate: http://dangerousprototypes.com/bus-pirate-manual/
  • opendous: http://code.google.com/p/opendous-jtag/
  • estick: http://code.google.com/p/estick-jtag/
  • Keil ULINK v1: http://www.keil.com/ulink1/
  • TI XDS110 Debug Probe: http://processors.wiki.ti.com/index.php/XDS110

4.11. 基于IBM PC并行打印口

有两条著名的“并口JTAG”线束,分别是Xilinx DLC5和Macraigor Wiggler。市场上有许多克隆和变体。

并行端口变得越来越不常见,因此如果有选择,应该避免使用这些调试器,而选择基于USB的端口。

  • Wiggler: http://www.macraigor.com/wiggler.htm
  • fla arm-jtag: https://www.olimex.com/Products/ARM/JTAG/ARM-JTAG/

5. 附录2: 关于 About Jim-Tcl

OpenOCD使用了一种名为 Jim-TCL 的小型 TCL解析器。这种编程语言提供了简单和可扩展的命令解析器。

本本提供的所有命令都是Jim-Tcl的扩展。 您可以将它们用作简单的命令,而无需了解有关Tcl的任何内容。 或者,您可以使用它们编写Tcl程序。

以在网站http://jim.tcl.tk 上了解更多相关信息。

  • Jim 与 Tcl
    • Jim-Tcl是着名的Tcl语言的精简版本。 Jim-Tcl的功能要少得多。 Jim-Tcl是几十个.C文件和.H文件,并实现了基本的Tcl命令集。 相反:Tcl 8.6是一个包含1540多个文件,总共4.2 MB 的zip文件。
  • 缺少的功能
    • OpenOCD的做法是仅添加必要的Tcl功能。所以在OpenOCD中还有大量的Jim-Tcl可选功能都没有添加。
  • 脚本
    • OpenOCD 的配置脚本是 Jim-Tcl 的脚本。如今,OpenOCD的命令解析器融合了较新的Jim-Tcl命令,和较旧的原始命令。
  • 命令
    • 在OpenOCD的telnet命令行中(或者通过GDB监视器中的命令行),每次可以键入一个Tcl for()循环,设置变量等操作。本文提到了一些从startup.tcl文件到启动服务的命令,这些命令可以通过Tcl脚本的形式进行实现。
  • 变更记录
    • Jim-Tcl在2008年春季被引入到OpenOCD中。到2010年秋季,在0.5版本发布前,OpenOCD使用了Jim-Tcl作为Git的子模块,这样极大的简化了Jim—Tcl的升级。
  • Tcl快速入门
    • 本文第TBD章会进行Tcl的快速入门,如有需要可以阅读参考。