Previous papers in this series have discussed the design of embedded system hardware such that it will be easier to understand and control by firmware engineers. This thought process is critical to the success of embedded systems in the future. As embedded system hardware becomes more and more complicated, the learning curve for firmware developers is increasing to the point where the delay to produce working firmware can kill a product.
While simplifying the interface for firmware control is critical, the ability to debug the system is also critical to the firmware development process. This paper, the final in this series, discusses design considerations that allow firmware to better monitor and control the hardware. While these ideas do help with firmware development, many become especially valuable during system bring-up and debug efforts.
The first chip-level design consideration should be the inclusion of firmware-readable version registers. If the embedded system includes several third party or independently supported hardware blocks, each of these should include a version register. There should be a chip-level version register in addition to these.
This allows firmware to synch up with different versions of the hardware without human intervention. The version number should change whenever a functionality change occurs after the initial release of the silicon. That being said, not all functionality changes are visible to the CPU. A change to the hardware logic that does not affect the firmware need not necessarily require a version change. However, it's always safer to increment the version register even when not needed.
If firmware is being developed in parallel with the hardware, there is really no need to increment the version registers early in the design. Once a milestone is reached where functional simulations are running, the organization may begin incrementing the revision registers to allow the tracking of the firmware development.
The remainder of this paper is divided into three sections: functional block control, debug considerations, and exception handling considerations.
1 Global control of functional blocks
Many functions in an embedded system require some type of enabling logic for correct operation. Others, during normal operation, do not. However, when debugging the system, the ability to disable any hardware block can be invaluable.
Adding an enable capability to every hardware block greatly increases the ability of firmware to isolate an operational problem. The firmware engineer can work with only part of the IC. and increase the ability to determine the source of a problem in the hardware. This can also be useful if a newly designed capability proves to be a bust in hardware; the firmware can turn off that capability or mimic it in code if needed until a fix is made available.
In addition to the disable capability, hardware functions should be designed with the ability to stop operation. This is not a reset, simply the capability to stop the function without disturbing the contents of internal registers. This, combined with the ability to read all internal storage elements, can greatly facilitate the understanding of unexpected behavior. This may be as simple as de-asserting the enable or the "GO" bit to the hardware block.
When a hardware operation is stopped, it does not always make sense to restart from the stopped state, especially if the hardware is dealing with real-time inputs or outputs. In these situations a "soft reset" capability is a great benefit to the system engineers. This stops the current operation and resets internal state machines to a state from which the hardware can restart. This is useful for debug purposes, but may also provide added exception handling capability during actual operation.
Table 1 Reset and stop capabilities
2 Elimination of careless mistakes
Often, in an embedded system, there are some key values that are used throughout the system. An example from my own experience is the sector size of a data stream.
The standard hardware design methodology calls for independent design of individual hardware blocks that are then assembled into a full system. These self-contained blocks will often contain duplicate information in separate registers.
This is not good design form! If some information is required by more than a single block, then only one block in the IC should contain a register for that data. The contents of that register should be provided as outputs from the parent hardware block in order to supply the value to other blocks in the system.
The alternative is that the firmware engineering team must intuitively recognize that two registers in separate logic blocks must contain the same value. This is difficult to do; the difficulty is compounded by the fact that the register may have different names in different blocks. Remember, different individuals may be designing the firmware for the two hardware blocks. The idea that the firmware designers should communicate and catch these problems is moot when they cannot be aware that the problem exists.
In this same vein, there are often several values that must be loaded to various registers that are related to each other. These types of registered values must be carefully thought out to avoid permitting the firmware to write conflicting values.
An example would be a data packet with an error correction code. Hardware must know the size of the packet, the size of the data portion, and the size of the ECC portion. Any two of these can be loaded by firmware without a problem, leaving hardware to calculate the remaining value. If all three values must be loaded by firmware then the system runs the risk of receiving conflicting values.
Figure 1 Implementing registers for data used in more than one block
3 Exception handling considerations
Exception handling is the biggest part of the firmware development effort for a number of reasons. First of all, the hardware is designed to work correctly with correct data, not necessarily to handle exceptions.
Secondly, the very nature of exceptions hints that whatever occurred was unexpected. Add to these the fact that exception handling is simply not often considered properly early in the hardware design process.
One of the biggest steps that can be made to improve the controllability and usability of a design is to discuss exception handling, very early, with firmware engineers. This type of communication can provide real error recovery capabilities in the system rather than default reset-and-retry runs.
Any interrupt that signals an error condition should be discussed. The hardware designer should understand and document exactly how the firmware engineer would plan to recover from each error condition. Note that "recovery" implies a fix-and-resume operation; simply halting the operation is not a full recovery.
The ability to flush a data channel (such as a FIFO or an ordered queue) in a single step is an excellent exception-recovery feature. A "Flush" function resets all counters and pointers and pretends that the channel has done nothing and is ready to start from scratch. If the flush function actually destroys the data in the memory blocks of the channel, this should be highlighted in the spec.
Note that any state that locks out the CPU from the system effectively eliminates the ability to fully debug the system with firmware. This is often done by disabling the CPU access to the system or by gating the clock to the CPU.
The most obvious issue with a locked-out CPU is the fact that, if an error occurs in this state, there is nothing the firmware can do to fix or work around the problem. A more insidious problem is the fact that it destroys any real-time response capabilities of the CPU. This severely limits the firmware's ability to handle exceptions and interrupts in the timely manner expected.
How does the hardware design handle the potential problem of a locked-out CPU? The only answer is "Don't do it!" This cannot be over-emphasized!
GPIO signals provide the firmware with off-chip access independent of any hardware modules. These can be used to trigger test and debug equipment, toggle LEDs, and measure interrupt latencies. The ability to configure these as sources into the interrupt register allows the system engineer to control the CPU from outside the IC.
In today's world of ultra-complex systems, embedded IC designers can no longer design to simply get a functionally correct system. The design process must take into consideration the users of the IC.
Firmware friendly considerations can cut the firmware development time by huge margins. A complex system designed without firmware considerations may never reach the market, as the system development and firmware effort may be delayed to the point where the market window is missed. Two competitive products may be differentiated only by their firmware friendliness, and that difference could spell the difference between the wildly successful product and the product that never gets past the prototyping stage.
Nearly as important as firmware friendliness is the inclusion of debug capabilities. Indeed, this could simply be considered a part of firmware friendly design. The ability to debug the IC in a system in an efficient manner can save significant time in prototyping. The ability to bypass and work around problems can mean early shipment of a product that would otherwise have been killed by the prohibitive time and expense to respin prototypes.
"First Time Success" is the mantra of every semiconductor company, but experience has shown that this goal is rarely achieved. I have worked with hardware groups that consider a product that ships on time, with firmware workarounds for broken hardware functions, a first-time success story. This is absolutely the correct attitude; the designers were intelligent enough to recognize the possibility that the design (logical or physical) may not be as perfect as supposed. They should be commended for their foresight and rewarded for their intelligent design work.
In much the same manner that GUI interfaces killed command line interfaces in the past two decades, firmware-friendly hardware has the capability to kill difficult-to-understand hardware in the next decade. The high cost of IC development continues to increase to the point where a single ASIC can cost millions just to develop first silicon.
The result of this is that companies are taking fewer chances with new products. This means that the success of companies becomes more dependent upon fewer products. An embedded system product that costs $10M to develop but fails to capture significant market share can lead to the failure of an entire company.
One can easily forecast the demise of IC products designed without firmware and debug considerations. The IC design teams who do not include these considerations in the design will eventually be out of work because they will, to put it simply, be out of customers.
Previous articles in this series
Tips for firmware-friendly register design
Making hardware modules firmware-friendly
Making storage elements firmware friendly
Making interrupt design firmware friendly
Firmware-friendly reset design
Making hardware specifications firmware-friendly
David Fechser is a senior staff engineer working for the Systems Verification group of the Storage Products Division at LSI Logic Corp.