My 4 Rules For Firmware Development
Rosmianto Aji Saputro
Embedded Systems Consultant | Author | FREE Firmware Course ?? fw101.rosmianto.com
I try to compile as much as I can. These are my rules for firmware development over the past 6 years of professional experience and pet projects combined. Firmware development is usually done using C/C++, so my article will favor those languages.
Always Use Brackets Even for Single if
It's easy to fix syntax errors (e.g. missing semicolon or indentation error), but semantic errors are harder. Firmware compiled just fine but its behavior is incorrect. Junior developers tend to make such errors, and I always emphasize the effort to prevent it, because it will save costs in the long run.
One example is brackets usage for if. You know that in C/C++, we can omit brackets if there's only one statement following it, like this:
if (oneCondition == true) function1(); else function2();
The thing is when a junior is tasked to improve the firmware, I've witnessed too many cases that they tend to do something like this:
if (oneCondition == true) function1(); else function2(); new_features();
What would you expect? Yes, the code will compile seamlessly, but whether oneCondition is true or false, new_features() function will always be executed. Now check this:
if (oneCondition == true) { function1(); } else { function2(); new_features(); }
Puff, the bug's gone. You got the idea.
But yeah, what if I have lots of else if? Brackets will cost a lot of lines.
Oh you mean, you want something like this?
if (condition1 == true) function1(); else if (condition2 == true) function2(); else if (condition3 == true) function3(); else if (condition4 == true) function4();
In that case, just do this:
if (condition1 == true) { function1(); } else if (condition2 == true) { function2(); } else if (condition3 == true) { function3(); } else if (condition4 == true) { function4(); }
Use Version Control System like Git or SVN Whenever Possible
Remember when you all started making software and don't want to lose track of your work?
It's okay if it's only for your amusement, crude and dirty way will do just fine. But seriously, if you are developing software professionally, please use software that specifically designed to manage it: Version Control System.
Invest a little bit of your time to learn Git and SVN, and see which one is best for you. In my early career, I use SVN (and TortoiseSVN) to keep track of my work, then I switched to Git because it's distributed. I can clone from local repositories, commit, diff without the need to connect to central repo first. It fits my needs, so I have never looked back.
Always Divide Firmware Structure Based on Subsystems and Peripheral
This will promote better modularity and easier to conduct testing. Although it will make the project a little more complex, the high readability and ease to navigate will not slack further development.
Let's say we want to develop a new logging device that logs its orientation to SDCard and Flash Memory. Divide firmware like this:
Peripherals may be called as HAL in other platforms (like STM32 + Keil).
This way, our firmware has a high degree of modularity and testing it will be far easier than ever.
Delete Your Dead Code
Don't be hesitant to eliminate dead code, commented code. The software versioning system will track that for you.
Wait, isn't dead code == commented code?
Nope. Commented code is, well, code that is commented. Like this:
if (condition == true) { } else if (condition2 == true) { } // else if (condition3 == true) { // } else { }
You should delete it, especially when the code was commented months ago.
Dead code is code that's never be executed, like this:
if (true) { init(); func1(); func2(); func3(); } else { func4(); func5(); func6(); }
The statements inside the else will never be executed, and you should delete them as well. Well, the compiler may give you a warning about this. But yeah, better look for yourself, don't rely solely on the compiler.