Firmware quality

jonr

Well-known member
Say you (or a customer) want assurances of better quality embedded code. What can be done other than "be careful" and "lots of unit testing"?

Follow most of the MISRA standard? Do something like this to measure code coverage during testing?

https://mcuoneclipse.com/2014/12/26/code-coverage-for-embedded-target-with-eclipse-gcc-and-gcov/

The above modifies the code produced - I can imagine alternatives involving the automated use of a debugger.

Much of quality is "I know it when I see it", but that doesn't satisfy a customer looking for something more specific.
 
The most rigorous standards I know of typically require at least two separate coding teams, one writing the code and the other independently reviewing it against the requirements.

You can also set requirements like "No dynamic memory allocation" and check code size against available memory.

Unit and systems level testing, ensuring full-coverage of the paths.
 
> "No dynamic memory allocation"

Having just found a bug similar to below, is there a way to prevent this? Say a gcc option that warns if there is ANY use of the address of a stack variable? I suppose there is "switch to Rust".

Code:
int *p;

void foo()
{
        int i[5];
        p = i;
        return;     // bug!  i will no longer exist - was supposed to be "static int i[5];"
}
 
Lint is a good idea. gcc -fsanitize=address also works well on the PC (at execution time) - not clear what would happen with the teensy.
 
> "No dynamic memory allocation"

Having just found a bug similar to below, is there a way to prevent this? Say a gcc option that warns if there is ANY use of the address of a stack variable? I suppose there is "switch to Rust".

Code:
int *p;

void foo()
{
        int i[5];
        p = i;
        return;     // bug!  i will no longer exist - was supposed to be "static int i[5];"
}

Note, I haven't tried either of these, but there's a couple options that I see on Stack Overflow:
1. Remove the _sbrk() function:
https://stackoverflow.com/questions/55175265/disable-dynamic-memory-allocation
2. Use --wrap to have malloc call a different function and leave it undefined:
https://stackoverflow.com/questions/40130374/gcc-how-to-disable-heap-usage-entirely-on-an-mcu

They both take the same approach, resulting in malloc / new being undefined and throwing an error if used.
 
So, I just tried clang-tidy on your code snippet and it does produce a warning that the code will result in a dangling reference.
 
I tried splint (like lint) on a complete teensy program and it had one parsing problem after another. Might take considerable work to make teensyduino code splint compatible.

So I'm not aware of a practical solution for catching such errors (in a typical teensy program).
 
Last edited:
Leaving the INO empty and coding into a .cpp file in the folder and completing the needed includes and prototypes might present a valid usable source file, where the IDE build preprocesses that in behind the scenes from what is not an otherwise valid .cpp source file.
 
Last edited:
Some things that do work in the teensy environment to improve code quality and/or testing.

Use gcc with "-fstack-protector-all" and add this to your code:

Code:
extern "C" {
unsigned long __stack_chk_guard = 0xBAAAAAAD;//provide some magic numbers
void __stack_chk_fail(void) { for(;;) {} };
}

Install gcc 10+ (not hard) and compile with "-fanalyzer".

Compile with "-pedantic".

I haven't worked on coverage (gcov), but this is important to verifying that code is correct.
 
Back
Top