要在开发项目中使用OpenOCD,您需要做的不仅仅是将JTAG适配器硬件(加密狗)连接到开发板并启动OpenOCD服务器。您还需要配置您的OpenOCD服务器,以便它知道您的适配器和主板,并帮助您的工作。您可能还想将OpenOCD连接到GDB,可能使用Eclipse或其他GUI。
目前最常见的情况是一个加密狗,一边是JTAG电缆(例如带有10针或20针IDC连接器的带状电缆),另一边是USB电缆。一些加密狗可能使用以太网而不是USB;旧的可能使用PC并行端口,甚至是串行端口。
使用telnet(在许多系统上是telnet localhost 4444)或者GDB与OpenOCD服务器对话。参见第20章[GDB和OpenOCD],第183页。
有许多方法可以配置OpenOCD并启动它。
一个简单方法是使用一个给定的板子将所有涉及的文件打包进一个单一的目录。当您从该目录启动OpenOCD时,它首先在那里搜索配置文件、脚本、通过半托管访问的文件以及您上传到目标板的代码。它也是编写文件的自然位置,例如从电路板下载的日志文件和数据。
配置OpenOCD有两种基本方法,还有多种方法可以混合使用。
区别就在于如何启动服务器:
下面是一个示例openocd.cfg文件,用于使用基于Signalyzer ft2232的JTAG适配器与带有Atmel AT91SAM7X256微控制器的板进行设置:
source [find interface/ftdi/signalyzer.cfg]
# GDB can also flash my flash!
gdb_memory_map enable
gdb_flash_program enable
source [find target/sam7x256.cfg]
下面是该配置的命令行:
openocd -f interface/ftdi/signalyzer.cfg \
-c "gdb_memory_map enable" \
-c "gdb_flash_program enable" \
-f target/sam7x256.cfg
您可以将这么长的命令行封装在shell脚本中,每个脚本支持一个不同的开发任务。比如一个使用特定的固件版本重新刷新板,另一个可能会设置特定的调试或运行时环境。
重要:在撰写本文(2009年10月)时,命令行方法在如何处理变量方面存在问题。例如,在-c "set VAR value"之后,或者在脚本中做同样的事情,变量VAR将没有可以在以后的脚本中测试的值。
这里,我们将重点讨论更简单的解决方案:一个用户配置文件,包括基本配置和任何TCL过程,以简化您的工作
用户配置文件将项目的所有部分捆绑在一起。以下其中一种最符合你的情况:
理想情况下,几乎所有内容都来自其他人提供的配置文件。例如,OpenOCD分发一个脚本目录(可能在 /usr/share/openocd/scripts (Linux) )。电路板和工具供应商也可以提供这些,个人用户网站也可以。-s 命令行选项允许您指定在何处查找这些文件(参见第4章[运行openocd])。 上面的AT91SAM7X256示例就是这样工作的。
三种主要类型的非用户配置文件在scripts目录中都有自己的子目录:
最好的情况是:只包含两个文件,它们处理其他所有内容。第一个是接口配置文件。第二个是特定于主板的,它设置JTAG tap和它们的GDB目标(通过推迟一些target.cfg文件),声明所有闪存,除了满足您的截止日期外,您什么也不用做:
source [find interface/olimex-jtag-tiny.cfg]
source [find board/csb337.cfg]
带有单个微控制器的电路板通常不需要超过目标配置文件,如AT91SAM7X256示例。这是因为它没有外部存储器(FLASH、 DDR RAM),并且板的差异被应用程序代码封装。
也许您还不知道您的板子是什么样子的JTAG。一旦您知道要使用interface.cfg文件,您可能需要OpenOCD的帮助来发现电路板上的内容。一旦找到JTAG tap,您就可以搜索适当的目标和板配置文件…或者你自己写,从下往上写。参见[Autoprobing]
您可以经常重用一些标准配置文件,但需要编写一些新的配置文件,可能是board.cfg文件。您将使用本用户指南后面描述的命令指南,并在下一章中使用这些指南。
例如,可能有针对JTAG适配器和目标芯片的配置文件,但是您需要一个新的特定于主板的配置文件来访问特定的闪存芯片。
或者您可能需要为围绕Cortex-M3内核构建的新芯片编写另一个目标芯片配置文件。
注意:当您编写新的配置文件时,请提交它们以便在下一个OpenOCD版本中包含它们。例如,board/newboard.cfg文件将帮助该板的下一个用户,target/newcpu.cfg文件将帮助支持使用该芯片的任何板的用户。
尽可能重用现有的配置文件。首先查看scripts/boards区域,然后查看scripts/targets。您可能会找到一个很好的电路板配置示例。
在编写配置文件时,将可重用部分(该接口、芯片或主板的每个用户都需要的东西)与特定于您的环境和调试方法的部分分开。
一些特定于项目的实用程序例程可能会加快您的工作速度。编写它们,并将它们保存在项目的用户配置文件中。
例如,如果您正在使引导加载程序在板上工作,那么能够将“加载到RAM之后”的部分与设置DDR RAM控制器和时钟的繁琐的早期代码分开调试是很好的。像这样的脚本,或者更支持gdb的同类脚本,可能会有所帮助:
proc ramboot { } {
# Reset, running the target’s "reset-init" scripts
# to initialize clocks and the DDR RAM controller.
# Leave the CPU halted.
reset init
# Load CONFIG_SKIP_LOWLEVEL_INIT version into DDR RAM.
load_image u-boot.bin 0x20000000
# Start running.
resume 0x20000000
}
然后,一旦代码工作,你需要使它从NOR闪存启动,此时需要一个另外的实用程序。另外,一些开发人员使用GDB编写flash。(如果您正在使用基于flash的微控制器应用程序而不是引导加载程序,则可以使用类似的脚本。)
proc newboot { } {
# Reset, leaving the CPU halted. The "reset-init" event
# proc gives faster access to the CPU and to NOR flash;
# "reset halt" would be slower.
reset init
# Write standard version of U-Boot into the first two
# sectors of NOR flash ... the standard version should
# do the same lowlevel init as "reset-init".
flash protect 0 0 1 off
flash erase_sector 0 0 1
flash write_bank 0 u-boot.bin 0x0
flash protect 0 0 1 on
# Reboot from scratch using that new boot loader.
reset run
}
从NAND引导时,您可能需要更复杂的实用程序。这通常涉及一个额外的引导加载程序阶段,从片上SRAM运行以执行DDR RAM设置,以便它可以加载主引导加载程序代码(该代码不适合该SRAM)。
其他辅助脚本可能用于编写生产系统映像,涉及的内容远远不止一个三阶段引导加载程序
有时,您可能希望对正在开发的软件进行一些小的更改,以帮助更好地进行JTAG调试。例如,在C或汇编语言代码中,您可以使用#ifdef JTAG_DEBUG(或相反)来处理代码处理问题,如:
芯片供应商通常提供高度可配置的软件开发板,这样他们就可以支持产品板可能需要的所有选项。确保任何跳线或开关与您正在使用的系统配置相匹配。
常见问题包括:
另外,您当然应该有reset-init事件处理程序来设置硬件以匹配跳线配置。这尤其包括用于为CPU时钟的振荡器或锁相环,以及访问外部存储器和外设所需的任何存储器控制器。如果没有这样的处理程序,你将无法访问这些资源,没有工作的目标固件可以做那个设置…当您试图调试目标固件时,这可能会很尴尬。即使有一个ROM引导加载程序可以处理一些问题,它也很少提供对所有主板特定功能的完全访问。