(this article is not just for embedded developers)
A few months back I was reading Doug Schmidt’s blog, on The Growing Importance of Sustaining Software for the DoD, and he made the claim
“although software does not wear out, firmware and hardware become obsolete, thereby requiring software modifications”.
It was a bit of a clarifying moment for me. Doug clarified two terms that I suppose were obvious, or maybe not. Software is this thing that can have a long useful life, where firmware is going to be regularly be made obsolete as hardware evolves.
I’d like to add to Doug’s statement:
although software does not wear out, it can be destroyed from within by unmanaged dependencies on firmware and hardware.
Think of all the code denied the potential long life of software due to being infected with dependencies on hardware.
By firmware I don’t mean just the code lives in ROM, as the definitions I found suggest. It’s not firmware because of where it is stored, it is firmware because of what it depends upon and how hard it is to change as hardware evolves, and hardware does evolve (pause and look at your for phone for evidence).
I have nothing against firmware, or firmware engineers (I’ve been known to write some firmware myself). But what we really need is less firmware and more software. Actually, I am disappointed that firmware engineers write so much firmware!
By the way non-embedded engineers, you essentially write firmware too whenever you bury SQL in your code or when you spread platform dependencies throughout your code. Android and iPhone app developers do it when they don’t separate everything they should from dependency on those platforms.
I’ve been involved in a lot of efforts where the line between the product code (the software) and the code that interacts with the product’s hardware (the firmware) is pretty fuzzy at best, fuzzy to the point of non-existence. For example, in the late 90’s I had the fun of helping to redesign a communications system that was transitioning from time-division multiplexing (TDM) to voice over IP (VOIP). VOIP is how things are done now, TDM was state of the art in the 80’s and 90’s. Whenever we had a question for the systems engineer about how a call should react to a given situation, he would disappear and a little later emerge with a very detailed answer. Where did he get the answer? From the worn out legacy code. The existing implementation had no separation between TDM and the business logic of making calls. The whole product was hardware/technology dependent from top to bottom and could not be untangled.
Take another example, of a brand new message processor/dispatcher that resides in the same file as code that interacts with a UART. The message processor was polluted with UART details. It could have been software with a long useful life. Instead the brand new firmware would soon be obsolete. The message processor was denied the opportunity to become software! And that is just not right!
I’ve known and understood the need for separating software from hardware for a long time, but Doug’s words clarified how to use the terms software and firmware in relationship to each other.
So engineers and programmers, stop writing so much firmware and give your code a chance at a long useful life.
I write embedded firmware for a living. I find that my firmware is sometimes outdated by hardware changes. More often, it needs changing because of some new feature that someone has fallen in love with, and MUST have.
I think things might be changing. I’m relatively young and in my undergrad, while experimenting with different micros in the robotics club, one thing that I really worked on, then pushed as I took on more responsibility, is that the bulk of the code we write should be written once.
Since we favored micros that had (free) c compilers and since we needed to do the same thing on almost all our robots, PID loops, communication with a laptop or external computer, process GPS, ultrasonic sensors, etc, everytime we started on a new robot, we shouldn’t have to rewrite that same code. . . considering that it already existed in our language of choice.
I always saw a design that needed to tightly couple high level code with details about the embedded system as being flawed. And for those who say, “well, x micro doesn’t have hardware math, so we need to optimize that code”. The slight penalty in writing an integer only sin/cos function in C will be outweighed by your distrust the compiler’s ability to optimize your C code for your specific platform.
Slight? Embedded MCU’s with hardware FPU’s are still a rarity, and even those seldom have the FPU performance equivalent to desktop PC’s (that is nearly 1-to-1 with integer arithmetic). With most M-Series Cortex processors, floats are faster than doubles, and neither are anywhere near the performance of integers. With SW floating point, a multiply can take hundreds of clock cycles in floating point versus one with interger arithmetic. And seldom is the case where we can just “throw a bigger CPU at it”.
Even in the case of a maths library, the code can be factored out. For example, let’s say you’re working on your PID library, you have a number of high level methods and properties that define how to calculate the next iteration. Using Embedded C++, you can template away the dependency on doubles or floats, and with a little operator overloading, make a nice substitute fixed-point format that can take either’s place. That would give you something like:
Pid myPidLib = new Pid(); // fast MCU with HW FPU hopefully
Pid myPidLib = new Pid(); // not as fast, but need the precision
Pid myPidLib = new Pid(); // really fast, but not as precise
I would strongly urge that while ANSI-C has unit frameworks that work well enough, if you want to embrace TDD and have real separation of concerns, then you need to switch to Embedded C++.
@Steve, Part of the point of my article is that the embedded engineer has to be careful to separate firmware from software. HW changes lead to FW changes, feature requests should mostly involve SW, unless the HW/FW cannot support the feature. Then HW, FW and SW may need changing. Too much would be SW is turned into FW due to not separating platform concerns from application concerns.
@Renee, Are you asking if I am slighting embedded engineers? Not really, trying to increase awareness. Many embedded engineers do not know about separation of concerns. I believe this because I see a lot of embedded code where there is not separations.
I agree that C++ is superior at helping manage dependencies, though not using C++ is not an excuse not to. (I don’t think you are saying it is.) Concerns can be separated in C as well.
In your post above did you mean to templatize the three Pid() creations? I can edit and add them if you tell me about the missing code.