How to introduce or port my microcontroller project to MISRA C?
MISRA C has become a de facto standard for all embedded systems firmware, no matter if it is safety-related or not. C comes with a lot of freedom, which makes it powerful yet dangerous. MISRA C is a safe subset of the C language, acting as a filter to block poorly-defined or otherwise dangerous parts of C from making it to production code. The advantage of C being such an old language by now, is that all problems with it are well-known and documented.
MISRA C compliance is an increasingly common requirement, particularly for microcontroller libraries. Even if it is not a requirement, MISRA C is a quality tool to get rid of bugs. Did you ever reason as "it would sure be nice if we have plenty of bugs in our programs"? :) Probably not, but rather the opposite! Then MISRA is something of interest for you.
The prerequisites are roughly:
-
You (or your organization) have some manner coding standard for how to write C programs, or you are willing to introduce one through documentation. A coding standard is after all a pretty much mandatory means to increase software quality in any professional setting.
-
You have access to at least one veteran C programmer with extensive knowledge of the language. This is needed both for the MISRA C implementation, as well as offering guidance during daily use and code reviews.
-
Probably a bit of a tool budget, since most MISRA C static analyzer tools ("MISRA checkers"/"linters") are still commercial at this point. The state of the various open source projects is uncertain and I have no experience of using any such open source tool.
Which version to use?
There are a number of different versions: MISRA C 1998, 2004, 2012 and 2023. For new projects you should always use the latest version. All versions from 1998 to 2012 are major revisions, non-compatible and very different. They all support the ISO C90 version of the language only, until 2012 when C99 support was added. MISRA C:2012 can still be said to be the latest one and the one you should aim for.
The 2023 version is just a consolidated version of MISRA C:2012 + Amendments 1,2,3,4 and Technical Corrigendum 1 and 2. So MISRA C:2012 and 2023 can be said to be identical. The amendments 2, 3 and 4 covered C11 and C18 compliance.
So you can either get the MISRA C:2023 document with everything in one place (convenient and highly recommended) or you can get the MISRA C:2012 version and download the various amendments and TC from https://misra.org.uk/publications/. The main 2012/2023 document is not free, but very affordable compared to ISO standards - basically you are just paying an administration fee.
Notably the MISRA C:2023 has nothing to do with the yet to be released ISO C23.
There also exists a MISRA C++, but this post will refrain from addressing that one here even though it works similarly. As a long term user of C++, I cannot recommend that language for embedded systems, but that's another story.
I should however mention that there is another safe subset CERT C, also a quite good one, but mainly aimed towards system/desktop programming, whereas MISRA C is more suitable for embedded systems. CERT C originates from research at the Carnegie Mellon University, whereas MISRA C was originally developed by the automotive industry.
How does it work?
Notably, The MISRA document is a guideline, so strictly speaking most of the contents are optional and can be addressed as suitable for the needs of your project or organization. Hence the need for the mentioned C programming veteran, to make an informed choice of which parts to implement and which to deviate from.
A common mistake by large organizations in particular is to enforce all of MISRA C to the letter, which could actually be dangerous if the individual developers don't understand the reasoning behind a certain rule and start to modify perfectly fine code, thereby making it less readable and possibly unsafe as well.
The document consists of a long list of guidelines, divided into Directives and Rules. Directives are big picture issues that you cannot easily cover by plain peer/tool review. These need to be integrated in the design and software development routines. Rules are more straight-forward requirements that are easier to check during code review alone.
All Directives and Rules have a classification: Mandatory, Required or Advisory.
- Mandatory Directives/Rules may not be deviated from. You must follow them or you cannot claim MISRA compliance.
- Required Directives/Rules are highly recommended to follow. You are allowed to deviate from them, but in case you do so, it must be done through a formal deviation process which you must document in your coding standard.
- Advisory Rules are optional. Often they make a lot of sense, but a couple of them are mostly there for informative purposes. You can deviate from them without formal deviation, but it's still recommended to document which ones you follow or not.
(For example there's an Advisory rule about not casting from an absolute address to a pointer, although I have yet to encounter a single embedded system project which needn't do this somewhere. The main rationale for the rule is to ensure that you don't cast a misaligned address. "Aha, that's a good thing to know about indeed MISRA, but I'm making a hardware peripheral register map here, so I'm going to ignore the rule.")
Please note that the MISRA guidelines is a very technical and hands-on document, and the average C programmer may not understand all of it. But that also means that it can be an eye-opener and quite excellent learning material. Did you know of technical things such as "order of evaluation", "implicit type promotion", "type punning", "strict pointer aliasing" etc etc before? If not, now might be an excellent time to learn and start to progress from intermediately skilled towards expert.
But in the meantime, there's probably the need for the mentioned C veteran to explain the rationale behind certain guidelines. Most of the guidelines have very sound rationales behind them. And a few of them actually don't. Making an informed choice to deviate from some guidelines is perfectly fine.
For example you'll most likely want a bunch of deviations for stuff like asm
or interrupt
keywords, various compiler-specific pragmas and so on. These are OK to use, just document what they do and how they work (as per the requirements from the first Directive).
Claiming compliance
There is (probably?) no third party verification available for claiming compliance, other than as part of safety verification through big picture "SIL" standards like IEC 61508 or ISO 26262. So it is mostly up to each organization to self-certify by claiming compliance.
First of all you need to set a quality level scope: do you require all code present in the project to be MISRA compilant, including standard libraries and tool vendor code, such as drivers and CRT? For safety-/mission-critical applications, you most likely will. For non-critical applications, it might suffice that only your own application code is MISRA compliant.
You claim compliance in your coding standard document, by implementing a compliance matrix. Basically a table where you need to cover each Directive or Rule in the document and demonstrate how you cover that rule, or otherwise point to the documentation showing how and why you deviate from it. With this method, you'll cover all Required and Advisory rules in the same manner.
For example, a certain rule could be covered by compiler diagnostic messages, and/or peer code review and/or static analysis with a MISRA checker tool. ("Rule 10.10 is covered by C compiler x, warning #1234".)
I strongly recommend not to allow deviations on an individual project or developer basis; not even Advisory ones. All deviations should instead be documented in the coding standard for your organization, making them apply to everyone. Like any decent requirements document, this should preferably be a live document. So that in case an individual developer finds a need to formally deviate from a Required/Advisory rule, it should be brought up for discussion and an organization-wide deviation can be documented (ideally with broad consensus).
Tools need to be configured to ignore deviated rules and everyone should use the same configuration.
It is also possible to add company-specific rules not related to MISRA in the same document. For example, MISRA C is explicitly not a style guide, but you really ought to have one of those and it can be integrated in the same document. Perhaps you are already using a "beautifier" such as GNU Indent etc with company rules and a configuration of its own.
You can integrate the deviation procedure with the quality system such as ISO 9001, if there's already routines for technical improvements within the organization.
Tools
You need a C compiler, obviously. And you need to figure out at what extent it can be configured to catch bugs and poorly-defined behavior. Some hints for gcc-like compilers can be found here: What compiler options are recommended for beginners learning C?
For example, many programmers are surprised to learn that gcc is very far from a conforming C compiler per default. Now the very first MISRA rule states that we may have no violations of the C standard's constraints or syntax, so in case we are using gcc, it needs to be brought in line - we have to smack some sense into it with options like -std=c11 -pedantic-errors
. Similarly, all GNU non-standard extensions is something that you will most likely want to outlaw in a MISRA project.
Additionally, tools like gcc and clang-tidy support various nice features these days, such as -fsanitize
or code coverage options. See for example the gcc manual 3.12 Program Instrumentation Options for some hints of how to use modern options to spot bugs.
A "MISRA checker" static analysis tool is also pretty much required, to focus on the specific rules that the compiler won't look for. There is a whole bunch of them, there's a decent list of them at Wikipedia: List of tools for static code analysis, which also mention which tools that have MISRA support as an option. Do pay attention to which version they use though! A lot of tools with "MISRA support" could still be using the 2004 version.
Check that the tool is using the 2012/2023 version. Check that it is regularly updated. Check how they deal with MISRA bugs - do you need to sign up for on-going support to get your hands of those?
Sadly, the state of MISRA checker quality on the market remains mediocre, to put it mildly. There is no obvious relation between the price you pay and the quality of the tool either - I have used some of the supposed state of the art ones and were almost as disappointed with those as with the notoriously bad but far cheaper ones (coughPCLintcough).
Therefore your compliance matrix also needs to take this in account: in case a tool fails to give accurate warnings for certain rules, or in case it spews false positives, you will need to adjust your routines accordingly, blocking rules that are broken by the program and finding other ways to check for those.
Again, it is very important that everyone uses the same tool configurations both for the C compiler and the static analyzer!
Further tools are not required for MISRA compliance but are highly recommended/mandatory still, in a professional embedded systems context: IDE, formatting tools, in-circuit debugger, multi-meter, oscilloscope, version control system.
Resources
- https://misra.org.uk/shop/ is where you get your legal copy of MISRA C. You might be able to order hardcopies even, if that's your thing.
- The official MISRA site also has some old-school discussion forums for free support. I haven't used them in ages personally, but overall these are reasonably active and you may be able to get formal statements from the committee to use in your documentation even.
- Some MISRA Committee members and other experts tend to hang out at the MISRA tag at Stack Overflow (as well as yours sincerely, although I'm not affiliated with MISRA) to offer informal advise and support.
- There's a MISRA-C & C++ group on Linked-In which engineers can apply for an invitation to.
0 comment threads