By Craig MacKenzie | Oct 3, 2013
The best way to achieve high levels of system reliability in a complex, fast moving development cycle is to have a suite of automated tests continuously verifying your design. This article presents some tips and tricks for getting a solid automated embedded design testing flow up and running to keep development bug-free and moving quickly. The diagram below shows what a typical automated test setup looks like.
Unit Under Test Resource Limitations
Trying to fit test and diagnostic code into an embedded application can be challenging, especially in systems with tight memory constraints. The following techniques can be helpful when trying to overcome resource limitations:
- Don’t run tests on real hardware. Instead, implement a hardware abstraction layer, which permits use of a simulated embedded environment. This minimizes resource limitations and allows for better test instrumentation.
- Build the layers of your application as separate code libraries. The test and application code can then be built as separate firmware images to decouple their resource requirements while linking both against the same library code.
- Use (or build) a lightweight test framework to consolidate the test infrastructure on the unit under test (UUT). Several open source options exist. For example, we have successfully used the Unity test framework on small embedded targets in the past.
Hardware Interfacing
The next problem to tackle is how to drive the analog and digital inputs of the system from your host system. While the option of buying purpose-built test equipment exists, a few alternative options are listed below:
- Off-the-shelf USB adapters exist for many common low level interfaces. If the goal is simply to drive some GPIOs or a UART, FTDI provides several solutions. On the analog side, a USB sound card can serve as a cheap arbitrary waveform generator.
- Standard lab equipment typically provides several communications interfaces for remote instrument control. It is quite easy to control digital multimeters and function generators over USB, GPIB, or Ethernet. Most instruments implement the VISA API standard, further simplifying interfacing requirements.
- Rather than a custom PCB design, consider using an MCU evaluation kit with a suitable host communications interface to drive the inputs of the UUT first.
Test Automation
The final piece of the puzzle is managing and controlling tests on the UUT from the host system. Ensure that you’ve considered the following when building your test infrastructure:
- A communications channel between the host system and the UUT needs to be incorporated into your design to trigger events and read results. Ideally this should use a simple interface with minimal hardware and software dependencies, that isn’t a focus during testing.
- Often the best option for host-to-UUT communications is a simple command line interface implemented on a spare UART (or a login shell exposed over one on Linux). This has the advantage of being both easily automated and readable by humans for diagnostic purposes.
- Rather than building your host system test software from scratch, consider using one of the many open source testing frameworks. For example, the Robot Framework is an excellent test automation framework supporting either Java or Python.
Using the techniques above will help minimize time spent manually turning knobs on test equipment while ensuring a rock-solid tested product.