I try to get some debug output using the SWO pin with openocd
version 0.10.0+dev-00512-gfd044600
and gdb-multiarch
.
I compiled the firmware with the ARMToolchain_8-2018-q4
with the flags --specs=nosys.specs --specs=nano.specs --specs=rdimon.specs
, put the function call initialise_monitor_handles();
in the main()
. My .gdbinit
looks like that:
target extended-remote localhost:3333
monitor reset halt
monitor arm semihosting enable
monitor tpiu config internal ../bin/swo.log
load
break main
I installed the call to ITM_SendChar()
in the _putchar()
function like that:
void _putchar(char c) { ITM_SendChar(c) };
The chip is STM32L432KC and the openocd command is:
openocd -f board/stm32l4discovery.cfg
When I print "Test\r\n" string I get some extra characters in the swo.log
file (output from xxd -b swo.log
):
000032e8: 00000001 01010100 00000001 01100101 00000001 01110011 .T.e.s
000032ee: 00000001 01110100 00000001 00001101 00000001 00001010 .t....
The string "Test\r\n" is there but with some extra rubbish. How can I get rid of that?
My workaround now is to cut the nonprintable characters with:
tail -f ../bin/swo.log | tr -cd '\11\12\15\40-\176'
ITM channel can handle 8-, 16- and 32-bit data.
ITM_SendChar()
uses 8-bit (1-byte) stream so you have 1
in every other byte as length of subsequent data portion.
For swo.log
decoding one can use perl script from this post.
Just to clarify, "semihosting" and "SWO" are completely separate concepts. What you describe does not make any use of semihosting so you can skip --specs=rdimon.specs
, initialise_monitor_handles();
and monitor arm semihosting enable
as they are unrelated to your problem.
Semihosting is a way to let the host system implement some of the system calls, by having the target fill in some datastructures in memory and then executing a breakpoint. This triggers the debug host (OpenOCD) which will then read the arguments from target memory, emulate the system call, write the result back to memory, and finally resume the target. This can be used as a stdout
channel but also for much, much more (stdin
, full filesystem emulation, etc.). The downside is that the target is halted during the system call so the method is very intrusive.
SWO on the other hand is a lightweight trace channel which among other things can output arbitrary data via any of the 32 channels of the ITM block. This can be useful as a non-intrusive stdout
channel. Other types of data can also be funneled through the SWO output; timestamping, PC-sampling, DWT traces of variable accesses, performance counters and much more. This multiplexing requires a framing around each data type, which is what you see as the extra bytes in the SWO log-file. The data stream can be decoded by utilities such as Swodec.