Writing code for uncompleted hardware is so hard : (
General process of embedded software development is as follows:
- Developing software on own computer
- Debugging on an evaluation board
- Testing on a target hardware
Most of engineers that I have met try to debugging on an evaluation board as quickly as possible, so they tend not to care about testability for unit test. As a result, we get high coupling code.
At the time, we have to advance the development with several risks as follows:
- Own computer, evaluation board and target hardware have a little bit different library and compiler.
- The evaluation board is bad in quality at the beginning of the development.
- There are many mistakes in logic of code
- Software engineer has to resolve underlying discrepancy in specification at the end of development.
If we do agile software development for embedded software system, this will be a bottleneck.
For this problem, the author of "Test Driven Development for Embedded C (Pragmatic Programmers)" recommend hardware-independent software design and unit test on both of own computer and evaluation board from the beginning. This is called "Dual-Target Testing". If we do it from the beginning, we can eliminate bugs and make test easier.
What do we need for Dual-Target Tesing
At first, we need software design techniques to make software more testable. That is discussed in the books like "Test Driven Development: By Example" written by Kent-Beck or "Working Effectively with Legacy Code" written by Michael Feathers.
Second, we need cooperation with hardware engineers for low layer software development. For example, in the book of "Test-Driven Development for Embedded C ", there is a scene that software engineer and hardware engineer are discussing about design of interface between software and hardware so that software engineer can decide design of Test Double.
What "Test-Driven Development for Embedded C" is doing for this?
There are some code examples in my github. There is product code and test code for LED driver.
Key point of this example is a dependency injection at a constructor. Passing writing port address to constructor makes software independent with hardware. We can do unit test on both of own computer and the evaluation board.
This driver has writing port only. State of LED driver is stored at variable ledsImage once, then write to the port. This was an issue that software engineer and hardware engineer discussed in the book.
You might think that this example is quite simple and there are more difficult examples in real world. I think basic idea is the same as this example, which is interface design between software and hardware and low coupling software design against hardware and other software modules.
I will held the third monthly meeting of "Test Driven Development for Embedded C" book club in Tokyo and see this problem deeply : )