Hardware Design Ramblings

Reset Behaviour Rules

 * If the user wishes to reset the device and holds the Reset button down, all components should immediately reset and remain in the reset state. All signals should go to a defined level. You don't want your device to become an uncontrolled source of electromagnetic interference (EMI) during reset, so there should be no wires left in a high impedance state (also known as hi-Z, tri-stated, or floating). Your device should not do weird things like amplify noise during reset (high impedance lines can act like antennas). In practice, this means adding pull-up or pull-down resistors to all lines. You cannot assume that the user will hold the Reset button for a very short time. The software may also need to temporarily reset parts of the system (see further below), and having random signal values may occasionaly trigger subtle bugs on reset, which tend to be hard to reproduce. Besides, having a defined reset state may help testers if they need to keep some subsytems under reset for specific test cases. This system-wide reset signal should also be routed to the SRST pin on the JTAG debug interface. This way, the device will always behave the same during start-up, no matter where the reset comes from, which will simplify the software and reduce the scope for initialisation bugs.


 * When the user releases the Reset button, the main CPU alone should come out of reset. Only those components that are truly necessary for the CPU to start should come out of reset at this point in time. All other components should remain in the reset state. This rule is normally easy to implement, because most CPUs revert their I/O pins to floating inputs when under reset. If you connect all of your component's reset lines to the CPU, and add a pull-down (or sometimes a pull-up) resistor to those lines, all components will automatically stay in reset until the CPU starts and configures the related I/O pins as outputs.


 * The software that runs on the main CPU should then bring all other components out of the reset state, step by step. This way, the software has full control over the hardware initialisation order. If a random racing condition is discovered later on, the software can be modified to avoid the problem. For example, sometimes changing a power regulator can alter the order in which the different voltages required (3.3V, 5V, etc.) become stable on the board, so the firmware may need to introduce (or increase) a start-up delay for a particular subsystem.


 * The software should be able to reset any single component at any point in time. It is not uncommon to design a device, ship thousands of units to customers all over the world, and then realise that some component has a hardware bug that makes it hang under certain conditions. Such hardware bugs are often listed in the corresponding errata sheet. The trouble is, some bugs are discovered months or even years later after a component is shipped, and some manufactures seem to hide their bugs by moving errata sheets to separate, hard-to-find documents. You may come across a component that works reliably if the input data makes sense and then occasionally freezes if connected to a noisy line that yields random input data every now and then. Or maybe your design proves to be incorrect and does not always meet some component's electrical requirements, making it hang every now and then. If the CPU can reset any single component, chances are that you can implement a software watchdog in order to alleviate the problem. The end user is never going to like coming across a short, random glicht in one of the device functions, but if the affected function is then quickly restored with a controlled, local reset, the glitch may be tolerable. It is hard to predict which component will fail and how many will need to be reset (and in what order) in order to restore the affected function, so do not skimp on reset lines. If you can only reset a group at a time, or just the whole device at once, chances are that a small, trivial glitch may render your device unusable for the customer.

General Hardware Design Checklist

 * Add comments to your circuit diagram about local voltage or power requirements, or about the reasons behind non-obvious design decisions. It is interesting to see the same people who frown upon uncommented C source code create huge hardware designs without a single comment label. I have seen many times hardware subsystems copied around carrying old ballast that nobody wants to remove for fear that some electrical requirement might not be properly fulfilled. Those original requirements are often no longer known, and then speculations abound. I have come across many cases where some of the old components were just unnecessary, and sometimes even counterproductive, in the new system.


 * Add convenient ground pins for measurements. Most oscilloscopes have a standard alligator clip for ground purposes when testing low-speed signals, but the clip cable is usually too short. If the board under test has evenly-distributed, easily-accessible ground points, you will waste less time and get better results when checking the board.


 * Add test points for all signals. There is nothing more frustrating than not being able to reach a problematic signal with your oscilloscope probe. If there is no protective lack on the board, sometimes resistors can act as test points, but you cannot easily solder pins on the small ones so as to attach an oscilloscope probe clip. Therefore, implement the test points as connector pins or test pads.
 * Place ground points next to high-speed lines so that you can use short ground springs or ground clips attached to your oscilloscope probes in order to minimise ground loops.
 * Label at least the most popular test points. Power supply lines (3V3, 5V) are among the most-tested signals.
 * Place the test points on the board's top side. Otherwise, opening the device lid may not be enough, and you may have to disassemble the whole device in order to reach some of the test points.


 * Add a few test points that are just connected to spare CPU GPIOs. Sometimes, you will want to toggle those signals for test purposes, in order to drive special test hardware or to act as oscilloscope triggers that start capturing other signals.


 * Provide one or two extra GPIOs, just in case.
 * Later on you will often need an extra signal that nobody thought of in the design phase. Examples are some local trigger for some action, because the customer has no PC or HMI interface at hand to trigger it over the normal interface, or some unforeseen synchronisation signal, so that many of your boards/devices can coordinate their actions.


 * Consider adding a temperature sensor. Heat is a common cause of failure at the customer's site. Without early warning, you will have no idea why the board suddenly failed without any apparent reason.


 * Add a software-controlled heartbeat LED. During manufacturing, you will know at a glance if the firmware has been correctly programmed. During development and hardware troubleshotting, you will be able to tell at a glance if the CPU and its firmware are running, which will quickly narrow the search for hardware problems.


 * Add a serial port for a software debug console. Without it, software development and troubleshooting will be considerably harder.


 * Provide a jumper or button to clear the configuration in persistent memory, or at least to skip parsing it. Such a button is usually called "Reset to factory settings" in the user documentation.
 * Most boards have some sort of persistent memory for configuration information, like EEPROM, flash memory (built into the microcontroller, or on a separate SPI-Flash chip), or FRAM. The configuration may become corrupt for whatever reason. Maybe insufficient validation can lead to an invalid configuration that makes the firmware crash on start-up. In order to prevent bricking the device, the user must have a way to clear the configuration. Some memory chips have a physical way to erase them, like removing the CMOS battery. The firmware on other boards should check some 'clear config' jumper before trying to read and parse the persistent configuration.


 * Long clock signals should have a termination resistor in series next to the clock source (clock output).
 * For more information about signal termination, see this article (in German).


 * Place all capacitors oriented in the same direction.
 * Many capacitors are round and have a marking that indicate their orientation. If the contract manufacturer has made a mistake, it will be immediately obvious that not all markings are oriented the same.


 * Document which interfaces or power connectors are galvanically isolated.
 * Your colleagues and customers will need that information in order to avoid ground loops and constant current flows between boards or devices, when designing surge protection, or when planning large power supply networks.
 * For example, say you have 2 boards that operate at different voltage levels (3.3V and 5V), share a common ground (GND), and are connected with a serial interface that is not galvanically isolated. In this case, you should only connect Tx and Rx, but not GND on the serial interface. Otherwise, you would create a ground loop between the common GNDs (from the power supplies) and the serial interface's GND line.

Hardware Interface Checklist
By hardware interface I mean a pin header or an IDC connector where you attach another board or device.


 * Add a couple of unused lines. You never know what extra signals you will need in the future, or what the interface will be reused for. If possible, connect those signals to spare GPIOs on the CPU. Even if the pins are just connected to ground, a new board version may use more signals, and the same peripheral could be physically connected to both old and newer boards without hardware adapters.


 * Mark pin 1 on the board. Do not rely on any marking on the connector soldered on the board, because it could be swapped at any time for a cheaper connector without markings. Having the marking on the board also helps if you need to replace the connector itself. There are several ways to mark the pin 1:
 * Add a text label next to it (for example, the number '1'), or a small triangle or arrow pointing to it. If the board does not have a label layer, you can shape a copper track nearby on the first layer like text.
 * Make its soldering pad different. For example, if all pads are round, make the one for pin 1 square- or diamond-shaped.


 * Label the interface with its name. If the board does not have a label layer, you can shape a copper track nearby on the first layer like text.


 * Always provide ground and power lines. Your interface may only need data lines today, but you might attach a different device in the future which could draw its power over the same interface. Just think of SATA hard disks, where you need 2 cables, as opposed to USB disks, which just need one.


 * Add protection against reverse polarity. There is nothing easier than connecting a cable the wrong way around. Even if you carefully choose connectors that make such errors impossible, those connectors may get replaced later on during production if the original ones are not available or are just more expensive. Ideally, a connection should be reversible, that is, it should work both ways around. Next step down is that the system detects when the connection has been reversed, and may even alert the user accordingly. In any case, reversing the connection by mistake should not cause permanent hardware damage.


 * Place ground pins next to high-speed lines for measurement purposes. If you have a high-speed interface, like a fast-clocked SPI bus, you may have to inspect the signal with an oscilloscope in order to troubleshoot electrical disturbances. In order to reduce the impact of ground loops, you should attach short ground springs or ground clips to your oscilloscope probes, but then you will need easily-accessible ground pins near the signal under test.