A deterministic embedded architecture designed for safety-critical firmware, mitigating single-event upsets (SEU) and flash corruption in aerospace and industrial environments through Triple Modular Redundancy (TMR) and autonomous self-healing.
Stack: ESP32 — C++ — Python — Arduino-CLI — esptoolDomain: Aerospace / Industrial IoT — Reliability Engineering — Fail-Operational Systems
01 — Problem
The Fragility of Single-Image Systems
In high-radiation or electrically noisy environments, a single bit-flip in the flash memory (SEU) or a partial write during an OTA update can render a device completely bricked. Standard recovery mechanisms often rely on a single backup, but if both the primary and backup are corrupted, the system fails catastrophically.
TripleRedundant OTA partitions (ota_0, ota_1, ota_2) to ensure a "Golden Image" always exists
3×3 MatrixTwo-layer TMR voting for RAM and CPU operations to eliminate transient faults
ZeroDowntime. The system repairs itself in the background while the main control loop continues
02 — Architecture
Autonomous Self-Healing Loop
The system implements a "Watchdog-Reparation" cycle. Upon boot and periodically during runtime, the agent scans all available OTA slots. If an invalid image is detected, the system dynamically selects the healthiest available slot as the source to rebuild the corrupted partition.
Technical Detail: The "Golden Image" is not fixed. Any partition that passes the ESP_ERR_IMAGE_VALID check can act as the source, allowing the system to evolve its firmware across all slots while maintaining a safety net.
03 — Mitigation Matrix
From Random Failure to Deterministic Recovery
The system treats hardware instability as a data-corruption problem, applying a tiered defense strategy across different memory and compute domains.
Failure Scenario
Mitigation Strategy
System Outcome
Flash Bit-Flip (OTA Partition)
Triple Redundancy and SHA-256
Autonomous repair from valid slot
RAM Corruption (Critical Var)
Two-Layer TMR (3×3 Matrix)
Correct value recovered via voting
Transient CPU Fault (Math)
Symmetric Redundant Compute
Majority vote eliminates outliers
System Hang (Flash Op)
Task Watchdog Timer (TWDT)
Deterministic reboot to valid image
04 — TMR Implementation
Combatting Compiler Optimization
A naive implementation of redundancy (a+b, a+b, a+b) is often collapsed into a single operation by the -O2 or -Os compiler flags. To ensure true physical redundancy, I used volatile qualifiers, compiler memory barriers, and expression diversity.
// TMR-wrapped addition with expression diversitystatic floatadd(float a, float b) {
float res[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
volatile float tmp;
if ((i + j) % 3 == 0) tmp = a + b; // standardelse if ((i + j) % 3 == 1) tmp = b + a; // swappedelse tmp = a; tmp += b; // accumulation
res[i][j] = tmp;
asm volatile("" ::: "memory"); // Memory Barrier
}
}
return twoStageTMR(res);
}
FIG 2.0 — Two-Stage TMR Voting Logic: Eliminating Single Points of Failure
05 — Validation
Fault Injection and Recovery Log
Verification was performed using a Python-based fault injector that writes garbage data to specific OTA flash offsets. The logs show the system detecting an ESP_ERR_IMAGE_INVALID state and initiating a background repair from a secondary valid partition.
# Fault Injection Sequence
[TEST] Corrupting non-running partition ota_0...
[OK] Corrupted ota_0
[INFO] Scanning all partitions.
[ERROR] ota_0 is INVALID (err: ESP_ERR_IMAGE_INVALID)
[INFO] ota_1 is VALID
[INFO] ota_2 is VALID
[INFO] Using ota_2 as source for repairs
[INFO] Attempting to repair invalid partition: ota_0
[INFO] Repairing ota_0 <- ota_2 (size: 1.3 MB)
[INFO] Repair successful, ota_0 is now VALID
<Normal Task> System active - 0ms interruption observed.
Verification: The baseOperation task maintained 100% uptime during the corruption and repair of ota_0, proving the architecture is truly fail-operational.
06 — Impact
From Fragile to Fail-Operational
By decoupling boot validity from a single memory location and implementing computational redundancy, the system mitigates the primary risks of unattended operation in radiation-heavy or electrically noisy environments.
Zero-Touch Recovery: No manual reset or JTAG intervention required after catastrophic flash corruption.
TMR Precision: Mathematical operations are protected against transient CPU faults.
Continuous Availability: Repair cycles happen in parallel to the main control task.
Scalable Redundancy: Triple-slot architecture allows for simultaneous "Golden Image" and "A/B Update" patterns.