Language Compliance
Do not stray outside the language definition.
Compile with all warnings enabled; use static source code analyzers.
Predictable Execution
Use verifiable loop bounds for all loops meant to be terminating.
Do not use direct or indirect recursion.
Do not use dynamic memory allocation after task initialization.
* Use IPC messages for task communication.
Do not use task delays for task synchronization.
* Explicitly transfer write-permission (ownership) for shared data objects.
Place restrictions on the use of semaphores and locks.
Use memory protection, safety margins, barrier patterns.
Do not use goto, setjmp or longjmp.
Do not use selective value assignments to elements of an enum list.
Defensive Coding
Declare data objects at smallest possible level of scope.
Check the return value of non-void functions, or explicitly cast to (void).
Check the validity of values passed to functions.
Use static and dynamic assertions as sanity checks.
* Use U32, I16, etc instead of predefined C data types such as int, short, etc.
Make the order of evaluation in compound expressions explicit.
Do not use expressions with side effects.
Code Clarity
Make only very limited use of the C pre-processor.
Do not define macros within a function or a block.
Do not undefine or redefine macros.
Place #else, #elif, and #endif in the same file as the matching #if or #ifdef.
* Place no more than one statement or declaration per line of text.
* Use short functions with a limited number of parameters.
* Use no more than two levels of indirection per declaration.
* Use no more than two levels of dereferencing per object reference.
* Do not hide dereference operations inside macros or typedefs.
* Do not use non-constant function pointers.
Do not cast function pointers into other types.
Do not place code or declarations before an #include directive.