在 Cortex-M3 CPU 上通过 printf 进行输出调试,在 BKPT 指令处停止关于 JTAG 和 SW 端口的混淆
我有一个 Keil ULINK2 USB 仿真器盒连接到我板上的 JTAG 连接器,它正在工作与板载 Cortex-M3 CPU(TI/Stellaris/LuminaryMicro LM3S 系列)配合良好。看起来 JTAG 和 SWJ-DP 端口在这些 CPU 上共享相同的引脚(以及板上的连接器)。一个似乎没有 ITM (printf) 功能,而另一个则具有。
以前的固件人们一直使用stdio到UART(串行端口),但我需要释放串行端口,以便调试消息不会干扰从串行端口发送/接收的其他数据,因此我需要跟踪消息去其他地方。遗憾的是我这块板上只有一个串口。我认为该 CPU 中的 ITM(跟踪)功能意味着我可以将调试 printf 消息直接发送到我的调试器/IDE (Keil uVision)。 TI/Stellaris CPU 文档将此功能称为“串行线 JTAG 调试端口 (SWJ-DP)”,据我了解,对此功能的支持绝对是 Keil uVision IDE 中实现的功能。
在我的代码中添加 printf 消息会导致我的代码在开始调试时锁定。锁定似乎位于链接到我的应用程序的 RTL 库中,在函数 _sys_open 中的 BKPT 指令中:
_sys_open:
0x00009D7A B50E PUSH {r1-r3,lr}
0x00009D7C E9CD0100 STRD r0,r1,[sp,#0]
0x00009D80 F7FFFC0F BL.W strlen (0x000095A2)
0x00009D84 9002 STR r0,[sp,#0x08]
0x00009D86 4669 MOV r1,sp
0x00009D88 2001 MOVS r0,#0x01
>>0x00009D8A BEAB BKPT 0xAB
0x00009D8C BD0E POP {r1-r3,pc}
以上似乎是 __rt_lib_init_stdio_1
调用的代码的一部分。
到底是怎么回事?我不知道BKPT是做什么的。我认为它会引发一个软件断点,然后应该由调试器处理? Keil/ARM ULINK2 软件和硬件不应该已经为此进行配置吗?是否有一些技巧可以使调试 printf 与 Keil JTAG/sw 端口一起工作?
我不确定 sw 和 JTAG 端口之间有什么区别。 sw到底意味着什么,我相信它指的是板上JTAG物理连接器的两种可能模式之一,其中JTAG是经典但更有限的模式,没有跟踪支持,sw模式增加了跟踪支持,而不向JTAG添加任何引脚连接器布局?但这是嵌入式系统,神秘是常态。我是 Cortex-M3 开发的新手,自从 ARM7TDMI 时代以来,很多东西对我来说都是新的。但 Keil uVision 打印出以下消息:“ITM 仅适用于 SW 端口,不适用于 JTAG”。 SW 是您必须在主板上设计的不同物理端口吗? (我使用的是定制设计的应用程序板,而不是开发入门板。)
[通过谷歌搜索,我发现 _sys_open
和一些 pragma __use_no_semihosting_swi
以及其他东西是与这个难题密切相关的是,ROM 中的 BRKPT 指令可能是 SWI(“软件中断”)ARM 指令的某种 ARM 变体。]
I have a Keil ULINK2 USB emulator box attached to the JTAG connector on my board, which is working fine with the Cortex-M3 CPU onboard (TI/Stellaris/LuminaryMicro LM3S series). It seems that both a JTAG and a SWJ-DP port share the same pins (and thus connector on your board) on these CPUs. One appears not to have ITM (printf) capability, the other does.
The previous firmware people have always used stdio to UART (serial port), but I need the serial port freed up so that debug messages do not interfere with other data being sent/received to/from the serial port, thus I need for trace messages to go elsewhere. Sadly I only have one serial port on this board. I thought that the ITM (Trace) feature in this CPU meant that I could send debug printf messages directly to my debugger/IDE (Keil uVision). The TI/Stellaris CPU documentation call this feature 'Serial Wire JTAG Debug Port (SWJ-DP)', support for which, I have read, is definitely a feature implemented in the Keil uVision IDE.
Adding a printf message to my code causes my code to lock up when I start debugging. The lockup seems to be here in the RTL libraries which are linked into my application, in the function _sys_open, at the BKPT instruction:
_sys_open:
0x00009D7A B50E PUSH {r1-r3,lr}
0x00009D7C E9CD0100 STRD r0,r1,[sp,#0]
0x00009D80 F7FFFC0F BL.W strlen (0x000095A2)
0x00009D84 9002 STR r0,[sp,#0x08]
0x00009D86 4669 MOV r1,sp
0x00009D88 2001 MOVS r0,#0x01
>>0x00009D8A BEAB BKPT 0xAB
0x00009D8C BD0E POP {r1-r3,pc}
The above appears to be part of code called by __rt_lib_init_stdio_1
.
What is going on? I don't know what BKPT does. I assume it raises a software breakpoint which should then be handled by the debugger? Shouldn't the Keil/ARM ULINK2 software and hardware already be configured for this? Is there some trick to making debug printf work with Keil JTAG/sw ports?
I am unsure what the difference between an sw and JTAG port is. sw means what exactly, I believe it refers to one of two possible modes for the JTAG physical connector on a board, where JTAG is a classic but more limited mode without trace support, and sw mode adds trace support without adding any pins to the JTAG connector layout? But this is embedded systems, where being cryptic is the norm. I am new to Cortex-M3 development, and a lot of this stuff is new to me since the old ARM7TDMI days. But the Keil uVision prints this message out: "ITM works only with SW port, not with JTAG". Is SW a different physical port that you have to design on your board? (I am using a custom designed application board, not a development starter board.)
[Googling around lets me in on the fact that _sys_open
and some pragma __use_no_semihosting_swi
and something else are intimately involved in this puzzle, BRKPT instructions in ROM might be some ARM variant on the SWI ('software-interrupt') ARM instruction.]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这对我来说是一个失败,无法理解 stdio 没有实现,而是您必须提供自己的实现,通常在名为“retarget.c”的文件内完成。文件名是纯粹的约定,但在 Keil 的 uVision/RTLIB 文档中有详细记录(事实证明)
This one was a failure on my part to understand that stdio is not implemented, but rather you must provide your own implementation, usually done inside a file called "retarget.c". The filename is pure convention, but is well documented (as it turns out) inside Keil's uVision/RTLIB documentation
我已经使用 IAR EWW ARM 工具链完成了此操作,但半主机一词让我相信 Keil 方法是类似的。指定要链接的标准库以使用半主机时应该有一个选项。这将在不同的库中进行编译/链接,该库将 printf / putc 通过 JTAG 端口重定向到调试器。
因此,请查看 Uvision IDE 或 make 脚本中的项目选项。在 IAR 链接器命令行中,这是“--semihosting”,但对于 Keil 工具可能有所不同。
BKPT 是工具插入源代码以触发调试器的指令。这就是当调试器不支持硬件断点(或者您已经使用了它们的完整补充)时,IDE 使您能够向代码添加断点的方式。
I've done this with the IAR EWW ARM toolchain, but the term semihosting leads me to believe that the Keil approach is similar. There should be an option when specifying the standard library to link in to use semihosting. That will compile/link in a different library which redirects printf / putc through the JTAG port to the debugger.
So look at the options for the project in the Uvision IDE or in the make scripts. In the IAR linker command line this is "--semihosting" but is probably different for the Keil tools.
BKPT is the instruction the tools insert in the source to trigger the debugger. It's how the IDE enables you to add breakpoints to the code when the debugger doesn't support HW breakpoints (or you have used your full complement of them already).
SW 是一个两线接口,可提供对设备上调试端口的访问。
Arm在这里有一个关于它的.pdf:
http://www.arm .com/files/pdf/Low_Pin-Count_Debug_Interfaces_for_Multi-device_Systems.pdf
SW is a two wire interface that provides access to debugging ports on the device.
Arm have a .pdf about it here:
http://www.arm.com/files/pdf/Low_Pin-Count_Debug_Interfaces_for_Multi-device_Systems.pdf
要在 Keil uVision 中处理这个问题,只需进入项目选项即可。在“目标”选项卡/“代码生成”中,选中“使用 MicroLIB”复选框。
To deal with this problem in Keil uVision just go to project options. In Target tab/Code Generation check the Use MicroLIB checkbox.