SDK Architecture
SDK Directory Structure
rust/
├── ameba-hal/ HAL driver layer: GPIO, I2C, SPI, UART, Timer peripheral abstractions
│ ├── src/
│ ├── ld/ Main linker script (ameba.x) and memory layout definitions
│ └── pac/ amebagreen2-pac (svd2rust-generated register access layer)
├── ameba-rom-sys/ ROM FFI binding layer: extern "C" declarations + ROM symbol linker script
│ ├── src/
│ ├── ld/ ameba_rom_symbol.x (ROM function address map)
│ └── bin/amebagreen2/ Prebuilt firmware cache (boot.bin, km4ns_image2_all.bin)
├── ameba-rt/ Runtime layer: Bootloader entry table, cortex-m-rt extension
├── ameba-wifi/ WiFi network layer: WHC IPC driver + smoltcp network stack
│ └── ld/ ameba_rom_symbol_wifi.x (WiFi ROM symbol address map)
├── examples/ Example projects (hello-world, gpio, tim, shell, wifi-connect)
├── xtask/ Build orchestration tool (cargo xtask build-amebagreen2)
├── scripts/ Helper scripts (toolchain installation, etc.)
├── doc/ SDK internal technical documentation
├── rust-toolchain.toml Pins the nightly toolchain version and cross-compilation target
└── Cargo.toml Workspace root configuration
Crate Layers
The SDK is organized into five layers from top to bottom:
Crate |
Layer |
Responsibility |
|---|---|---|
|
Network |
WHC IPC channel driver (AP ↔ NP inter-core communication) + smoltcp network stack (DHCP, TCP, UDP) |
|
HAL |
Wraps GPIO, I2C, SPI, UART, Timer, and other peripherals; implements |
|
PAC |
svd2rust-generated type-safe register access; includes |
|
FFI binding |
Raw |
|
Runtime |
Provides the Bootloader entry table and VTOR |
Build Pipeline
cargo xtask build-amebagreen2 executes three stages:
Stage |
Tool |
Output |
|---|---|---|
1 |
|
ELF firmware (with debug symbols) |
2 |
|
|
3 |
|
|
ROM FFI Mechanism
The SDK calls C functions fixed in chip ROM directly through FFI. At link time,
ameba_rom_symbol.x resolves each function name to its fixed ROM address, so a Rust call
compiles to a single branch instruction with no additional overhead.
// Declaration in ameba-rom-sys
extern "C" {
pub fn DiagPrintf(fmt: *const u8, ...) -> i32;
}
// Calling from user code (requires unsafe)
unsafe { ameba_rom_sys::DiagPrintf(b"Hello\n\0".as_ptr()); }
ameba-hal wraps ROM calls internally and exposes a safe Rust API; user code typically does
not need to use unsafe directly.