This really is where good embedded programming skills come to bear, bringing up a new board or debugging an existing one. My first and best tool for the process pf debugging an embedded system is to read and understand the data sheets for the parts on the board. After confirming that the controller is functional, using a in-circuit programmer/debugger device, I start writing low-level functions, making sure that may understanding of the device is correct. I like to get the interrupts functional first, verifying that the critical processes are functioning correctly (ADC/Timers/UARTs, etc.). Once the data is being collected correctly, I like to work on the functionality or algorithmic process that using the data and drives the outputs.

As far as tools go, here are my favorites:

Volt meter - I like to start with verifying the power sections of the design. These need to be right or everything else is going to be effected.

Oscilloscope - This is my go to piece of equipment. This is where you really get to see if things are working. With most embedded devices all of the interesting things are happening inside the part, if there are little to no external devices, you will need some help to see anything going on here, so I use unused pins to toggle on internal events so I have something to look at while trying to monitor the functions of the device.

As an example of this technique, here is an example of measure processor loading during interrupt processing:

The lower (cyan) trace is connected to an LED driver that I re-assigned for this measurement. The signal is driven low upon entering the timer interrupt and returned high upon exiting. The 'low' time represents the processing time of the interrupt, while the 'high' time represents the time available to the background task. The upper (yellow) trace is a signal generated by the interrupt processing. This signal is a channel select line that addresses one of the four MUX channels. This signal is switched to the next channel every fourth interrupt. Using this technique, I was able to optimize each phase and balance the load between the different phases of the interrupt processes.



In-circuit programmer/debugger - Being able to change and load code is fundamental to the the debugging process. Having a good tool to modify code, read/modify EEPROM and check registers is very important. Also a good debugger is helpful to set break-points, allowing you to trace the functioning of the code is helpful.

Logic analyzer - Tracing multiple digital waveform is easy with a logic analyzer. Very useful for viewing communications to/from the microprocessor to external devices. Complex triggering allow you to zoom in and find the information you need when there is a lot of data present.

Signal generator and extra power supplies - With embedded systems that have external sensors and devices, being able to simulate the signals in a controlled manner is a good way to verify functionality and to test limits of the sensor ranges.

Soldering tools and microscope - When things don't go right and problems are found, being able to fix them is important. I find that being able to repair/replace/modify the board is very helpful.

As far as best practices, I like to always try to reuse as much code as possible. When designing a new board/product, I like to attempt to use the same microprocessor as in prior designs. By being able to leverage an existing project as a starting place on a new project, I find that I can hit the road running. After doing a little (or in some cases a lot) of reworking the code to match the current project's desired functionality, I can truly focus on the changes and new code and assume that the untouched code if mostly functional.

I hope that this helps.

