I’m not a big fan of using printf() in embedded applications, but I have to admit that in some cases it is very useful. One problem in debugging embedded systems debugging is getting values or information off the target: because of the limited resources this can be very challenging.
So why not doing this with the debugger in an automated way? And here dynamic printf breakpoints can help: it adds printf()-style output on-the-fly to your program without the need to recompile or restart your program, without the need to run printf() on the target:
The feature is the ability for the debugger or debug session to use the application printf() to communicate to the outside world. Instead that the code calls directly the printf() function, it is the debugger which can do this.
One way to output information in printf() style to the host is using semihosting (see Silicon Shortage and Semihosting with NXP MCUXpresso SDK on FRDM-KE02Z), however this requires the printf() code executed on the target with debugger intervention which is very intrusive.
So why not use the debugger to get the information off the target, but have the printf() itself exected by the debugger on the host? Here is where the Eclipse CDT Dynamic Printf Breakpoint feature comes into play.
There is a feature in Visual Studio Code named logpoints. The Eclipse dynamic printf is a feature of Eclipse CDT 8.4. Note that the feature recent gdb version of 7.7 or later. In this article I’m using the NXP MCUXpresso IDE 11.5.0 which supports dynamic printf breakpoints. What it does is when hitting a dynamic breakpoint, it inserts on-the-fly a call the printf() with the given arguments.
Adding Dynamic Printf Breakpoint
The breakpoint can be added as usual in the disassembly or source view, like any other breakpoints:
If adding several breakpoints, I can change the default type of breakpoint to be added:
By default it adds a breakpoint printing the source line:
That default can be changed to anything printf() would accept. So for example I can print the value of a variable:
One thing to keep in mind is that the output goes to the Debugger Console view:
The gdb used feature for dynamic printf is the dprintf command. You can see this if you do a ‘info break’:
The behavior of it is highly configurable, and by default it uses the printf() on the host (gdb). Usint the ‘set dprintf-style’ it is possible to change this to the printf() code on the target or to any other function you specify. To find out what is getting called, check ‘dprintf-function’ and ‘dprintf-style’: Below it shows that it is using the printf() of gdb.
With ‘set dprintf-style call’ it will call e.g. the printf() application code. In that case, make sure you have it present (linked) in your application, e.g. through using semihosting.
Keep in mind that that this feature is still rather intrusive compared to natively printing things over an UART or similar channel. But because it uses the printf() in the debugger and on the host, I don’t have to add the printf code to my application, and it is only used with the debugger: So this is fine and especially useful for ‘sporadic’ printf’s. Do not use dynamic printf breakpoints in ‘tight’ loops or too frequently, as this can add a lot of overhead and making the target/debugger unresponsive.
The other thing is that of course the debugger needs to ‘see’ the variables/symbols in the active context where the breakpoint is installed. If that variable is not visible or does not exist, you will get an error message:
Dynamic printf comes handy if I need to print out values from the target or any other kind of information, without having printf itself present on the target as it gets executed on the host if using dprintf-style with gdb. It is still intrusive as the debugger halts the target, prints the output and resumes it. If not overusing that feature, it is very useful and versatile feature for debugging an embedded application. The gdb dprintf functionality makes it very configurable and versatile, so this is one more hidden gem inside the GNU debugger and Eclipse.
Happy printing 🙂
- Dynamic printf in Eclipse: https://www.eclipse.org/community/eclipse_newsletter/2017/april/article2.php
- Dynamic printf in CDT: https://wiki.eclipse.org/CDT/User/NewIn84#Dynamic-printf
- GDB breakpoints: https://www.sourceware.org/gdb/current/onlinedocs/gdb.html#Breakpoints
- Visual Studio Code Log Points: https://code.visualstudio.com/docs/editor/debugging#_logpoints
- Automatic Variable, Expression and Memory Display with GDB and Eclipse
- Why I don’t like printf()