🌙 ☀️

spi_flash Driver Documentationv0.1.0


Table of Contents

  1. Overview
  2. Project Structure
  3. Public API Reference
  4. Usage Example
  5. Communication Flow

1. Overview

spi_flash is a no_std compatible SPI flash driver designed primarily for Winbond W25Q series and similar NOR flash memory devices. It provides a clean, safe, and efficient API for interacting with SPI flash memory in embedded Rust applications.

Key Features

2. Project Structure

The library is organized into several modules to separate concerns and maintain clean architecture.

Module Description
device Device-specific logic (manufacturer detection, status registers, etc.)
error Error types for the library
interface Trait definitions for SPI interface, CS pin, and delay
misc Miscellaneous utility functions (address conversions, etc.)
mock Mock implementations for testing (only available when "std" feature is enabled)
types Type definitions for commands, status enums, and sizes

3. Public API Reference

This section provides a detailed, man-page style documentation for the core SpiFlash driver. All operations are safe and block until completion (or until an error is encountered).

Initialization & Setup

Signature pub fn new(spi: SPI, cs: CS, timer: Timer) -> Result<Self, SpiFlashError>
Description Constructs a new SpiFlash instance and initializes communication with the device. This function automatically issues a JEDEC ID command to detect the flash manufacturer, memory type, size, and computes the internal page, sector, and block counts.
Arguments
  • spi: An object implementing the SpiInterface trait.
  • cs: An object implementing the CsPin trait for chip select control.
  • timer: An object implementing the Delay trait for blocking operations.

Device Information

These methods return information about the detected device properties. They do not initiate SPI transactions and are virtually instantaneous.

Method Signature Description
manufacturer fn manufacturer(&self) -> Manufacturer Returns the detected flash manufacturer (e.g., Winbond, Macronix).
size fn size(&self) -> Size Returns the capacity size of the device (e.g., Mbit1, Mbit256).
memory_type fn memory_type(&self) -> u8 Returns the specific memory type identifier returned by the JEDEC ID query.
page_count fn page_count(&self) -> u32 Total number of 256-byte pages in the device.
sector_count fn sector_count(&self) -> u32 Total number of 4KB sectors in the device.
block_count fn block_count(&self) -> u32 Total number of 64KB blocks in the device.

Read Operations

Read functions are bounded by the internal flash structures. Attempting to read beyond the boundary of the specified unit (page/sector/block) using an offset will return a SpiFlashError::Protocol.

Signature pub fn read_page(&mut self, page_number: u32, data: &mut [u8], size: u32, offset: u32) -> Result<(), SpiFlashError>
pub fn read_sector(&mut self, sector_number: u32, data: &mut [u8], size: u32, offset: u32) -> Result<(), SpiFlashError>
pub fn read_block(&mut self, block_number: u32, data: &mut [u8], size: u32, offset: u32) -> Result<(), SpiFlashError>
Description Reads a sequence of bytes from a specific page, sector, or block, bounded by the unit's size limit.
Arguments
  • number: The 0-indexed index of the unit.
  • data: The mutable buffer to store the retrieved data.
  • size: The exact number of bytes to read into the buffer.
  • offset: The starting offset inside the specific unit to read from. Must be less than the unit's total size (e.g., < 256 for page).

Write Operations

Before writing, ensure that the target region has been erased. Flash memory can only be written from 1 to 0; a 0 cannot be written back to a 1 without an erase cycle. The driver handles cross-page boundary logic internally for higher-level writes.

Address Write pub fn write_address(&mut self, address: u32, data: &[u8], size: u32) -> Result<(), SpiFlashError>
Writes data sequentially starting from an absolute byte address. Automatically fragments the operation across page boundaries as required by the flash controller.
Unit Writes pub fn write_page(&mut self, page_number: u32, data: &[u8], size: u32, offset: u32) -> Result<(), SpiFlashError>
pub fn write_sector(&mut self, sector_number: u32, data: &[u8], size: u32, offset: u32) -> Result<(), SpiFlashError>
pub fn write_block(&mut self, block_number: u32, data: &[u8], size: u32, offset: u32) -> Result<(), SpiFlashError>
Writes data into a specific unit, bounded by the maximum capacity of that unit minus the starting offset.

Erase Operations

Erasing resets all bits in the targeted region to 1 (0xFF). Erase operations are typically much slower than read or write operations. The driver will actively block until the internal erase cycle is fully completed by polling the status register.

erase_chip pub fn erase_chip(&mut self) -> Result<(), SpiFlashError>
Erases the entire flash device. Can take several seconds on large chips.
erase_sector pub fn erase_sector(&mut self, sector_number: u32) -> Result<(), SpiFlashError>
Erases a specific 4KB sector.
erase_block pub fn erase_block(&mut self, block_number: u32) -> Result<(), SpiFlashError>
Erases a specific 64KB block.

4. Usage Example

Add this as a dependency in your Cargo.toml:

[dependencies]
spi_flash = { path = "path/to/spi_flash" }

Example of initializing and reading a page:

// Initialize your SPI bus, Chip Select pin, and Delay provider
// let spi = ...;
// let cs = ...;
// let delay = ...;

let mut flash = SpiFlash::new(spi, cs, delay).unwrap();

// Read device info
let mfg = flash.manufacturer();
let size = flash.size();

// Read a page from address 0x000000
let mut buffer = [0u8; 256];
flash.read_page(0x000000, &mut buffer).unwrap();

5. Communication Flow

The standard flow for interacting with the SPI flash memory involves asserting the Chip Select (CS) pin, sending a command byte, sending any required address bytes or dummy bytes, transferring data, and finally deasserting CS.

sequenceDiagram participant Host participant SPI Flash Host->>SPI Flash: Assert CS (Low) Host->>SPI Flash: Send Command Byte (e.g., 0x03 for Read) Host->>SPI Flash: Send 24-bit Address SPI Flash-->>Host: Stream Data out on MISO Host->>SPI Flash: Deassert CS (High)