spi
An emulator-focused SPI host controller implementation in Rust.
This crate provides a cycle-accurate SPI host controller (SpiHost) and a trait (SpiDevice) for attaching peripheral devices. It is designed for use in hardware emulators where you need to emulate SPI communication between a CPU and one or more peripherals.
Features
- All four SPI modes (CPOL/CPHA combinations)
- MSB-first and LSB-first transfer endianness
- Up to 8 simultaneously attached devices with chip-select per device
- System clock and external clock inputs
- Fast transfer mode (FRX) for back-to-back transfers
- Interrupt support (transmission complete)
- Tristate MOSI support
- Software reset via control register
SpiDeviceblanket impls forBox<dyn SpiDevice>,RefCell<T>, andRc<RefCell<T>>
Usage
Add to your Cargo.toml:
[]
= "0.1"
Implementing a device
use SpiDevice;
Wiring up the host controller
use SpiHost;
let mut host = new;
// Attach a device; save the returned ID to remove it later
let id = host.add_device.unwrap;
// In your CPU read/write handlers (4 registers, address bits [1:0]):
// reg 0 — data (read: RX byte, write: TX byte)
// reg 1 — control/status
// reg 2/3 — device select bitmask (one bit per device)
host.write; // software reset
host.write; // select device 0
host.write; // begin transfer of 0xAB
// Drive the system clock from your emulator's clock source
host.sys_clock;
host.sys_clock;
// ... repeat until transfer completes (STS_TC set in status register)
let rx = host.read; // read received byte
// Optionally check for interrupt
if host.int
Register map
| Addr (bits [1:0]) | Read | Write |
|---|---|---|
| 0 | RX data byte | TX data byte (starts transfer) |
| 1 | Status register | Control register |
| 2–3 | Device select bitmask | Device select bitmask |
Control register bits (write to reg 1):
| Bit | Name | Description |
|---|---|---|
| 7 | SR | Software reset (self-clearing) |
| 6 | END | Endianness: 1 = MSB-first, 0 = LSB-first |
| 5 | IER | Interrupt enable |
| 4 | FRX | Fast transfer: auto-reload TX from RX on data read |
| 3 | TMO | Tristate MOSI (output 0 regardless of data) |
| 2 | ECE | External clock enable |
| 1 | CPOL | Clock polarity |
| 0 | CPHA | Clock phase |
Status register bits (read from reg 1):
| Bit | Name | Description |
|---|---|---|
| 7 | TC | Transmission complete |
| 6 | BSY | Transfer in progress |
| 5–0 | — | Mirror of control register bits 5–0 |
Clock modes
All four standard SPI modes are supported via CPOL and CPHA:
| Mode | CPOL | CPHA | Clock idle | Sample edge |
|---|---|---|---|---|
| 0 | 0 | 0 | Low | Rising |
| 1 | 0 | 1 | Low | Falling |
| 2 | 1 | 0 | High | Falling |
| 3 | 1 | 1 | High | Rising |
License
Licensed under your choice of MIT or Apache-2.0.