Programming embedded programs: making use of assertions and Design by Contract

[ad_1]

On this installment, you will notice tips on how to apply Assertions and Design by Contract (DBC) ideas to embedded programs.

Within the earlier episode of this sequence, you realized what assertions and Design by Contract (DBC) are, how to think about them, and tips on how to use them correctly. At present, you will notice tips on how to apply these ideas to embedded programs.

Lesson 48 Assertions and Design by Contract, Half-2

Embedded Assertions

The final lesson launched the usual assert() macro from the C library. Nonetheless, in embedded programs, you nearly at all times should outline custom-made assertions [1], which isn’t sophisticated however requires a couple of concerns, as defined within the video.

First, the usual assert() facility makes use of the usual macros __FILE__ and __LINE__ to establish the assertion inside a given file and at a selected line. Nonetheless, embedded assertions have to be extra secure and constant to be testable. For instance, the __LINE__ quantity is kind of an unstable identifier for an assertion as a result of including or eradicating any strains of code adjustments all the next line numbers. A extra secure answer proven within the video is to make use of a numerical identifier (distinctive inside a given file) explicitly assigned to the assertion by the developer.

Equally, the string generated by the __FILE__ macro typically relies on how the file is specified to the compiler. If the file is specified with the trail identify, __FILE__ expands accordingly. Additionally, in the event you use a number of assertions in a given file, some embedded compilers may generate a number of copies of the __FLILE__ string, which is wasteful. A proposed answer is to explicitly outline the file string (usually on the high of the file) after which reuse that string in all assertions inside the file.

The following consideration is the construction of the customized assertion macro, which may be outlined as an if-statement or an expression with the ternary operator (?:). The video makes use of the ternary operator, as in probably the most normal assert() implementations.

Lastly, the customized assertion macros supply a possibility to use parts of DBC (Design by Contract). For instance, you may significantly enhance the documentation facet of your assertions by offering assertion variants for preconditions, postconditions, invariants, and errors (incorrect paths by way of the code). The video makes use of assertion variants REQUIRE, ENSURE, INVARIANT, and ERROR, borrowed from the Eiffel programming language that natively implements DBC [2].

The Assertion Handler

In case of failure, all customized assertion variants name a customized assertion handler. This assertion handler mustn’t return and must be explicitly marked as such, for instance, by the C99 normal _Noreturn specifier. This may help the compiler optimize the unreachable execution paths.

Moreover, in the event you use a static evaluation instrument, the assertion handler must be given the no-return semantics, just like the video demonstrates for the PC-Lint-Plus static evaluation instrument. This helps the instrument to raised perceive your code and keep away from diagnostics for the asserted circumstances.

{Hardware} Assertions

To date, this dialogue has solely addressed software program assertions positioned explicitly within the supply code. Nonetheless, a number of failure circumstances can even come up in {hardware}. For instance, within the lesson concerning the startup code, you’ve encountered {hardware} fault exceptions for ARM Cortex-M, equivalent to HardFault, MemManage, BusFault, and UsageFault. Historically, {hardware} faults haven’t been seen as associated to assertions, however for all intents and functions, the {hardware} fault handlers and the assertion handler have the identical perform. Subsequently, since you could implement sturdy {hardware} fault handlers anyway, you would use only one frequent handler for {hardware} and software program assertions.

Assertions and Purposeful Security

The essence of purposeful security requirements, equivalent to IEC 61508, could be summarized in simply two key elementary ideas [3]:

Carry out the meant perform appropriately
Fail in a predictable method

One other approach of claiming the identical factor is that the first aim of purposeful security requirements is to keep away from failing unpredictably. Probably the most harmful scenario arises when the embedded software program fails silently and retains operating unpredictably. Such code can kill individuals [4]. Subsequently, all purposeful security requirements strongly advocate self-checking mechanisms, together with assertions [5].

Disabling Assertions

The usual C assertions are meant just for debugging and infrequently get disabled within the launch model. Many embedded builders apply this philosophy, however disabling assertions within the closing product contradicts the purposeful security mindset. But in addition, all of the analogies for forming the correct psychological mannequin of assertions clearly present that disabling them is unnecessary, whether or not you consider assertions as fuses, guardrails, insurance coverage insurance policies, or seatbelts.

Testing Assertions

Assertions left within the closing launch can carry down the entire system. This energy of assertions necessitates thorough testing, which requires particular concerns.

First, you could take a look at the person assertions by deliberately injecting errors and verifying {that a} particular assertion fails. (That is the place you want secure and constantly identifiable assertions talked about earlier.) In that case, a failing assertion represents a passing take a look at. Sadly, most unit testing frameworks don’t help such a “reversed logic.” Additionally, you have to be cautious that the system will get cleanly reset after each assertion and earlier than executing any subsequent assessments. Once more, unit testing frameworks usually don’t help clear resets between assessments.

One other facet is testing the assertion handler, which isn’t your common code as a result of it executes when the system is compromised. Subsequently, you could fastidiously take a look at the assertion handler beneath numerous fault circumstances, equivalent to stack overflow, interrupt preemption, and so on.

Finish Notes

As Bertrand Meyer remarked: “The usage of assertions will utterly change your strategy to software program building and, particularly, your view of errors” [2]. Certainly, working with software program programmed “offensively” (with assertions) feels utterly completely different than with software program programmed “defensively.” While you attain a enough density of assertions [6], the software program stops producing undesired conduct, denial of service, or random crashes. All bugs manifest themselves as assertion failures. This impact is really superb. The integrity checks embodied in assertions stop the code from “wandering round.” Even {hardware} failures and damaged builds don’t crash and burn however find yourself within the assertion handler.

As soon as an assertion fires, dismissing the issue as an intermittent “glitch” is way tougher, so all errors require consideration. You even have a file within the type of the distinctive assertion-id to begin your investigations. This makes most bugs extra clear. In distinction, testing defensively programmed code is inconclusive. You may run assessments for days and nights, however you may by no means make sure if the runs have been actually profitable or if this system silently produced rubbish all night time lengthy.

Nonetheless, assertions, particularly the query of leaving them within the closing launch, stay controversial in embedded programming. Some authors of safety-critical software program sidestep the controversy by implementing the required self-checks as verbose if statements (e.g., if (…) Perform_Safe_Shutdown()) [7]. Nonetheless, this manner of representing the de facto assertions isn’t idiomatic and misses most of the advantages of the DBC approach.

In my expertise, any controversy round assertions is finally rooted within the confusion between error and distinctive circumstances, which I defined within the earlier episode.

[1] Quantum Leaps, Design By Contract (DBC) for Embedded C and C++, GitHub, 2024

[2] Bertrand Meyer, “Object-Oriented Software program Building, 2nd. Ed.” Pearson School Div. 2000, ISBN 978-0136291558

[3] Dr. William Goble, “IEC 61508 – Two Key Elementary Ideas,” Exida, 2023

[4] Miro Samek, “Are We Capturing Ourselves within the Foot with Stack Overflow?” Embedded Gurus, 2014

[5] IEC, “IEC 61508 Half 7: Overview of methods and measures, C 3.3.3 Failure Assertion Programming,” IEC 61508-7:2010

[6] Gerard J. Holzmann, “The Energy of 10: Guidelines for Growing Security-Vital Code,” Laptop, June 2006

[7] Michael J. Pont, “The Engineering of Dependable Embedded Techniques, 2nd. Ed.”, Safetty Techniques Ltd, 2017, ISBN 978-0993035531

Dr. Miro M. Samek is the creator of the open supply QP real-time embedded frameworks and the freeware QM graphical model-based design instrument. He’s additionally the founder and CEO of Quantum Leaps — the supplier of recent embedded software program based mostly on lively objects and hierarchical state machines in addition to instruments for visible modeling, computerized code era, and unit testing of deeply embedded software program. Miro teaches the favored YouTube “Fashionable Embedded Techniques Programming” video course on which this text sequence is predicated.

Associated Contents:

Proceed Studying

[ad_2]

Supply hyperlink

Redmi Pad Professional debuts with 12.1” IPS LCD and SD 7s Gen 2

Apple Watch Sequence 9 Drops to New Low Worth of $295 on Amazon