Embedded Ecosystem (std.embedded)
Flame’s embedded hardware ecosystem (std.embedded) represents a paradigm shift in firmware engineering. Unlike traditional C++ Arduino libraries or raw microcontroller registers, Flame delivers both a platform-independent hardware abstraction layer (HAL) and a zero-cost bare-metal hardware transpiler backed by Rust’s industry-standard embedded-hal and arduino-hal architecture.
Write one hardware program, and execute or burn firmware without modification to:
- Atmel AVR & Arduino Uno/Mega/Nano (
arduino-hal,avr-hal,atmega328p) - Espressif ESP32 & ESP8266 (
esp-hal/esp-idf) - ARM Cortex-M & STM32 (
stm32-hal) - Raspberry Pi RP2040 (
rp2040-hal) - Linux GPIO / Edge Robotics (
rppal/ Userland HAL)
Bare-Metal Hardware Compilation (@Embedded)
Section titled “Bare-Metal Hardware Compilation (@Embedded)”When deploying firmware directly to physical microcontrollers (such as an Arduino Uno, ESP32, or STM32 chip), traditional embedded developers use a manual two-stage design consisting of void setup() and an infinite void loop().
Flame automates this workflow cleanly using the @Embedded architectural decorator. Functions annotated with @Embedded act as continuous hardware execution loops, while declarations above them automatically compile into hardware peripheral setups.
import std.embeddedimport std.thread
// Hardware capabilities initialize once during system bootlet led = embedded.pin(13)let button = embedded.pin(2)
// @Embedded designates the infinite real-time microcontroller hardware loop@Embedded(target = "arduino-uno", baud = 115200)fn firmware_loop() { led.mode("OUTPUT") button.mode("INPUT_PULLUP")
// Read logic level from pushbutton if button.read() == 0 { print("[UART] Button active - Toggling LED HIGH") led.high() } else { led.low() } thread.sleep(100)}Hardware Toolchain & CLI Commands
Section titled “Hardware Toolchain & CLI Commands”Flame provides native subcommand integration for compiling, burning, and inspecting physical microcontrollers:
1. Build Zero-Cost Bare-Metal Firmware
Section titled “1. Build Zero-Cost Bare-Metal Firmware”When you execute flame build, the compiler detects @Embedded(target = "...") in your code (or inspects flame.toml / --target) and directly transpiles your Flame AST into a freestanding #![no_std] Rust binary, generating production-grade .elf and .hex machine firmware:
flame build --target arduino-uno2. Burn Firmware to Hardware Device (flame flash)
Section titled “2. Burn Firmware to Hardware Device (flame flash)”Builds and directly burns the generated machine code onto connected hardware chips over serial or debugging programmers (invoking avrdude, espflash, or probe-rs automatically):
flame flash --port COM3# Or equivalently using the unified run workflow:flame run --device3. Connect to Serial UART Monitor (flame monitor)
Section titled “3. Connect to Serial UART Monitor (flame monitor)”Opens an interactive, low-latency UART telemetry session with your connected board to stream print statements and debug metrics:
flame monitor --port COM3 --baud 115200Core Architecture & Design Principles
Section titled “Core Architecture & Design Principles”Flame’s embedded architecture is governed by five fundamental engineering rules:
- Everything is a Capability Object: No unsafe global functions like
digitalWrite(13, HIGH). Instead, hardware pins and peripherals are constructed as independent capability objects with strong methods:let led = embedded.pin(13). - Resource Ownership: Pins and bus lines cannot be accidentally double-allocated. Once
pin(13)is constructed, ownership rules guard against conflicting directional modes. - Platform-Independent Signatures: Calling
.angle(120)on a servo works identically across AVR hardware PWM timers and Linux userland drivers. - Clean Scope & Zero Boilerplate: Write execution logic directly without mandatory C-style
void setup()andvoid loop()ceremonies. - No Redundancy: Traditional computer networking (
WiFi,Ethernet,MQTT,HTTP) lives natively in Flame’s general networking standard library rather than polluting the bare-metal microcontroller module.
Digital GPIO & Analog ADCs
Section titled “Digital GPIO & Analog ADCs”GPIO Capability Pin (embedded.pin)
Section titled “GPIO Capability Pin (embedded.pin)”Digital pins govern logical state signals (3.3V / 5V vs 0.0V).
import std.embedded
let led = embedded.pin(13)let sensor_pin = embedded.pin(2)
// Configure bidirectional mode ("OUTPUT", "INPUT", or "INPUT_PULLUP")led.mode("OUTPUT")sensor_pin.mode("INPUT")
// Assert digital logic levelsled.high()led.low()led.toggle()
// Read logic level as integer boolean (1 or 0)let state = sensor_pin.read()println($"Pin 2 level is: {state}")Analog-to-Digital Converter (embedded.analog)
Section titled “Analog-to-Digital Converter (embedded.analog)”Read continuous environmental sensor voltages with 12-bit binary conversion resolutions:
import std.embedded
let pot = embedded.analog(0)
// Sample raw ADC binary word (0 - 4095 on 12-bit DACs)let raw = pot.read()
// Read calibrated voltage directlylet voltage = pot.readVoltage()
// Sample ratio as 0.0% to 100.0%let percent = pot.readPercent()println($"Potentiometer dial at {percent}% ({voltage}V)")Actuators & Robotics Control
Section titled “Actuators & Robotics Control”Hobby Servo Motors (embedded.servo)
Section titled “Hobby Servo Motors (embedded.servo)”Control precise robotic joint rotations via pulse-width horn signaling:
import std.embedded
let arm = embedded.servo(5)
// Set absolute target rotation angle in degrees (0 - 180)arm.angle(90)
// Smoothly sweep anglearm.rotate(135)H-Bridge DC Motor Driver (embedded.motor)
Section titled “H-Bridge DC Motor Driver (embedded.motor)”Drive standard dual-channel DC motors and robotic wheels using Direction, Brake, and PWM speed pins:
import std.embedded
// Define H-Bridge Pin Mapping: (PWM_PIN, DIR_PIN_A, DIR_PIN_B)let left_wheel = embedded.motor(9, 7, 8)
// Set directional polarizationleft_wheel.forward()
// Set throttle output as percentage of full system bus voltageleft_wheel.speed(75.5)
// Coast or electro-dynamically brake motor shaft to haltleft_wheel.stop()Buses & Displays
Section titled “Buses & Displays”I2C / SPI OLED Framebuffer (embedded.display)
Section titled “I2C / SPI OLED Framebuffer (embedded.display)”Directly render geometric glyphs and monitoring dashboards onto SPI/I2C graphic matrices (SSD1306, SH1106, TFT displays):
import std.embedded
let oled = embedded.displayoled.clear()oled.text("Flame OS Telemetry")oled.text("Battery: 99.4%")Synchronous I2C & SPI Bus Transactions
Section titled “Synchronous I2C & SPI Bus Transactions”Transact directly with custom registers over 2-wire (I2C) or 4-wire (SPI) protocols:
import std.embedded
let bus = embedded.i2c(0x68) // Target MPU-6050 Accelerometerbus.write([0x6B, 0x00]) // Wake device from sleeping low-power register
let spi_dac = embedded.spi()spi_dac.transfer([0x01, 0xFF])Complete API Reference
Section titled “Complete API Reference”| Constructor / Method | Capability Object | Primary Methods & Properties |
|---|---|---|
embedded.pin(num: Int) |
GPIO Pin | .mode("INPUT"/"OUTPUT"/"INPUT_PULLUP"), .high(), .low(), .toggle(), .read() |
embedded.analog(pin: Int) |
ADC Channel | .read(), .readVoltage(), .readPercent() |
embedded.pwm(pin: Int) |
PWM Driver | .write(duty: Float), .enable(), .disable() |
embedded.servo(pin: Int) |
Servo Actuator | .angle(deg: Int), .rotate(deg: Int), .stop() |
embedded.motor(pwm, d1, d2) |
DC Motor Driver | .forward(), .reverse(), .speed(pct: Float), .stop() |
embedded.i2c(addr: Int) |
I2C Slave Bus | .write(bytes: Array), .scan() |
embedded.spi() |
SPI Master Bus | .transfer(bytes: Array) |
embedded.can(baud: Int) |
CAN Bus Network | .send(frame: Formula) |
embedded.display |
OLED / TFT Screen | .clear(), .text(content: String) |
embedded.diffDrive(m1, m2) |
Rover Kinematics | .forward(), .rotate(deg: Int), .stop() |
embedded.board |
System Metadata | Properties: .arch, .cpu, .os, .memory |
embedded.flash |
Non-Volatile ROM | .write(addr: Int, val: Int), .read(addr: Int) |
embedded.watchdog |
Watchdog Timer | .feed() |
