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>
108 lines
4.8 KiB
Markdown
108 lines
4.8 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
# 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_std` only**: No heap allocation. Fixed-size arrays and stack-only data structures.
|
|
- **`embedded-hal` generics**: All hardware drivers must be generic over `embedded_hal::i2c::I2c` (1.0 traits). Never use concrete HAL types in driver code.
|
|
- **LedController trait**: LED controllers implement the `LedController` trait defined in `src/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 with `From<E>` impl (see LP5562 driver pattern).
|
|
- **Register addresses**: Place in a `reg` submodule as `pub const` values.
|
|
- **`const fn`**: Prefer `const fn` where possible (see `EngineCommand` builder 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↔I2C
|
|
- `CONFIG_1_SRAM_ENABLE = 1 << 1` — Enable SRAM access
|
|
- `CONFIG_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`), reference `main.rs` boot sequence
|
|
- `../ntag5sensor/` — NTAG5Link command reference (`vicinity/ntag5link.py`), I2C patterns (`vicinity/i2cbase.py`)
|