assert() Your Success!

Last modified by Microchip on 2024/01/29 17:56

It’s always nice when everyone plays by the rules. We invest in defined interfaces and robust APIs so we don’t have to suffer from finding test escapes. But you can’t be the police and ensure that your code isn’t called with junk parameters or can you?

In the desktop world, there is a legacy concept of a console which is a carryover from the mainframes of the distant past when there was a physical teletype connected to a special port that was always available for system messages like crashes, core dumps, and abends. You may be aware of the C standard interface called assert(). assert() is implemented like a macro and if the expression passed to it evaluates to false, the behavior defined in the standard is to print a message on the console and exit. This deceptively simple operation can be very powerful but it is also 100% fatal.

In an embedded system, there is rarely a console. Often there are dire consequences for exiting software control (e.g., leaving an H-bridge in a static state as the motor continues to turn and lets the fire out of many components in rapid succession). Wouldn’t it be nice to have a built-in compiler that provides all of the automated control of assert() without the embedded misbehavior inherent in that facility?

The designers of the MPLAB® XC Compiler understand that need and have provided the __conditional_software_breakpoint(int assertion) facility to meet it. The facility takes an assertion (like assert()). (This allows you to do a simple global search and replace any existing assert()s that you may currently have.) If the assertion is false, your debug session stops immediately at a breakpoint. Thus, you have all of the benefits of an automated sentry on your API with none of the misbehavior and disruption of assert(). This allows you to write code like this:

#include <assert.h>

// parameter should be in the range 512
void foo(int parameter)

__conditional_software_breakpoint((parameter >= 5) && (parameter <= 12));

This will generate a breakpoint if the parameter is less than 5 or greater than 12.

The designers went even further, assuring that the facility only generates code when you’re in debug mode, so you can safely and economically leave them all in – even in production code. We all know that production code only stays that way until the current release is shipped and then it’s back to the grindstone! Rather than having to re-instrument the code, leave them in! It doesn’t cost you a thing – in code size or execution time. Don’t worry about squandering precious hardware breakpoints either. The facility uses the _software_breakpoint(), so it is very economical in terms of your debugging resources as well! What’s more, it’s only a breakpoint, so if you can figure out how you were supposed to be called, you can use the MPLAB® X IDE to change the value of the trapped variable and continue on your merry way! You can save your changes and make edits in a bunch, saving valuable time getting out of debug mode and into edit mode in the edit-compile-debug cycle.

The facility is available from MPLAB XC8 v1.36, MPLAB XC16 v1.26, and MPLAB XC32 v1.42. It automatically checks the parameters of your code. Also, you can check array indexes before you index the array to do bounds checking, you can check that the pointers are not NULL before dereferencing them. In all the ways that you’ve been frustrated by misbehaving in the past, __conditional_software_breakpoint can keep you on the right side of the dynamite.