The emergence of energy-harvesting devices allows extremely low-power devices to operate using the energy that they extract from their environment only. Energy-harvesting frees a device from its tethered power supply, enabling the use of these devices in a broad range of emerging sensing, computing, and communication applications “beyond the edge”. However, an application can run only intermittently, when the energy-harvesting device has sufficient energy available to do some useful work. A typical device works by collecting energy from an extremely low-power input source (e.g., radio waves, weak solar energy, vibration), slowly accumulating the energy in a capacitor. After sufficient energy accumulates, the device runs a burst of operations, quickly consuming the energy and powering off, awaiting more energy in the future. Applications on these devices operate according to the intermittent execution model, making application progress in short bursts interleaved by recharge periods.
What makes intermittent computing challenging?
Without careful programming and system support, applications can fail to make forward progress, and intermittent operation can leave non-volatile and volatile memory states inconsistent. If the execution state is not saved across power failures, the program will run from the beginning on re-boot, and it will never progress further than what can be executed in one power cycle. To make reliable forward progress, the programmer needs to use some sort of checkpointing system and to ensure that the next checkpoint is a reachable distance with one capacitor charge.
Since the microcontrollers used for intermittent computing have a mixture of volatile and non-volatile memory, a naive system might allow the two memory states to become inconsistent. In the example image, the program is incrementing a counter located in non-volatile memory and then storing a data sample into a buffer at the counter index. If the power cycle ends between the increment and accelerometer read, the volatile execution state is cleared and reverts to what it was at the beginning of the program, but the non-volatile counter does not. In the second execution attempt, the program increments the counter again unecessarily, and then stores into the buffer, skipping a slot.