This invention is related to energy-autonomous systems, for example, energy-harvesting systems, and, in particular, to the problem of debugging software and firmware that operates and controls these systems.
Energy-autonomous computing devices have the potential to extend the reach of computing to a scale beyond either wired or battery-powered systems. However, these devices pose a unique set of challenges to application developers who lack both hardware and software support tools. Energy harvesting devices experience power intermittence which cause the system to reset and power-cycle unpredictably, in some cases tens to hundreds of times per second. This can result in code execution errors that are not possible in continuously powered systems and that cannot be diagnosed with conventional debugging tools such as JTAG and/or oscilloscopes.
Energy-harvesting devices are embedded computing systems that eschew tethered power and batteries by harvesting energy from the environment. A power system collects energy into a storage element (i.e., a capacitor) until the buffered energy is sufficient to power the computing device. Once powered, the device can operate until its energy is depleted and power fails. After the failure, the cycle of charging begins again. These charge-discharge cycles power the system intermittently and, consequently, software that runs on an energy-harvesting device also executes intermittently. A power failure may interrupt an execution with a reboot at any point. A reboot clears volatile state, for example, data stored a register file or SRAM, and retains non-volatile state, for example, data stored in FRAM. When the system restarts, control is transferred to some earlier point in the program, for example, the start of the main routine.
Intermittence makes software difficult to write and un-derstand. A reboot can happen at any point in a program's code, and may occur tens or hundreds of times per second. Reboots complicate a program's possible behavior because reboots are implicit discontinuities in the program's control flow that are not expressed anywhere in the code. Even with checkpointing and versioning, reboots cause control flow unintuitively back to a previous point in the execution.
Intermittence can cause correct software to misbehave. Intermittence-induced jumps back to a prior point in execution inhibit forward progress and may cause repeated execution of code that should not be repeated. Intermittence can also leave memory in an inconsistent state that would not normally occur in a continuously powered execution. These failure modes represent a new class of intermittence bugs. To avoid intermittence-related malfunctions, code must correctly leverage non-volatile memory. Writing intermittence-safe code for an energy-harvesting application or runtime system requires the programmer to understand, find, and fix intermittence bugs.
To diagnose bugs in their code, programmers need to monitor system behavior, observe failures, and examine internal program state. Unfortunately, this simple debugging methodology is unusable for intermittence bugs in energy-harvesting devices because existing debugging tools power the target device, masking the intermittent behavior. As a result, programmers are left with an unsatisfying dilemma: to use a debugger to monitor the system and never observe a failure, or to run without a debugger and observe the failure but gain no insight into the system necessary for understanding the bug.
As an example, assume an energy-intermittent system that executes a C program that takes longer than a single charge-discharge execution cycle to complete. The device may have a mixture of volatile registers and memory, as well as some non-volatile memory. Further, assume a checkpointing mechanism that periodically collects a checkpoint of volatile execution context (i.e., register file and stack).
Power intermittence complicates understanding and debugging a system, because the behavior of an intermittent system is closely linked to its power supply. This link is illustrated in
Debugging intermittence bugs, like the example shown in
One approach to diagnosing an intermittence bug is to directly write debugging instrumentation code into an application to trace certain program events. In embedded systems, one popular ad hoc approach is to toggle an LED at a point of interest. LED-based tracing, however, does not work in energy-harvesting devices, because the energy required to power the LEDs changes the behavior of the system.
Another tracing strategy is to manually instrument code to log program events to non-volatile memory. The resulting trace, however, lacks information about the energy level, unless the developer also spends time, energy, and an ADC channel to log the DUT's energy state. Non-volatile tracing also consumes precious non-volatile storage space. To avoid consuming non-volatile storage space, a programmer may write code to stream the event log to a separate, always-on system (e.g., via UART). Powering and clocking an I/O peripheral to transfer the log is also time and energy expensive and adds considerable complexity to code.
All of the instrumentation-based approaches change the point in the program at which energy is exhausted. As a result, the act of debugging alters the intermittent behavior of the application. Furthermore, the value of tracing depends on the events which the programmer decides to trace. To understand the intermittence bug in
Energy-interference and lack of visibility into intermittent executions makes prior approaches to debugging inadequate for intermittence debugging. Therefore, it would be desirable to provide a means for debugging an energy-intermittent system that does not interfere with the power profile of the system.
Disclosed herein is an energy-interference-free debugger, a hardware and software platform for monitoring and debugging energy-intermittent systems without adversely affecting their energy state. The energy-interference-free debugger (EDB) re-creates a familiar debugging environment for energy-intermittent software and augments it with debugging primitives for effective diagnosis of intermittence bugs and addresses the current lack of basic debugging support for energy-intermittent systems.
The EDB is a complement of hardware and software for energy-interference-free monitoring and manipulation of intermittent devices. EDB can passively monitor a target device for its energy level, I/O events (e.g., I2C, RFID) and program events. Monitoring with EDB, unlike with conventional debuggers, is energy-interference-free, because it is designed to be electrically isolated from the target device. EDB also provides a capability to actively manipulate the amount of energy stored on the device. Using this mechanism, EDB can compensate for the energy consumed by arbitrarily expensive tasks, effectively eliminating their impact on the energy state experienced by the program.
Many important debugging tasks in energy-intermittent systems are impossible without energy-interference-free monitoring and manipulation mechanisms. Passive monitoring allows concurrent tracing of energy, program events, and I/O under realistic scenarios. EDB's energy manipulation and compensation mechanism lets a programmer instrument application code with energy-intensive invariant checks (e.g., asserts) and trace statements (e.g., printfs) without impacting the behavior of the system. The same mechanisms enable interactive debugging with breakpoints that can be conditioned on energy level and with access to the state of the target device.
Energy-interference-freedom is essential for debugging intermittent, energy-harvesting systems. EDB provides this capability, providing debugging primitives for intermittent software, including energy-aware breakpoints, keep-alive assertions, and energy guards.
EDB is an energy-interference-free debugging platform for intermittence debugging that addresses the difficulties described above. EDB is a co-designed hardware and software implementation that makes EDB energy-interference-free debugging possible.
EDB comes in the form of an independently-powered hardware module including a CPU executing the software necessary for interfacing with the target device. An external monitor can be connected to the hardware module to provide a user interface for interactive debugging functions. The hardware module interfaces with the target device via a plurality of interfaces, including general-purpose I/O (GPIO), universal asynchronous receiver-transmitter (UART), an I2C interface. All connections between EDB and the target device are electrically isolated using low-leakage diodes on interface pins to avoid having EDB sourcing current from the target device and/or providing current to the target device. The I/O pins on the interfaces available on the EDB can be mapped via the onboard software to interface with any available I/O point on the target device.
Passive Mode Operation—
EDB's passive mode operation is built around the three right-most components at the top of
Active Mode Operation—
The capability to manipulate the amount of energy stored on the target device is the key to EDB's active mode of operation. Active mode frees debugging tasks from the constraint of the small energy store of the target device. EDB can compensate for the energy consumed by a debugging task that involves a costly operation on the target device, such as interacting with the programmer, executing arbitrary debug code, or conveying state to the debugger. Before performing an active task, the energy on the target device is measured and recorded. While the active task executes, the target is continuously powered. After performing the active task, the energy on the target device is restored to the level measured before the active task. Continuously powering active tasks enables them to consume arbitrary amounts of energy. Energy compensation provides the illusion of an unaltered, intermittent execution of the application. Without this support, debugging tasks that require considerable involvement from the target are not possible.
Energy-Interference-Free Debugging Primitives—
Using the monitoring and manipulation capabilities described thus far, EDB creates a toolbox of energy-interference-free debugging primitives. EDB brings familiar debugging techniques that are currently confined to continuously-powered platforms to intermittent platforms. Additionally, new intermittence-aware primitives are introduced to handle debugging tasks that arise only on intermittently-powered platforms.
Code and Energy Breakpoints—
EDB implements three types of breakpoints. A code breakpoint is a conventional breakpoint that triggers at a specified code point. An energy breakpoint triggers when the target device's energy level is at or below a specified threshold. A combined breakpoint triggers when a specified code point executes and the target device's energy level is at or below a specified threshold. Breakpoints conditioned on energy level can help catch energy leaks due to unexpected code paths. They initiate an interactive debugging session precisely in problematic iterations when more energy was consumed than expected or when the device is about to brown-out.
Keep Alive Assertions—
EDB provides support for using familiar assertions on intermittent platforms. When an assertion fails, EDB immediately tethers the target device to a continuous power supply to prevent it from losing state by browning out. This keep-alive feature turns what would have to be a post-mortem reconstruction of events into an investigation on a live device. A post-mortem analysis is limited to scarce clues in a tiny ad hoc “core dump” that a custom fault handler has managed to save into non-volatile state before the target device runs out of energy and resets. The clues available in the interactive debugging session automatically opened by EDB for a failing assert include the entire live target address space and I/O buses to peripherals.
Energy Guards—
EDB can hide the energy cost of an arbitrary region of code if enclosed between a pair of energy guards. Code within energy guards executes on tethered power. Code on either side of an energy-guarded region experiences an illusion of continuity in the energy level across the energy-guarded region as if no energy was consumed. EDB implements energy guards using its energy compensation mechanism by recording the target energy level upon entering an energy-guarded region of code and restoring the energy level upon exiting the energy-guarded region of code. Without energy cost, instrumentation code becomes non-disruptive and therefore useful on intermittent platforms. Two especially valuable forms of instrumentation impossible without EDB are complex data structure invariant checks and external event tracing. Extra code added to an application to check invariants on data structures or report when certain events have executed via an I/O mechanism (e.g. printf, LED) can be costly enough to repeatedly deplete the target energy supply and prevent forward progress.
Besides instrumentation, EDB energy guards may also assist with the incorporation of non-intermittence-safe third-party code into intermittent applications. As long as third-party library calls are wrapped in energy guards, intermittence failures are guaranteed to not occur within the library. Functionality can now be developed separately from handling intermittence. Similarly, energy guards are useful for gradually porting code from a continuously powered platform to an energy-intermittent platform. A programmer can start with an energy guard around the entire program and repeatedly exclude modules from the guarded region after verifying the correctness of the module under intermittence, until the entire application is out of the guarded region and intermittence-safe.
Interactive Debugging—
EDB supports interactive debugging of a target device from a work-station. An interactive session provides full access to view and modify the target's memory, as with a conventional debugger. A developer can enable code-energy breakpoints and can manually manipulate the target's energy level. An interactive session is entered automatically when a breakpoint is hit, when an assertion fails or on demand by a console command. A unique benefit of EDB is its ability to trigger a manipulation of the target's energy state based on the target's program behavior and vice versa.
Hardware/Software Implementation—
Energy Level Monitoring—
Energy-interference-free measurement of the target device's energy level is essential to EDB's passive mode of operation. To measure a device's energy level, EDB uses two physical connections, Vcap and Vreg, to the target device's energy storage capacitor and its regulated power line, respectively. These signals pass through a dual high impedance, unity gain instrumentation amplifier to minimize leakage current from the target device to the EDB. These analog voltages are digitized by an analog to digital converter (ADC) and are logged or used internally for debugging tasks. While it is possible for energy harvesting devices to measure their own stored energy levels, doing so uses energy, perturbing the energy state being measured and altering the intermittent behavior of the software.
Energy Manipulation and Compensation—
Energy manipulation and compensation are the basis for EDB's active mode of operation. EDB has a custom circuit consisting of a low pass filter, a keeper diode, and GPIO pins that can charge and discharge the target device's energy storage capacitor. This circuit is designed to prevent loading down or trickle charging the target device while inactive (i.e., in a high impedance state).
To charge (or discharge) the target device to a desired voltage level, EDB activates a GPIO pin to raise (or lower) the voltage on the target device's energy storage capacitor. A basic iterative control loop in EDB's software ensures that the voltage converges to the desired level. Discharging works similarly: the target's energy storage capacitor discharges through a fixed resistive load and a software control loop ensures convergence to the desired level. Initially, the charging circuit assumes a capacitive storage element, but with software changes, the same design can support other power storage media, such as thin-film batteries.
I/O Monitoring—
EDB enables passive monitoring of arbitrary I/O and attached peripherals, such as sensors, communication buses, and radios. These digital signals, shown in
Note that, while the target device has an on-board regulator, the Vreg line may drop below its specified, regulated value during a power failure on the target device. The Vreg drop is addressed with a simple tracking circuit consisting of an analog buffer to keep the level shifter at the target device's voltage. This circuit is important because too large a mismatch (i.e., over +/−0.3V) may activate the voltage protection diodes in the target device's MCU, which perturbs the target device's power state.
EDB can monitor GPIO, UART, I2C, and RFID RX/TX data lines. A key benefit of EDB is that it monitors data communication lines externally. With external monitoring, messages (e.g., RFID messages) can be decoded even if the target device does not correctly decode them due to power failures. EDB's I/O monitoring support aids developers in I/O calibration and debugging I/O related issues in software.
Program Event Monitoring—
EDB can track program execution using the Code Marker connections shown in
Monitoring program events using EDB is virtually energy-interference-free. The main energy cost is the target device holding a GPIO pin high for one cycle to encode each traced code point as it executes. The cost of this GPIO-based signaling was found to be negligible. Without EDB, monitoring has a prohibitive cost in code, memory pace, and energy. However, with EDB, events are not only logged without these costs, but also correlated with energy state into a multi-faceted profile.
Developer's Interfaces into EDB—
The debugging primitives provided by EDB are accessible to the end-user through two complimentary interfaces: the libEDB API and the host console commands listed in Table 1. The libEDB library statically links into the on-board software controlling the target device and exports C macros for inserting assertions, breakpoints, watchpoints, energy guards, and energy-interference-free printf calls into the code of the target device. Internally, the library implements the target-side half of the protocol for communicating with the debugger over a dedicated GPIO line and a UART link, which includes routines for reading from and writing to target address space. Preferably, the library is integrated into the software controlling the target device and downloaded to the target device along with that software.
The debug console is a command-line interface for interacting directly with EDB and indirectly with the target device over a USB connection from a workstation. During interactive de-bugging in active mode, the console reports assert failures and breakpoint hits and provides commands to inspect target device memory. During passive mode debugging, the console delivers traces of energy state, watchpoint hits, monitored I/O events, and the output of printf calls. EDB can emulate intermittence at the granularity of individual charge-discharge cycles using the charge/discharge commands.
Implementation Details and Release—
EDB was prototyped as a printed circuit board (PCB) that connects to the target device via a board-to-board header. The core design is also compatible with an implementation as an on-chip component within the target device architecture. EDB software includes firmware and the libEDB, both written in C, and code for the scripting API and host console, both written Python.
Debugging Capabilities—
EDB provides new debugging capabilities to the development of software for intermittent-energy systems. There are several debugging tasks that are particularly difficult to resolve using state-of-the-art tools. Energy-harvesting applications in the following scenarios execute intermittently and keep state in non-volatile memory to make progress without relying on a runtime checkpointing system. A reboot causes execution to return to the program entry point (i.e., the main routine).
Early Detection of Memory Corruption—
Memory corruption due to incorrect pointer arithmetic or a buffer overflow is a frequent yet difficult problem to debug. The root cause is obscured behind symptoms that are far from the offending memory write in both time and in space. Memory corruption induced by intermittence is even harder to diagnose, because it is not reproducible in a conventional debugger. An example of an application is presented that fails due to an intermittence-induced memory corruption and demonstrates how EDB's support for assertions exposes the root cause.
The code snippet listed in the left pane of
After having run on harvested energy for some amount of time, the GPIO pin indicating main loop progress stops toggling. The real oscilloscope trace shown in
Because the broken final state persists across re-boots, one approach is to attach a conventional debugger after the failure and attempt to determine why the main loop stopped running. This approach may help uncover the symptom, but not the root cause, because the information that happens to persist in memory may not be sufficient to follow the chain of events backwards in time. A better approach is to catch the problem at its source by asserting an invariant on the linked-list data structure whenever it is manipulated. However, conventional assertions fall short in this case, because they let the target drain the energy supply, reset, and continue past a failed assertion.
EDB's intermittence-aware assert mechanism is designed to tackle this class of bugs. The invariant that the tail pointer points to the last element in the list is asserted, as shown in
The interactive debug session is shown on the right in
Instrumenting Code With Consistency Checks—
To aid in debugging, applications often have separate debug and release build configurations. A debug build includes instrumentation code such as checks for consistency of data structures or array bounds. On continuously-powered platforms the convenience of the debug build comes at the cost of slower execution speed, higher memory usage, and higher energy consumption. However, on intermittently-powered platforms, the effect is more critical: the energy overhead imposed by the instrumentation can render an application non-functional by preventing it from making any forward progress. Yet, instrumented energy-harvesting applications must be run on harvested energy to diagnose intermittence-induced bugs, since these bugs are invisible while the device is continuously powered. This example demonstrates how an application can be instrumented with debug code of arbitrary energy cost using EDB's energy guards.
The code snippet shown in
The application's release build produces an inconsistent list without any indication that there is a problem. The debug build stops executing the main loop after having added approximately 555 items to the list. The trace in
The energy cost of the consistency check is proportional to the length of the list. Once the list is long enough, the consistency check consumes all of the energy available in one charge-discharge cycle and leaves none for the main loop. Once reached, this hung state persists indefinitely because the application cannot make progress in subsequent charge-discharge cycles.
EDB lets the developer keep the consistency check without breaking application functionality by wrapping the check with energy guards as shown in
Tracing Events and Profiling Energy Cost—
The intermediate results of calculations, frequency of events, and energy cost of operations are valuable clues for quick diagnosis of erroneous code. Directly extracting such information from an energy-harvesting device using existing tools changes the behavior of the application. As an example, the sampling rate of a sensing application may increase by a factor of 100-1000 when powered continuously in the lab relative to when harvesting energy in a realistic deployment. This section demonstrates how EDB's energy-interference-free printf function and watchpoints can view the internals of running code with minimal impact on application behavior.
The code snippet of an activity recognition application shown in
Information can be extracted from the target device either over a traditional debugger interface or using I/O peripherals (e.g. UART or GPIO ports). To relay a data stream via a traditional debugger, the target device must be on during the entire debugging session. Off-the-shelf USB-to-serial adapters are not electrically isolated from the target UART and permit energy to flow into or out of the target device. Encoding information onto GPIO pins and decoding it using an oscilloscope requires significant effort compared to a printf call that outputs text to a console on the host.
The measurements in Table 2 demonstrate the impact on application behavior of using a UART. The energy cost of the printf statement changes the iteration success rate (i.e. the fraction of iterations that successfully complete out of the total attempted). To trace application progress without disrupting its behavior, the loop body was instrumented with an EDB printf and three watchpoints as shown in
Debugging and Tuning RFID Applications—
Energy-harvesting applications that communicate using the RFID protocol are difficult to debug without simultaneous visibility into communication and energy state. This example demonstrates how EDB can monitor RFID I/O messages and correlate them with available energy.
The example RFID firmware decodes RFID query commands from a reader in software and replies with a unique identifier. The application and reader cannot be characterized and tuned without a measure of the target device's performance in different RF environments (e.g. the number of responses per queries received). Correctness cannot be verified without evidence that the application software successfully decodes and acts on each valid incoming query message.
Both tasks require a trace of incoming messages that reached the target device, for example, bit patterns in the incoming de-modulated waveform that could have been decoded into valid messages by software. An oscilloscope trace of the raw output from the RF demodulator does not reveal whether the waveform is decodable into a valid message. A decoder is necessary to separate messages that were corrupted in flight from valid messages that the target application failed to parse.
EDB can be used to stream RFID message identifiers and target device energy readings to the host. The data plotted in
Intermittently executing, energy-harvesting devices present unique system reliability challenges, and the EDB system presented herein is the first debugging system designed to address those challenges. Energy-interference freedom as a property is essential to the utility of a debugging platform for energy-intermittent systems and EDB provides such a capability. EDB supports passive monitoring of a target device's energy, software events, and I/O. Using its ability to manipulate a target device's energy, EDB also supports active debugging tasks with energy-interference freedom, including assertions, instrumentation, breakpointing, tracing, and interactive debugging. A prototype of EDB, including custom hardware, was evaluated and proved to be energy-interference-free in both passive and active tasks, and was able to provide invaluable debugging information that is out of reach using existing tools and techniques.
EDB has been explained in terms of functionality as well as with actual implementation details of the hardware and software. Although prototype EDBs have been built, many hardware and software implementations of EDB are possible without deviating from the intended scope of the invention, which is specified in the claims which follow.
This application claims the benefit of U.S. Provisional Patent Application Ser. No. 62/601,682, filed Mar. 28, 2017.
Number | Date | Country | |
---|---|---|---|
62601682 | Mar 2017 | US |