Embedded firmware occupies a category of software where the cost of a bug is categorically different from any other domain. On a web server, a bad deploy is a rollback. On a mobile app, a bad release waits for review. On a deployed IoT device, a firmware bug that corrupts flash or bricks the boot loader can require a physical recall or a truck roll to reflash devices that are installed in walls, buried in machinery, or distributed across thousands of field sites. That stakes profile changes every engineering decision: memory layout must be deliberate, interrupt handlers must be reentrant-safe, the OTA partition scheme must have a rollback path that works even when the new firmware fails to boot, and the power management strategy must be designed with a specific battery life target rather than discovered empirically after the hardware revision is locked. These are the engineering decisions that separate firmware that ships reliably from firmware that creates support costs for years. Volt is built to make those decisions correctly the first time.
Why the generalist approach breaks down
Ask a generalist chatbot to write a device driver for an I2C sensor and you will get code that initializes the peripheral and reads a register. Ask a firmware engineer to review it and they will find the missing timeout on the I2C transaction (the bus can hang indefinitely if the slave does not respond), the absent error return path from the HAL call (the code assumes HAL_I2C_Mem_Read always succeeds), the global state in the driver that makes it non-reentrant across the two contexts that call it (the main loop and an interrupt handler), and the raw register read that is not followed by the correct endian swap for a 16-bit value on a little-endian MCU. Each of these is a correctness issue with a known pattern fix, but they are invisible to a generalist that is producing syntactically valid C without embedded-systems knowledge.
Cursor and GitHub Copilot are more capable with embedded code than they were two years ago, but they complete patterns at the statement level rather than the architecture level. They will complete a Zephyr RTOS thread declaration without noting that the stack size chosen is too small for the interrupt-driven sensor read pattern the code uses. They will suggest a k_sleep(K_MSEC(100)) call without noting that this keeps the processor in a busy-wait mode that burns current at a rate inconsistent with a two-year battery life target. They will not suggest that the driver should be implemented behind a HAL boundary that allows mock substitution for unit tests. These are the design decisions that require systems-level thinking, not token-level completion.
Vendor SDK examples are perhaps the most dangerous starting point because they are written to demonstrate API usage, not to demonstrate production engineering. The ESP-IDF example for BLE advertising shows the API calls correctly. It does not show how to handle the advertising restart after a connection drops, the pairing state machine for secure bonding, the memory reclamation when a connection closes without proper termination, or the watchdog feed needed in the connection event handler to prevent a system reset during a long connection interval. The gap between a working example and production firmware is all the error handling, state machine correctness, and defensive design that examples deliberately omit to stay readable.
What an embedded engineer actually does
In a hardware company, the embedded engineer is the person who translates the hardware specification into working, reliable software that runs on constrained resources. They read the MCU datasheet and the peripheral datasheets before writing a line of code. They design the memory layout, flash regions for the application, bootloader, and OTA staging; RAM regions for stack, heap, and DMA buffers, deliberately rather than accepting defaults. They write interrupt handlers that are as short as possible and defer work to tasks or deferred function queues, because interrupt handler bugs are among the hardest to reproduce and debug. They design the power state machine with specific sleep modes and wake sources, and they measure the actual current draw at each state against the budget rather than estimating it.
The OTA architecture is where embedded engineering most visibly diverges from any other software domain. A field-deployed IoT device needs a firmware update mechanism that is safe to power-cycle at any point during the update, a power interruption mid-flash cannot brick the device. This requires a dual-partition or A/B update scheme where the new firmware is written to the inactive partition, validated by CRC or signature check, and only marked as active after the verification passes. The rollback mechanism must also work: if the new firmware fails to boot, the bootloader must detect the failure and revert to the previous partition without requiring any network connectivity. Implementing this correctly requires understanding the bootloader, the flash partition layout, the signature verification chain, and the boot counter logic, and making all of these decisions before the first device ships, because changing them in the field is exactly the kind of change that requires the OTA mechanism to already work.
Meet Volt
Volt is Tonone's embedded systems engineer, the specialist agent for firmware architecture, MCU drivers, OTA update systems, IoT protocols, and power management. Volt's working standard is that every driver it writes is behind a HAL boundary, every interrupt handler is minimal and reentrant-safe, every OTA system has a verified rollback path, and every power budget is designed against a specific battery life target rather than measured as an afterthought. Volt does not produce firmware that works on the bench; it produces firmware that is reliable in the field.
Tonone's Volt builds firmware for ESP32, STM32, and Nordic nRF platforms with interrupt-driven drivers behind HAL boundaries, OTA with dual-partition rollback, and power budgets designed for specific battery life targets.
What Volt actually does
Designing firmware architecture for MCU platforms
The volt-firmware skill is where embedded projects begin. You describe the target MCU, the connected peripherals, the communication protocols, the power constraints, and the operating environment, and Volt produces a firmware architecture that makes the structural decisions before a line of driver code is written. The architecture output covers the RTOS task structure (which tasks run at which priorities, what their stack sizes should be, and how they communicate via queues or semaphores), the HAL boundary design (the abstract interfaces that isolate hardware-specific code from application logic and enable unit testing), the memory layout (flash partition map including bootloader, application, OTA staging, and NVS regions), the error handling strategy (how hardware errors propagate up to the application layer without causing undefined behavior), and the watchdog configuration (independent watchdog for hardware fault detection, window watchdog for timing constraint verification). For Zephyr RTOS projects, Volt produces the device tree overlay alongside the application code, so peripheral configuration is in the correct location rather than hardcoded in driver initialization. For FreeRTOS or bare-metal projects, Volt adapts the architecture to the constraints of the runtime. The architecture document is designed to be reviewed by the hardware team before implementation begins, the firmware and hardware decisions are more interdependent in embedded systems than in any other software domain.
Writing interrupt-driven device drivers
The volt-driver skill produces device drivers that meet the production standard for embedded systems: a clean HAL boundary, minimal interrupt handlers that defer work to task context, correct timeout handling on all blocking operations, and explicit error propagation from every HAL call. For I2C and SPI sensor drivers, this means a driver struct that holds the peripheral handle and configuration, an initialization function that validates the sensor identity register before proceeding, read functions that handle I2C timeout and NAK conditions without hanging, and data conversion functions with the correct endian handling for the target MCU. For UART protocol drivers, Volt implements DMA-based receive with a ring buffer and a delimiter-based packet parser that runs in interrupt context at minimum cost, deferring packet processing to a task. For GPIO-based drivers (buttons, encoders, LEDs), Volt implements debouncing for inputs at the timer interrupt level and PWM generation using hardware timers rather than software toggling. Every driver produced by volt-driver includes a mock implementation behind the same HAL interface, so unit tests can run on the development machine without hardware and the application logic can be tested independently of the hardware state.
Tonone's Volt volt-driver skill produces interrupt-driven device drivers with HAL boundaries, correct timeout handling, endian-aware data conversion, and mock implementations, so drivers can be unit-tested off-hardware.
Building OTA update systems with rollback
The volt-ota skill builds the over-the-air update system that makes field-deployed firmware safely updateable. Volt implements the full A/B partition scheme: two application partitions in flash (the active partition from which the device is currently booting and the inactive partition that receives the new firmware image), a download pipeline that streams the firmware image to the inactive partition over MQTT or HTTPS with chunk validation, a signature verification step using an embedded public key that validates the image before it is ever marked as bootable, and a boot counter mechanism in the bootloader that detects failed boots and automatically reverts to the previous partition. The OTA pipeline is designed to be power-cycle-safe at every step: if power is interrupted during the download, the next boot continues from the active partition; if interrupted during the swap, the boot counter logic catches the incomplete transition; if the new firmware boots but fails the application-level health check, the firmware can revert itself by resetting the boot counter and requesting a reboot. The output includes the partition table configuration, the bootloader additions needed for the counter logic, the OTA client code in the application firmware, and the server-side signing workflow for generating correctly signed images. For ESP32 targets, Volt integrates with the IDF OTA framework while adding the signature verification layer that the default IDF example omits.
Auditing and optimizing power budgets
The volt-power skill designs and audits the power management system against a specific battery life target. The starting point is not the firmware, it is the power budget spreadsheet: the total battery capacity, the active current draw in each operating mode, the duty cycle of each mode, and the resulting estimated battery life. Volt builds this budget from the hardware specifications and the firmware's operating pattern, then designs the sleep architecture to meet the target. For battery-operated IoT devices, this typically means a power state machine with a deep sleep state that consumes under ten microamps, a configurable wake interval, wake sources for the communication radio and interrupt-driven sensors, and a connection-burst pattern for cloud sync (wake, connect, transmit, reconnect sleep) that minimizes radio-on time. Volt identifies the current draw offenders that are not obvious: the pull-up resistor on an I2C bus that is powered even in deep sleep because the GPIO is not driven low before sleep entry, the ADC reference voltage that remains enabled because the shutdown sequence is incorrect, the external flash that is not put into deep power-down mode. Each of these can represent milliamps of wasted current in a device that is targeting microamp sleep current. The power audit output includes current measurement checkpoints so the hardware team can verify actual current draw against the model, not just trust the firmware's intent.
Reconnaissance of embedded systems
The volt-recon skill is the intake assessment for existing firmware projects. Volt reads the project structure, the build system configuration, the existing driver implementations, the RTOS configuration, the memory layout, and the OTA setup (if any), and produces a structured assessment of the current state and the engineering risks. The recon output identifies drivers that have no HAL abstraction (making them untestable), interrupt handlers that do too much work in interrupt context (creating priority inversion risks), memory regions that are sized without accounting for stack usage under interrupt nesting, and OTA implementations that have no rollback path. For teams taking over an existing firmware project, volt-recon is the intake assessment that prevents the most dangerous failure mode in embedded: making a change to firmware that is already deployed in the field without understanding the risk surface.
A worked example
A team is building a battery-powered sensor node on the ESP32-C3 that reads a temperature/humidity sensor over I2C and reports via MQTT. They ask Volt to write the I2C driver with correct error handling and a HAL boundary for testability. Volt produces the following C implementation, interrupt-safe, timeout-protected, and testable off-hardware:
/* volt-driver output, SHT41 temperature/humidity driver, ESP-IDF I2C HAL */
#include "sht41_driver.h"
#include "driver/i2c_master.h"
#include "esp_log.h"
#include <string.h>
#define SHT41_ADDR 0x44
#define SHT41_CMD_MEASURE 0xFD /* High-precision, no heater */
#define I2C_TIMEOUT_MS 100
static const char *TAG = "sht41";
/* HAL interface, swap this struct to test without hardware */
typedef struct {
esp_err_t (*write)(uint8_t addr, const uint8_t *buf, size_t len);
esp_err_t (*read)(uint8_t addr, uint8_t *buf, size_t len);
void (*delay_ms)(uint32_t ms);
} sht41_hal_t;
typedef struct {
sht41_hal_t hal;
i2c_master_dev_handle_t dev;
} sht41_ctx_t;
/* CRC-8 per SHT41 datasheet (polynomial 0x31, init 0xFF) */
static uint8_t crc8(const uint8_t *buf, size_t len) {
uint8_t crc = 0xFF;
for (size_t i = 0; i < len; i++) {
crc ^= buf[i];
for (int b = 0; b < 8; b++)
crc = (crc & 0x80) ? (crc << 1) ^ 0x31 : crc << 1;
}
return crc;
}
esp_err_t sht41_init(sht41_ctx_t *ctx, i2c_master_bus_handle_t bus) {
i2c_device_config_t cfg = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = SHT41_ADDR,
.scl_speed_hz = 400000,
};
esp_err_t err = i2c_master_bus_add_device(bus, &cfg, &ctx->dev);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to add I2C device: %s", esp_err_to_name(err));
return err;
}
ESP_LOGI(TAG, "SHT41 initialised at 0x%02X", SHT41_ADDR);
return ESP_OK;
}
esp_err_t sht41_read(sht41_ctx_t *ctx,
float *temp_c, float *humidity_pct) {
uint8_t cmd = SHT41_CMD_MEASURE;
uint8_t raw[6];
/* Transmit measurement command */
esp_err_t err = i2c_master_transmit(
ctx->dev, &cmd, 1, I2C_TIMEOUT_MS
);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Tx error: %s", esp_err_to_name(err));
return err;
}
/* SHT41 needs ≥8.3 ms for high-precision measurement */
vTaskDelay(pdMS_TO_TICKS(10));
/* Receive 6 bytes: [T_MSB, T_LSB, T_CRC, H_MSB, H_LSB, H_CRC] */
err = i2c_master_receive(ctx->dev, raw, sizeof(raw), I2C_TIMEOUT_MS);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Rx error: %s", esp_err_to_name(err));
return err;
}
/* Validate CRC for both temperature and humidity words */
if (crc8(raw, 2) != raw[2] || crc8(raw + 3, 2) != raw[5]) {
ESP_LOGE(TAG, "CRC mismatch, data corrupt");
return ESP_ERR_INVALID_CRC;
}
/* Convert per datasheet: T = -45 + 175 * val / 65535 */
uint16_t t_raw = ((uint16_t)raw[0] << 8) | raw[1];
uint16_t h_raw = ((uint16_t)raw[3] << 8) | raw[4];
*temp_c = -45.0f + 175.0f * t_raw / 65535.0f;
*humidity_pct = -6.0f + 125.0f * h_raw / 65535.0f;
/* Clamp humidity to [0, 100], sensor can report slightly out of range */
if (*humidity_pct < 0.0f) *humidity_pct = 0.0f;
if (*humidity_pct > 100.0f) *humidity_pct = 100.0f;
return ESP_OK;
}Every embedded engineering concern is addressed: explicit error returns from every HAL call rather than assuming success, a timeout parameter on both the transmit and receive operations so a bus hang does not block the calling task indefinitely, CRC validation against both data words so bit errors in the I2C transaction are detected rather than silently passed to the application, correct endian conversion for the 16-bit raw values, humidity clamping to the physical range because the sensor datasheet documents out-of-range cases, and a HAL interface struct at the top of the driver that can be swapped for a mock in unit tests. This is the standard a firmware engineer holds. Volt produces it on the first output, not after a review cycle.
If you are starting a new embedded project, run volt-firmware before writing any driver code, the architecture decisions (RTOS task structure, HAL boundaries, flash layout) are much harder to change after drivers are written than before. If you are preparing for a field deployment and do not have an OTA system with rollback, volt-ota is the highest-priority investment, the first field update without a rollback path is the one that might require a truck roll.
Volt vs the alternatives
Volt is not competing with vendor SDKs or hardware documentation, it is the engineer who understands them and applies embedded systems discipline on top. The comparison below shows where Volt adds value that generalist tools, autocomplete, and vendor examples cannot provide.
| Capability | Tonone | Generalist chatbot | Cursor / Copilot |
|---|---|---|---|
| Interrupt-driven drivers with HAL boundaries and error handling | Yes, HAL abstraction, minimal ISR with task deferral, timeout on all blocking calls, mock for unit testing | Partial, produces working driver code without HAL boundary, reentrance safety, or timeout handling | Partial, completes driver syntax without embedded-specific error handling or HAL design |
| OTA system with dual-partition rollback | Yes, A/B partitions, signature verification, boot counter rollback, power-cycle-safe at every step | Partial, describes OTA architecture but produces code without signature verification or rollback logic | Partial, vendor examples show API usage without rollback design or power-cycle safety |
| Power budget design for battery life targets | Yes, current budget model, sleep state machine, radio duty cycle, current draw offender identification | No, can explain sleep modes conceptually but does not produce a calibrated power budget design | No, vendor examples demonstrate power APIs, not power budget engineering |
| RTOS architecture with task sizing and IPC | Yes, task structure, priority assignment, stack sizing, queue/semaphore IPC design per use case | Partial, can write FreeRTOS task code without priority inversion analysis or stack sizing | Partial, completes RTOS API usage without architecture-level design |
| CRC and data integrity for sensor reads | Yes, CRC validation per datasheet spec, endian conversion, physical range clamping | Partial, may include CRC if mentioned in the prompt, but does not apply it by default | No, no sensor data integrity design without explicit instruction |
| Firmware recon and risk assessment for existing codebases | Yes, volt-recon identifies HAL gaps, ISR overload, memory layout risks, and missing OTA rollback | Partial, can review code you paste but lacks embedded systems architecture assessment | No, no embedded architecture assessment capability |
Tonone's Volt volt-ota skill builds OTA systems that are power-cycle-safe at every step, dual-partition A/B scheme, signature verification, and boot counter rollback so a failed update never bricks a field-deployed device.
Install and try
Tonone is free and MIT-licensed. Install it once and all 23 agents, including Volt, are available in your Claude Code session. You pay only for Claude Code token usage during the work.
1. Add to marketplace
2. Install Volt
Frequently asked questions
- What does Tonone's Volt do?
- Volt is Tonone's embedded systems engineer. It builds firmware for MCU platforms including ESP32, STM32, and Nordic nRF. It writes interrupt-driven device drivers with HAL boundaries and error handling. It creates OTA update systems with dual-partition A/B schemes, signature verification, and rollback. It audits power budgets for battery life targets and identifies current draw offenders in existing firmware.
- What is a HAL boundary in embedded firmware and why does Volt use it?
- A Hardware Abstraction Layer boundary is an interface struct or set of function pointers that separates hardware-specific code from application logic. Volt uses HAL boundaries so drivers can be swapped for mock implementations in unit tests, running tests on the development machine without hardware. This is the primary mechanism for making embedded firmware testable.
- How does the dual-partition OTA rollback work?
- The A/B partition scheme keeps two application partitions in flash: the active partition currently running and the inactive partition that receives new firmware. The new image is written to the inactive partition, CRC- and signature-verified, and then marked as the next boot target. A boot counter in the bootloader tracks attempted boots, if the new firmware fails to boot a configurable number of times, the bootloader reverts to the previous partition automatically.
- Does Volt work with Zephyr RTOS?
- Yes. Volt produces Zephyr device tree overlays alongside application code, places peripheral configuration in the correct devicetree location, and follows Zephyr's driver model including the devicetree-based binding pattern. It also works with FreeRTOS, ESP-IDF's event loop system, and bare-metal projects.
- How does Volt model power budgets?
- volt-power starts with the battery capacity and the target life, then builds a current budget by mode: active processing, radio TX, radio RX, light sleep, and deep sleep. It designs the sleep state machine to meet the budget, calculates radio duty cycle for the cloud sync pattern, and identifies the specific firmware behaviors, GPIO pull-ups left active in sleep, ADC reference not shut down, that blow the budget. The output includes measurement checkpoints for hardware verification.
- Can Volt write BLE and MQTT protocol handlers?
- Yes. Volt writes BLE advertising and connection handlers for the GATT-based patterns common in IoT devices, including pairing state machines and connection event memory management. It writes MQTT client implementations with TLS, reconnect logic, QoS level selection, and the correct last-will configuration for device presence tracking. Both follow the platform SDK conventions (ESP-IDF, Zephyr, Nordic SDK) for the target MCU.
- How do I install Tonone's Volt agent?
- Install Tonone via the get-started guide at tonone.ai/get-started. Volt is one of 23 agents in the Tonone package. Invoke it with slash commands like /volt-firmware, /volt-driver, or /volt-ota. Tonone is free and MIT-licensed.