Monitoring serial console through JTAG

30.08.2012 18:15

I've written previously that VESNA has an unfortunately placed debug serial console. The connector with the RX and TX pins also provides power to the microcontroller in the common configuration we have deployed in the field. This means that it's quite hard to connect a terminal emulator to it without resetting the node. While it might seem that debug messages printed on the serial console are only useful in testing and development, we have a common occurrence where deployed VESNAs would stop responding to the network commands. Since checking the serial console is the first step in debugging such an issue, it's important that it's accessible even in a production system.

If you have a JTAG port accessible (and enabled) and an in-circuit debugger (like OpenOCD) that works with GDB you can attempt to monitor what is being printed to the serial port in the following way.

Load up the debug information for the firmware running on the microcontroller, set GDB for remote debugging through in-circuit debugger and enter the following commands:

(gdb) break _write
Breakpoint 1 at 0x80001c8: file hello-world.c, line 43.

This sets a break point on the function that writes to the serial console. I'm using the int _write(int file, char *ptr, int len) syscall hook here, which in turn calls low-level UART functions.

(gdb) commands 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>output *ptr@len
>echo \n

Here we instruct GDB to skip the usual informative messages about a break point being reached, print the array of characters in the function's arguments and continue without the usual command prompt.

(gdb) set height 0

Finally, we disable the built-in pager, so that GDB doesn't wait for confirmation on every screenful of print out. Now we can continue the execution of the program, and GDB will print a line for each invocation of the _write function:

(gdb) c
Note: automatically using hardware breakpoints for read-only addresses.
"Hello, world!\n"
"Hello, world!\n"
"Hello, world!\n"

In a pinch this turns out to be a useful workaround when debugging with no serial console. Be warned though that breaking into GDB this way does seem to incur a significant overhead. Programs that print a lot of output will run significantly slower, although I haven't measured exactly how much. This shouldn't be a problem unless the root of problem you are debugging is time-sensitive or you are calling printf() in interrupt handlers (but you wouldn't be doing that, would you?)

Posted by Tomaž | Categories: Code

Add a new comment

(No HTML tags allowed. Separate paragraphs with a blank line.)