Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output debug via printf on a Cortex-M3 CPU, stalls at BKPT instruction + confusion about JTAG and sw ports

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.]

like image 339
Warren P Avatar asked Dec 12 '22 20:12

Warren P


1 Answers

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

like image 199
Warren P Avatar answered Dec 28 '22 06:12

Warren P