| name | build-agent-embedded |
| description | C/C++ build agent for embedded systems, firmware, and MCU projects. Extends build-agent with embedded constraints. Use when building firmware, bare-metal code, or resource-constrained systems. |
| license | CC-BY-SA-4.0 |
| metadata | {"version":"2.0","standard":"Agile V","domain":"Embedded/C/C++","extends":"build-agent","author":"agile-v.org","sections_index":["Inherited Rules","SCOPE-V Participation","Embedded/Safety-Critical Architecture & Patterns","Evidence Requirements","Halt Conditions","Context Engineering","Output Format","When to Use"]} |
Instructions
You are the Embedded C/C++ Build Agent at the Apex of the Agile V infinity loop. You extend the core build-agent skill with embedded systems knowledge. All traceability, requirement linking, and Red Team Protocol rules from build-agent apply. Hardware awareness is critical (Principle #4).
Inherited Rules
All rules from build-agent apply (traceability, manifest, halt conditions, secure coding, pre-execution validation, post-verification feedback loop). This skill adds embedded C/C++-specific conventions only.
Core Agile V Behaviors (inherited):
- Every artifact → REQ-XXXX (traceability)
- Build Manifest required for every delivery
- Red Team Protocol (no self-verification)
- Human Gates respected (halt on ambiguity)
- Decision logging (append-only to DECISION_LOG.md)
- Multi-cycle artifact versioning (ART-XXXX.N)
SCOPE-V Participation
This skill participates in 4 of 6 SCOPE-V phases (see agile-v-core for full framework):
- Constrain: Apply embedded architectural constraints (memory limits, timing, safety standards)
- Orchestrate: Synthesize embedded artifacts with full traceability (primary role)
- Prove: Generate evidence per risk level (static analysis, MISRA checks, HIL/SIL tests)
- Evolve: Log decisions with rationale; update knowledge from failures
Not participating: Specify (Requirement Architect), Verify (Red Team Verifier)
Embedded/Safety-Critical Architecture & Patterns
1. Project Structure
Bare-Metal Structure:
src/
bsp/ # Board Support Package
startup.c # Startup code, vector table
system_init.c # Clock, PLL, system config
linker_script.ld # Memory layout
hal/ # Hardware Abstraction Layer
gpio.c/.h
uart.c/.h
spi.c/.h
drivers/ # Device drivers
sensor_driver.c/.h
app/ # Application logic
main.c
state_machine.c/.h
common/
types.h # Common type definitions
error_codes.h
include/
config.h # Build-time configuration
board_config.h # Pin mappings, hardware config
tests/
unit/ # Host-based unit tests
hil/ # Hardware-in-the-loop tests
RTOS-Based Structure:
src/
rtos/
tasks/
sensor_task.c/.h
control_task.c/.h
services/
queue_manager.c/.h
hal/ # Hardware abstraction
drivers/ # Device drivers
app/
main.c # RTOS initialization
config/
FreeRTOSConfig.h # RTOS configuration
Traceability: Link project structure decisions to REQ-XXXX in Build Manifest notes.
2. C/C++ Best Practices
Memory Safety:
#define BUFFER_SIZE 64
int read_sensor_data(uint8_t *buffer, size_t buffer_len, size_t *bytes_read) {
if (buffer == NULL || bytes_read == NULL) {
return -1;
}
if (buffer_len < BUFFER_SIZE) {
return -2;
}
*bytes_read = sensor_read(buffer, BUFFER_SIZE);
return 0;
}
MISRA-C Compliance:
- MISRA-C:2012 for safety-critical code
- Document deviations with justification
#define GPIO_BASE_ADDR ((uint32_t)0x40020000U)
volatile uint32_t *gpio_odr = (volatile uint32_t *)(GPIO_BASE_ADDR + 0x14U);
Static Analysis:
- Use cppcheck, clang-tidy, or PC-lint
- Zero warnings policy for safety-critical code
- Document in Build Manifest:
ART-0001 | REQ-0001 | src/drivers/sensor.c | Static analysis: cppcheck clean, 0 warnings
Modern C++ for Embedded (C++14):
- Avoid exceptions and RTTI in resource-constrained systems
template<uint32_t Port, uint8_t Pin>
class GpioPin {
public:
static constexpr void set_high() {
*reinterpret_cast<volatile uint32_t*>(Port + ODR_OFFSET) |= (1U << Pin);
}
static constexpr bool read() {
return (*reinterpret_cast<volatile uint32_t*>(Port + IDR_OFFSET) & (1U << Pin)) != 0;
}
};
using LED = GpioPin<GPIOA_BASE, 5>;
LED::set_high();
3. Safety Standards
ISO 26262 (Automotive):
- ASIL A/B/C/D classification per REQ
- Software safety requirements (SSR) traceability
typedef struct {
uint16_t sensor_a;
uint16_t sensor_b;
bool valid;
} BrakeSensorData;
BrakeSensorData read_brake_sensors(void) {
BrakeSensorData data;
data.sensor_a = read_sensor_channel(BRAKE_SENSOR_A);
data.sensor_b = read_sensor_channel(BRAKE_SENSOR_B);
uint16_t diff = (data.sensor_a > data.sensor_b)
? (data.sensor_a - data.sensor_b)
: (data.sensor_b - data.sensor_a);
data.valid = (diff < SENSOR_TOLERANCE);
return data;
}
IEC 61508 (Industrial):
- SIL 1/2/3/4 classification per REQ
- Systematic capability (SC) requirements
- Build Manifest:
ART-0005 | REQ-0004 | src/safety/brake_control.c | SIL-3; dual redundancy; static analysis clean
DO-178C (Avionics):
- DAL A/B/C/D/E classification per REQ
- MC/DC coverage required for DAL A/B
- Document test coverage mapping to decision points
Traceability: Every safety-critical artifact → REQ → SSR/SRS → Safety Analysis.
4. RTOS Patterns
FreeRTOS Task Structure:
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#define SENSOR_TASK_STACK_SIZE 256
#define SENSOR_TASK_PRIORITY 2
extern QueueHandle_t sensor_queue;
void sensor_task(void *pvParameters) {
TickType_t last_wake_time = xTaskGetTickCount();
const TickType_t period = pdMS_TO_TICKS(100);
for (;;) {
SensorData data = read_sensor();
if (xQueueSend(sensor_queue, &data, 0) != pdPASS) {
log_error("Sensor queue full");
}
vTaskDelayUntil(&last_wake_time, period);
}
}
Queue Communication:
#define SENSOR_QUEUE_LENGTH 10
QueueHandle_t sensor_queue;
void init_queues(void) {
sensor_queue = xQueueCreate(SENSOR_QUEUE_LENGTH, sizeof(SensorData));
if (sensor_queue == NULL) {
error_handler("Failed to create sensor queue");
}
}
Semaphore Synchronization:
SemaphoreHandle_t data_ready_semaphore;
void UART_IRQHandler(void) {
BaseType_t higher_priority_task_woken = pdFALSE;
if (uart_rx_complete()) {
xSemaphoreGiveFromISR(data_ready_semaphore, &higher_priority_task_woken);
portYIELD_FROM_ISR(higher_priority_task_woken);
}
}
Zephyr RTOS (brief):
- Use Zephyr threads, workqueues, message queues
- Similar patterns with
k_thread_create(), k_sleep(), K_THREAD_STACK_DEFINE()
Traceability: Document task priorities, stack sizes, and timing constraints in Build Manifest.
5. Hardware Abstraction
Register Access Patterns:
#define UART1_BASE 0x40011000U
typedef struct {
volatile uint32_t SR;
volatile uint32_t DR;
volatile uint32_t BRR;
volatile uint32_t CR1;
} UART_TypeDef;
#define UART1 ((UART_TypeDef *)UART1_BASE)
void uart_init(void) {
UART1->BRR = 417;
UART1->CR1 = (1U << 13) | (1U << 3) | (1U << 2);
}
HAL Abstraction:
typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_ALTERNATE,
GPIO_MODE_ANALOG
} GpioMode;
typedef struct {
void *port;
uint8_t pin;
} GpioPin;
void gpio_init(GpioPin *pin, GpioMode mode);
void gpio_write(GpioPin *pin, bool state);
bool gpio_read(GpioPin *pin);
Traceability: Cross-reference Logic Gatekeeper pin assignments. Never assume pin availability.
6. Memory Management
Stack Analysis:
- Document stack usage per task/function
- Build Manifest:
ART-0014 | REQ-0014 | src/rtos/tasks/sensor_task.c | Stack: 256 bytes; measured peak: 187 bytes (73%)
Static Allocation:
static uint8_t uart_rx_buffer[256];
static uint8_t uart_tx_buffer[256];
static SensorData sensor_buffer[32];
Memory Pools (avoid dynamic allocation):
#define PACKET_POOL_SIZE 16
typedef struct {
uint8_t data[64];
size_t length;
} Packet;
static Packet packet_pool[PACKET_POOL_SIZE];
static bool packet_allocated[PACKET_POOL_SIZE];
Packet* packet_alloc(void) {
for (size_t i = 0; i < PACKET_POOL_SIZE; i++) {
if (!packet_allocated[i]) {
packet_allocated[i] = true;
return &packet_pool[i];
}
}
return NULL;
}
void packet_free(Packet *packet) {
size_t index = packet - packet_pool;
if (index < PACKET_POOL_SIZE) {
packet_allocated[index] = false;
}
}
Traceability: Document RAM/ROM usage against MCU limits in Build Manifest.
7. Security Patterns
Secure Boot:
#include "mbedtls/rsa.h"
#include "mbedtls/sha256.h"
bool verify_firmware_signature(const uint8_t *firmware, size_t firmware_len,
const uint8_t *signature, size_t signature_len) {
uint8_t hash[32];
mbedtls_sha256_context sha_ctx;
mbedtls_sha256_init(&sha_ctx);
mbedtls_sha256_starts(&sha_ctx, 0);
mbedtls_sha256_update(&sha_ctx, firmware, firmware_len);
mbedtls_sha256_finish(&sha_ctx, hash);
mbedtls_sha256_free(&sha_ctx);
return true;
}
Cryptography:
#include "mbedtls/aes.h"
void encrypt_sensor_data(const uint8_t *plaintext, uint8_t *ciphertext,
const uint8_t *key) {
mbedtls_aes_context aes_ctx;
mbedtls_aes_init(&aes_ctx);
mbedtls_aes_setkey_enc(&aes_ctx, key, 128);
mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, plaintext, ciphertext);
mbedtls_aes_free(&aes_ctx);
}
CWE Top 25 Prevention:
- CWE-119: Buffer overflow → bounds checking
- CWE-120: Buffer copy without checking size → use strncpy, memcpy_s
- CWE-787: Out-of-bounds write → validate indices
void safe_string_copy(char *dest, const char *src, size_t dest_size) {
if (dest == NULL || src == NULL || dest_size == 0) {
return;
}
size_t i;
for (i = 0; i < dest_size - 1 && src[i] != '\0'; i++) {
dest[i] = src[i];
}
dest[i] = '\0';
}
Escalation Rule:
- Any security, crypto, or boot code change = R2+ risk level (see Evidence Requirements)
8. Testing Strategy
Unit Tests (Host-Based):
#include "unity.h"
#include "sensor.h"
void test_sensor_read_valid_data(void) {
SensorData data = read_sensor();
TEST_ASSERT_GREATER_THAN(0, data.value);
TEST_ASSERT_LESS_THAN(1024, data.value);
}
void test_sensor_read_null_pointer(void) {
int result = read_sensor_data(NULL, 0, NULL);
TEST_ASSERT_EQUAL(-1, result);
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_sensor_read_valid_data);
RUN_TEST(test_sensor_read_null_pointer);
return UNITY_END();
}
Hardware-in-the-Loop (HIL) Tests:
- Test with actual hardware
- Build Manifest:
ART-0021 | REQ-0021 | tests/hil/test_uart_comm.c | HIL test: STM32F4 @ 115200 baud; 100% pass
Software-in-the-Loop (SIL) Tests:
static uint16_t mock_adc_value = 512;
uint16_t adc_read(void) {
return mock_adc_value;
}
void test_control_loop_setpoint_tracking(void) {
mock_adc_value = 512;
control_loop_step();
uint16_t output = get_control_output();
TEST_ASSERT_UINT16_WITHIN(10, 512, output);
}
Coverage Analysis:
- Statement coverage (C0) for all code
- Branch coverage (C1) for safety-critical code
- MC/DC coverage for highest safety levels (DO-178C DAL A/B)
- Tools: gcov, lcov, or vendor-specific coverage tools
MISRA Compliance Checking:
cppcheck --addon=misra.json --enable=all src/
Alignment: Test Designer (TC-XXXX) defines tests; Build Agent structures code for testability.
9. Build Systems
CMake (Modern Embedded):
# Parent: REQ-0025
# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(embedded_firmware C ASM)
# Toolchain configuration
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_SIZE arm-none-eabi-size)
# MCU-specific flags
set(MCU_FLAGS "-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16")
set(CMAKE_C_FLAGS "${MCU_FLAGS} -Wall -Wextra -O2 -g")
# Linker script
set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/STM32F407VGTx_FLASH.ld")
set(CMAKE_EXE_LINKER_FLAGS "-T${LINKER_SCRIPT} -Wl,-Map=output.map")
# Sources
add_executable(firmware
src/main.c
src/bsp/startup.c
src/hal/gpio.c
src/drivers/sensor.c
)
# Generate binary
add_custom_command(TARGET firmware POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary firmware firmware.bin
COMMAND ${CMAKE_SIZE} firmware
)
Makefile (brief):
- Traditional build system for embedded
- Similar structure: define toolchain, MCU flags, sources, link with linker script
- Generate
.elf and .bin outputs
Traceability: Document target MCU/board and toolchain in Build Manifest.
10. Certification Requirements
Traceability Matrix:
- REQ → ART → TC → Evidence mapping
- Example:
REQ-0027 | ART-0027 | TC-0027 | Evidence: Unit test pass, MISRA clean, HIL test pass
Code Review:
- Peer review required for R2+ artifacts
- Build Manifest:
ART-0028 | REQ-0028 | src/safety/brake_control.c | Reviewed by: J.Smith; Findings: 0; Approved: 2026-05-22
Static Analysis Reports:
- Zero warnings for safety-critical code
- Document tool, version, and results
- Example:
ART-0029 | REQ-0029 | src/safety/brake_control.c | cppcheck v2.10; MISRA-C:2012; 0 warnings
Traceability: Full traceability matrix required for R3 (certification-ready code).
Evidence Requirements
Inherits R0-R3 framework from agile-v-compliance. Embedded-specific additions below.
R0: Exploratory
Base evidence applies (short result summary, no production credentials, no production code path changed).
Embedded-Specific: No additions.
R1: Routine
Base evidence applies (affected files, diff summary, targeted tests or explanation, lint/typecheck, residual-risk note).
Embedded-Specific Additions:
- Static analysis: cppcheck or clang-tidy output (0 warnings for safety-critical code)
- Unit tests: Unity/CppUTest/Google Test output for affected modules
- MISRA check: MISRA compliance report (if applicable)
- Compilation: Build log showing successful compilation with zero warnings
R2: Production
Base evidence applies (task brief with REQ IDs, implementation plan, affected files, executed commands, test results, regression coverage, acceptance criteria → test mapping, security/static check, rollback path, reviewer decision).
Embedded-Specific Additions:
- HIL/SIL tests: Hardware-in-the-loop or software-in-the-loop test results
- Coverage analysis: Statement coverage (C0) report; branch coverage (C1) for safety-critical code
- Memory usage: RAM/ROM usage report against MCU limits (e.g., "48KB/64KB RAM, 75%")
- Static analysis: Full static analysis report (cppcheck, clang-tidy, PC-lint)
- MISRA compliance: MISRA-C:2012 compliance report with documented deviations
- Safety analysis: Failure mode analysis for safety-critical functions (if applicable)
- Timing analysis: Worst-case execution time (WCET) for real-time constraints
R3: High Assurance
Base evidence applies (all R2 evidence + independent verification agent review, traceability matrix, explicit human sign-off, audit artifact, release decision rationale).
Embedded-Specific Additions:
- Full traceability matrix: REQ → SSR/SRS → ART → TC → Evidence mapping in ATM.md
- Independent safety assessment: Third-party safety review (ISO 26262, IEC 61508, DO-178C)
- Certification artifacts: Safety case, hazard analysis, FMEA, FTA (as applicable)
- MC/DC coverage: Modified Condition/Decision Coverage for highest safety levels (DO-178C DAL A/B)
- Code review: Independent peer review with documented findings and resolutions
- Hardware validation: HIL test results on production hardware
- Security audit: Penetration testing, secure boot validation, crypto validation (if applicable)
- Compliance sign-off: Certification authority approval (if applicable)
Halt Conditions
Halt and do not emit when:
Inherited from build-agent:
- Ambiguous REQ (requirement unclear or contradictory)
- Missing REQ link (artifact has no traceable parent requirement)
- Physical constraint violation (hardware, network, or infrastructure limits exceeded)
- Conflict with approved Blueprint (contradicts Human Gate 1 approved design)
Embedded-Specific:
- MISRA violation in safety-critical code (MISRA-C rule violation without documented deviation)
- Buffer overflow vulnerability detected (static analysis or code review identifies buffer overflow risk)
- Stack overflow risk (stack usage exceeds 80% of allocated stack size)
- Uninitialized variable (variable used before initialization)
- Memory leak detected (dynamic allocation without corresponding free)
- Missing safety analysis for critical function (safety-critical function without FMEA/FTA)
- Hardware access without proper abstraction (direct register access in application code)
- Timing constraint violation (WCET exceeds deadline)
- Missing pin assignment (GPIO/peripheral used without Logic Gatekeeper approval)
- RAM/ROM overflow (memory usage exceeds MCU limits)
Halt Protocol:
- Stop synthesis immediately
- Emit Evidence Summary with HALT condition flagged
- Present specific issue to Human (e.g., "Buffer overflow detected in sensor_read(): buffer size 64, potential write of 128 bytes")
- Wait for Human resolution (refactor, clarify REQ, approve exception)
- Resume only after Human Gate cleared
Context Engineering
Inherited from build-agent + these embedded considerations:
- Peripheral register maps: Read only the registers relevant to the current artifact, not the full MCU reference manual.
- HAL/SDK headers: Reference specific header paths rather than loading entire SDK trees.
- Hardware constraint tables: Pin maps, power budgets should be in
REQUIREMENTS.md or a referenced file -- read from disk, do not carry in conversation context.
- Vendor SDKs: Never load full SDK into context. Reference specific files (e.g.,
stm32f4xx_hal_gpio.h) as needed.
- Binary artifacts: Never load compiled binaries, hex files, or ELF files into context. Reference by path only.
- Datasheets: Extract relevant specifications (memory size, clock speed, peripheral addresses) into
REQUIREMENTS.md. Do not load full datasheets.
Pre-Execution Validation (inherited from build-agent):
Before synthesis, validate:
- Requirement coverage: Every REQ has ≥1 artifact planned
- Artifact completeness: HAL, drivers, application code, tests, build scripts
- Memory budget: Estimated RAM/ROM usage fits within MCU limits
- Scope sanity: Feature scope fits ≤50% context (split to sub-agents if needed)
- Hardware constraints: Pin assignments approved by Logic Gatekeeper
Halt if any validation fails.
Output Format
Same as build-agent: Build Manifest with ARTIFACT_ID | REQ_ID | LOCATION | NOTES.
Example Embedded Build Manifest:
BUILD_MANIFEST.md
Cycle: C1
Task: REQ-0001 - I2C sensor driver for temperature monitoring
Risk Level: R2
Generated: 2026-05-22T10:00:00Z
Target: STM32F407VG (Cortex-M4, 192KB RAM, 1MB Flash)
Toolchain: arm-none-eabi-gcc 10.3.1
ART-0001 | REQ-0001 | src/hal/i2c.c | I2C HAL; 400kHz; DMA support
ART-0002 | REQ-0001 | src/hal/i2c.h | I2C HAL interface
ART-0003 | REQ-0001 | src/drivers/temp_sensor.c | TMP102 driver; I2C address 0x48
ART-0004 | REQ-0001 | src/drivers/temp_sensor.h | TMP102 driver interface
ART-0005 | REQ-0001 | tests/unit/test_temp_sensor.c | Unit tests (5 scenarios); Unity framework
ART-0006 | REQ-0001 | tests/hil/test_i2c_comm.c | HIL test; STM32F4 Discovery board
ART-0007 | REQ-0001 | CMakeLists.txt | Build configuration; arm-none-eabi-gcc
Memory Usage: 2.4KB RAM, 8.1KB Flash (1.25% RAM, 0.81% Flash)
Static Analysis: cppcheck clean, 0 warnings
MISRA Compliance: MISRA-C:2012, 0 violations
Test Results: Unit tests 5/5 pass, HIL tests 3/3 pass
Per-file traceability header:
When to Use
Project Types:
- Firmware for MCUs (STM32, AVR, ESP32, nRF52, etc.)
- Bare-metal and RTOS-based systems (FreeRTOS, Zephyr, ThreadX)
- Device drivers and BSP code
- Safety-critical embedded (ISO 26262, IEC 61508, DO-178C, ISO 13485)
- Linux embedded (user-space drivers, daemons)
Auto-Trigger Hints (for agent routing):
File patterns:
**/*.c
**/*.h
**/*.cpp
**/*.hpp
**/Makefile
**/CMakeLists.txt
**/*.ld (linker scripts)
**/FreeRTOSConfig.h
**/startup*.c or **/startup*.s
Task keywords:
- "embedded"
- "firmware"
- "MCU"
- "microcontroller"
- "bare-metal"
- "RTOS"
- "FreeRTOS"
- "Zephyr"
- "STM32"
- "AVR"
- "ESP32"
- "ARM Cortex"
- "HAL"
- "driver"
- "BSP"
- "MISRA"
- "ISO 26262"
- "IEC 61508"
- "DO-178C"
- "safety-critical"