It’s often helpful to divide the “debugging” task into a non-real time constrained code and real time timing code. For example, a simple type-ahead typewriter application has a real time component that is “soft” in nature. The application continues to function, within reason, regardless of how fast a single key press is processed. The real time component can become more stringent, dropping the soft aspect, making the debugging process more complex because external factors control the software functioning based on time.
Debugging embedded software is a well supported activity with a wide range of tools available to perform the tasks. The tools for debugging include:
- Processor Probes
- In Circuit Emulators,
- Instruction Set Simulators,
- ROM Monitors
- integrated debugging capability with Real Time Operating Systems (RTOS)
- in-house custom systems
Of these tools, many industry standard tools based on probes and ROM monitors have similar capabilities. These include at least forming simple hardware breakpoints, instruction tracing, complex compound conditions for breakpoints, turning on and off instruction or data traces, and nested conditionals for all types of instruction and data conditions.
When designed properly, programmers can use either an instruction set simulator based debugging tool or an actual hardware development system with no loss in general purpose debugging capabilities excluding external hardware functionality.
Let’s look at the basic debugging capabilities needed to successfully complete a software debugging activity using the debugging tool recommendation from the Nexus Forum™, an industry standards setting body. Basic control features of any embedded debugger include the ability to:
query and modify all locations available in the processor’s supervisor map. For simplicity of implementation, this is often restricted to when the processor is halted.
support breakpoint/watchpoint features in the debuggers. These are available as either hardware or software breakpoints with software breakpoints used for ultra-low cost development environments. Some processors may favor one or the other approach depending on the architecture. Because of its simplicity of implementation, configuration of breakpoint/watchpoint features is often performed when the processor is halted.
Logic analysis requires basic facilities to:
- read instruction trace information with acceptable impact to the system under development. For low cost development kits access to instruction trace data is often performed by halting execution of the application program. This system succeeds in permitting developers to interrogate and correlate instruction flow to real-world interactions.
- retrieve information on how data flows through the system with acceptable impact to application under development. Central to this capability is understanding what system resources are creating and accessing data.
- assess whether the embedded software meets required performance goals.
Debugging can be carried out using the most rudimentary facilities, but at the cost of time and perhaps the need to build special hardware to add control or reporting. The decision of what tools you need is highly dependent on the size of code and the type of application that you are developing. An embedded application that fits into 2kW of program memory has different requirements than an application of tens of thousands of lines of code or more. Regardless of the application type, there is valuable information that can be obtained by any of the debugging facilities, no matter how basic.
Many processors lack full tracing facilities due to the high bandwidth requirements of the data unloading and the large number of I/O pins required to allow full access to address ad data busses for all internal busses. For example, Intel Architecture for embedded applications has no dedicated trace port – which reduces the pin count. The architecture supports the essential tracing capabilities for branch tracing. There is a branch trace recording buffer, and a means of emitting branch trace messages in line with write data.
Using the debug facilities described so far we can gather valuable information that allows us to find and fix several important classes of errors. For strongly typed languages with linguistic redundancy for type declarations, many difficult to find bugs are eliminated by the language construction. For most common bugs the simple tools described are adequate to find and fix most errors. Commercial debug tools include facilities that make test and evaluation straight forward.
Green Hills Software’s(1) processor probes for the Intel Architecture are provided by the Green Hills probe with high-performance debugging.
Wind River Systems (2) also provides a full suite of debug tools. The Wind River Probe is a portable JTAG-based probe. The Probe integrates Wind River Workbench On-Chip Debugging and the Wind River On-Chip Debugging API to provide a flexible debugging platform.
While these debug (probe) capabilities are adequate for debugging small programs of up to a few thousand lines of code, modern or more complex applications software requires additional capabilities. More importantly, there is a class of bugs that are pathological based on language structures. These include errors associated with type coercion, type casting, and array boundary checking. Bounds checking as an extremely expensive process often requiring twice or more resources than the array calculation itself. Due to the relatively expensive bounds check, it is a frequently overlooked means to improve software reliability. Instead the vast majority of applications rely on test methodologies to avoid this type of error. These errors are most often a dynamic fault which may change its behavior based on the size of the code space.
Where many control flow and logical errors that can be diagnosed using the simple probes described above, this class of error is best discovered through instrumentation of the software. Instrumentation through software combined with some hardware capabilities to find:
These dynamically oriented tools are supplemented by static analysis tools. But perhaps the most often overlooked debug tool provides programmers with program structure, hierarchy, dependency graphs and other related tools that aid programmers in understanding the intended function when original programmers are no longer available.
Software tools offer a wide range of capabilities for system test, diagnosis and verification. The tool choice, complexity, and cost depend on the complexity of that application, and the size of the organization. Perhaps no factor plays a bigger role than the processor architecture. For Intel embedded processors there are a number of commercial tool chains available, including offerings from Green Hills Software and Wind River Systems together with Intel’s tool kit.
What choice will you make?
Roving Reporter (Intel Contractor)
Intel(r) Embedded Alliance