Making embedded system debug easier: useful hardware & software tips
Embedded systems are a blend of hardware and software. Each must complement the other. Hardware people can make the ﬁrmware easier to implement. So here are some suggestions to make both the system hardware, software and firmware easier to debug. Remember that a good design works; a great design is also one that’s easy to debug.
First up: diagnostics
In the nonembedded world, a favorite debugging trick is to seed print statements into the code. These tell the programmer whether the execution stream ever got to the point of the print. But ﬁrmware people rarely have this option.
So, add a handful of unassigned parallel I/O bits. The ﬁrmware people desperately need these as a cheap way to instrument their code. Seeding I/O instructions into the code that drives these outputs is a simple and fast way to see what the program is doing.
Developers can assert a bit when entering a routine or ISR, then drive it low when exiting. A scope or logic analyzer then immediately shows the code snippet’s execution time.
Another trick is to cycle an output bit high when the system is busy and low when idle. Connect a voltmeter to the pin, one of the old-fashioned units with an analog needle. The meter will integrate the binary pulse stream, so the displayed voltage will be proportional to system loading.
If space and costs permit, include an entire 8-bit register connected to a row of 0.1 inch spaced vias or headers. Software state machines can output their current “state” to this port. A logic analyzer captures the data and shows all the sequencing, with nearly zero impact on the code’s execution time.
At least one LED is needed to signal the developer—and perhaps even customers—that the system is alive and working. It’s a conﬁdence indicator driven by a low-priority task or idle loop, which shows the system is alive and not stuck somewhere in an inﬁnite loop. A lot of embedded systems have no user interface; a blinking LED can be a simple “system OK” indication.
Highly integrated CPUs now offer a lot of on-chip peripherals, sometimes more than we need in a particular system. If there’s an extra UART, connect the pins to an RS-232 level shifting chip (e.g., MAX232A or similar). There’s no need to actually load the chip onto the board except for prototyping.
The ﬁrmware developers may ﬁnd themselves in a corner where their tools just aren’t adequate and will then want to add a software monitor to the code. The RS-232 port makes this possible and easy.
If PCB real estate is so limited that there’s no room for the level shifter, then at least bring Tx, Rx, and ground to accessible vias so it’s possible to suspend a MAX232 on green wires above the circuit board.
( Attention, developers: if you do use this port, don’t be in such a panic to implement the monitor that you instead implement the RS-232 drivers with polled I/O. Take the time to create decent interrupt driven code. In our experience, polled I/O on a monitor leads to missed characters, an unreliable tool and massive frustration.)
Bring the reset line to a switch or jumper, so engineers can assert the signal independently of the normal power-up reset. Power-up problems can sometimes be isolated by connecting reset to a pulse generator, creating a repeatable scenario that’s easy to study with an oscilloscope.