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 with finding test escapes – with all the frustration and wasted time that entails. 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, which lets the fire out of many components in rapid succession). Wouldn’t it be nice to have a compiler built-in that provides all of the automated control of assert() with out 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 for 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 benefit of an automated sentry on your API, with none of the misbehavior and disruption of assert(). This allows you to write code like this:
which will generate a breakpoint if 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() facility, 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 up changes so you can make edits in a bunch and save valuable time getting out of debug mode and into edit mode in the edit-compile-debug cycle.
The facility is available from XC8 v1.36, XC16 v1.26 and XC32 v1.42. It can be used for lots more than just automatically checking the parameters your code is called with. You can check array indexes before you index the array to do bounds checking, you can check that pointers are not NULL before dereferencing them. You’re an engineer – let your imagination run wild. 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.