Embedded Systems
Draft supports bare-metal and RTOS-based embedded development with no runtime overhead.
Overview
Section titled “Overview”Draft’s no-GC, no-runtime design makes it ideal for resource-constrained environments.
Supported Platforms
Section titled “Supported Platforms”| Platform | Architecture | Min RAM | Min Flash |
|---|---|---|---|
| ARM Cortex-M | ARMv6-M/7-M/8-M | 4 KB | 16 KB |
| RISC-V | RV32IMAC | 4 KB | 16 KB |
| AVR | ATmega/ATtiny | 1 KB | 8 KB |
| ESP32 | Xtensa | 32 KB | 128 KB |
| nRF52 | ARM Cortex-M4 | 8 KB | 32 KB |
Getting Started
Section titled “Getting Started”Install Embedded Target
Section titled “Install Embedded Target”draft target add arm-none-eabidraft target add riscv32-unknown-noneCreate Embedded Project
Section titled “Create Embedded Project”draft new my-embedded --template embeddedcd my-embeddedProject structure:
my-embedded/├── draft.toml├── memory.x # Linker script├── Cargo.toml # (for HAL dependencies)└── src/ ├── main.draft └── interrupts.draftConfiguration
Section titled “Configuration”draft.toml
Section titled “draft.toml”[package]name = "my-embedded"version = "0.1.0"
[target.thumbv7em-none-eabihf]runner = "probe-run --chip STM32F407VG"
[profile.release]opt-level = "s" # Optimize for sizelto = true # Link-time optimizationDigital Output
Section titled “Digital Output”import gpio
action main() @led = @gpio#Pin::new(13) @led#mode(@gpio#OUTPUT)
while true @led#high() @time#sleep(milliseconds(500)) @led#low() @time#sleep(milliseconds(500)) fin while.fin action.Digital Input
Section titled “Digital Input”import gpio
action main() @button = @gpio#Pin::new(0) @button#mode(@gpio#INPUT) @button#pull(@gpio#PULL_UP)
while true if @button#read() == @gpio#LOW handle_press() fin if. @time#sleep(milliseconds(10)) fin while.fin action.import gpio
action main() @pwm = @gpio#PWM::new(18) @pwm#frequency(1000) @// 1 kHz
for @duty in 0..100 @pwm#duty(@duty) @time#sleep(milliseconds(20)) fin for.fin action.Analog
Section titled “Analog”ADC (Analog Input)
Section titled “ADC (Analog Input)”import adc
action main() @sensor = @adc#Channel::new(0) @sensor#resolution(12) @// 12-bit
while true @value = @sensor#read() @voltage = @value * 3.3 / 4095 @time#sleep(milliseconds(100)) fin while.fin action.DAC (Analog Output)
Section titled “DAC (Analog Output)”import dac
action main() @dac = @dac#Channel::new(1)
for @value in 0..4095 @dac#write(@value) @time#sleep(milliseconds(1)) fin for.fin action.Communication Protocols
Section titled “Communication Protocols”UART/Serial
Section titled “UART/Serial”import uart
action main() @serial = @uart#UART::new(0) @serial#baud(115200) @serial#tx_pin(0) @serial#rx_pin(1)
@serial#write("Hello, World!\r\n")
while true if @serial#available() > 0 @data = @serial#read() @serial#write(@data) @// Echo fin if. fin while.fin action.import i2c
action main() @bus = @i2c#I2C::new(0) @bus#sda_pin(4) @bus#scl_pin(5) @bus#frequency(400000) @// 400 kHz
@address = 0x68 @// MPU6050
@// Read WHO_AM_I register @whoami = @bus#read_register(@address, 0x75) @io#write_line("WHO_AM_I: " + string(@whoami))
@// Read accelerometer data @data = @bus#read_registers(@address, 0x3B, 6)fin action.import spi
action main() @bus = @spi#SPI::new(0) @bus#sck_pin(2) @bus#mosi_pin(3) @bus#miso_pin(4) @bus#frequency(1000000) @// 1 MHz
@cs = @gpio#Pin::new(5) @cs#mode(@gpio#OUTPUT) @cs#high()
@// Read device ID @cs#low() @bus#transfer([0x9F]) @id = @bus#transfer([0x00, 0x00, 0x00]) @cs#high()fin action.CAN Bus
Section titled “CAN Bus”import can
action main() @bus = @can#CAN::new(0) @bus#baud(500000) @// 500 kbps @bus#tx_pin(0) @bus#rx_pin(1)
@msg = @can#Message::new(0x123) @msg#data([0x01, 0x02, 0x03, 0x04]) @bus#send(@msg)
while true @received = @bus#receive() if @received != nil process_message(@received) fin if. fin while.fin action.Timers
Section titled “Timers”Hardware Timer
Section titled “Hardware Timer”import timer
action main() @timer = @timer#Timer::new(0) @timer#frequency(1000) @// 1 kHz @timer#callback(fn() => toggle_led() fin action.) @timer#start()fin action.Watchdog
Section titled “Watchdog”import watchdog
action main() @wd = @watchdog#Watchdog::new() @wd#timeout(seconds(1)) @wd#start()
while true @// Do work... @wd#pet() fin while.fin action.Interrupts
Section titled “Interrupts”import gpioimport interrupts
action main() @button = @gpio#Pin::new(0) @button#mode(@gpio#INPUT)
@interrupts#enable(@button, @interrupts#EDGE_FALLING, fn() => handle_button_press() fin action.)
while true @// Low power wait @power#wait_for_interrupt() fin while.fin action.Low Power Modes
Section titled “Low Power Modes”import power
action main() while true @// Do work... @sensor_data = read_sensor() @radio#send(@sensor_data)
@// Sleep for 10 seconds @power#sleep(seconds(10)) fin while.fin action.Deep Sleep with Wake
Section titled “Deep Sleep with Wake”import powerimport gpio
action main() @wake_pin = @gpio#Pin::new(0) @wake_pin#mode(@gpio#INPUT) @wake_pin#wake_on(@gpio#EDGE_RISING)
while true @// Enter deep sleep @power#deep_sleep()
@// Woken up by interrupt handle_event() fin while.fin action.Memory Management
Section titled “Memory Management”Static Allocation
Section titled “Static Allocation”@// Statically allocated buffer@buffer: [Byte; 1024]
action main() for @i in 0..1024 @buffer[@i] = 0 fin for.fin action.Stack Allocation
Section titled “Stack Allocation”action process() @// Allocated on stack @data: [Byte; 256] @// ...fin action.No Heap
Section titled “No Heap”By default, Draft embedded targets have no heap. All allocation is static or stack-based.
RTOS Integration
Section titled “RTOS Integration”FreeRTOS
Section titled “FreeRTOS”import freertos
action main() @rtos = @freertos#RTOS::new()
@rtos#task("blink", fn() => while true toggle_led() @rtos#delay(milliseconds(500)) fin while. fin action.)
@rtos#task("read_sensor", fn() => while true @value = read_sensor() @rtos#queue_send("sensor_data", @value) @rtos#delay(milliseconds(100)) fin while. fin action.)
@rtos#start()fin action.Debugging
Section titled “Debugging”Semihosting
Section titled “Semihosting”draft run --target thumbv7em-none-eabihf --semihostingSWO Trace
Section titled “SWO Trace”draft debug --swodraft debug --gdbFlashing
Section titled “Flashing”@// Flash to devicedraft flash --target thumbv7em-none-eabihf
@// Flash with probedraft flash --probe cmsis-dap
@// Flash and rundraft run --target thumbv7em-none-eabihfSize Optimization
Section titled “Size Optimization”[profile.release]opt-level = "z" # Optimize for size aggressivelylto = truepanic = "abort"Typical sizes:
| Application | Flash | RAM |
|---|---|---|
| Blink LED | 2 KB | 256 B |
| Sensor reader | 8 KB | 1 KB |
| Full stack | 32 KB | 8 KB |
