Set up Rust embedded project targeting SAMD21 (thumbv6m-none-eabi) with XIAO M0 BSP for dev board prototyping. Includes LP5562 EN pin control on D0/A0, project documentation (README, CLAUDE.md), phased status tracker, and detailed development plan covering LP5562 driver integration, NTAG5Link I2C driver, pattern storage format, power management, NFC communication protocol, recovery mode, and firmware update strategy. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.8 KiB
4.8 KiB
xblink Development Guide
Embedded Rust firmware for a battery-free, NFC-powered LED implant. The NTAG5Link harvests energy from an NFC field and provides EEPROM storage for LED patterns. A SAMD21E MCU reads patterns from EEPROM, programs LP5562 execution engines, then sleeps while the LP5562 autonomously drives RGBW LEDs.
Build Commands
# Build release firmware
cargo build --release
# Flash via UF2 bootloader (XIAO M0: double-tap RST to enter bootloader)
cargo hf2 --release
Target
- Architecture:
thumbv6m-none-eabi(ARM Cortex-M0+) - Dev board: Seeed XIAO M0 (SAMD21G18A) — will port to bare SAMD21E18A later
- LED driver: LP5562EVM (TI evaluation module, RGBW, I2C addr 0x30)
- NFC: NTAG5Link Click board (MikroElektronika)
Dependencies
| Crate | Version | Purpose |
|---|---|---|
xiao_m0 |
0.13 | Board support package (dev board phase) |
panic-halt |
0.2 | Minimal panic handler for no_std |
cortex-m |
0.7 | Cortex-M runtime, critical-section-single-core feature |
embedded-hal |
1.0.0 | Hardware abstraction traits (I2C, GPIO, delay) |
When porting to bare SAMD21E: replace xiao_m0 with atsamd-hal = { version = "0.17", features = ["samd21e"] } and add cortex-m-rt = "0.7".
Project Structure
src/
main.rs # Entry point: boot, pattern load, sleep/wake loop
led/
mod.rs # LedController trait + re-exports
lp5562.rs # LP5562 driver (from ../ntag5-samd21-lp562/)
simple_pwm.rs # Single-color LED driver (GPIO PWM)
ntag5/
mod.rs # NTAG5Link I2C slave driver (MCU-side)
registers.rs # Register map and config constants
eeprom.rs # EEPROM read/write
sram.rs # SRAM mailbox for NFC pass-through
pattern/
mod.rs # Pattern format, parser, serializer
engine.rs # LP5562 engine program builder from patterns
Architecture Conventions
no_stdonly: No heap allocation. Fixed-size arrays and stack-only data structures.embedded-halgenerics: All hardware drivers must be generic overembedded_hal::i2c::I2c(1.0 traits). Never use concrete HAL types in driver code.- LedController trait: LED controllers implement the
LedControllertrait defined insrc/led/mod.rs. This enables modular support for LP5562, single-color PWM, and future LED driver ICs. - Error types: Use
Error<E>enum wrapping underlying I2C error withFrom<E>impl (see LP5562 driver pattern). - Register addresses: Place in a
regsubmodule aspub constvalues. const fn: Preferconst fnwhere possible (seeEngineCommandbuilder in LP5562 driver).- No
unsafe: Avoid unless absolutely necessary for hardware access.
Key I2C Addresses
| Device | Address | Notes |
|---|---|---|
| LP5562 | 0x30 | ADDR_SEL pins both low (LP5562EVM default) |
| NTAG5Link | 0x54 | Default NTP53x2 I2C slave address |
NTAG5Link I2C Register Map (MCU-side)
The MCU accesses NTAG5Link as a standard I2C slave — plain register read/write, NOT the NFC-side ISO15693 custom commands used by the Python ntag5sensor tooling.
| Region | Address Range | Size | Notes |
|---|---|---|---|
| Session registers | 0x00-0x06 | 7 bytes | Volatile, runtime config |
| Configuration | 0x37-0x3F | Varies | Persistent, EEPROM-backed |
| EH config | 0x3D | 1 byte | Energy harvesting voltage/current |
| SRAM | 0xF8-0xFF | 256 bytes | 64 x 4-byte blocks, volatile |
| EEPROM user memory | blocks 0x00-0x1FF | 2048 bytes | 512 x 4-byte blocks |
Key config constants (from ../ntag5sensor/vicinity/ntag5link.py):
CONFIG_1_USE_CASE_CONF_I2C_SLAVE = 0 << 4— NTAG5 as I2C slave (our mode)CONFIG_1_ARBITER_MODE_SRAM_PASSTHROUGH = 2 << 2— SRAM pass-through for NFC↔I2CCONFIG_1_SRAM_ENABLE = 1 << 1— Enable SRAM accessCONFIG_0_EH_MODE_LOW_FIELD_STRENGTH = 2 << 2— EH mode for phone NFC
Hardware Wiring (Dev Board)
| XIAO Pin | Connection | Function |
|---|---|---|
| A4 (SDA) | LP5562 SDA, NTAG5 SDA | Shared I2C data |
| A5 (SCL) | LP5562 SCL, NTAG5 SCL | Shared I2C clock |
| D0/A0 | LP5562 EN | Hardware enable (GPIO, active high) |
| TBD | NTAG5 FD pin | Field detect / SRAM write indication (EIC wake) |
| TBD | Hall sensor | Recovery mode trigger (EIC wake) |
Testing
- Hardware: XIAO M0 + LP5562EVM + NTAG5Link Click (when jumpers available)
- PCSC reader: Use
../ntag5sensor/Python tooling with ACR1552 reader - Phone NFC: VivoKey RawNFC app for SRAM mailbox testing
- Phone app: DT NFC Identifier for basic tag info
Sibling Projects
../ntag5-samd21-lp562/— LP5562 driver source (src/lp5562.rs), referencemain.rsboot sequence../ntag5sensor/— NTAG5Link command reference (vicinity/ntag5link.py), I2C patterns (vicinity/i2cbase.py)