Skip to content

SPI flash driver: read JEDEC ID, memory-mapped flash reads#14

Merged
widgetii merged 3 commits intomasterfrom
feature/spi-flash-driver
Mar 31, 2026
Merged

SPI flash driver: read JEDEC ID, memory-mapped flash reads#14
widgetii merged 3 commits intomasterfrom
feature/spi-flash-driver

Conversation

@widgetii
Copy link
Copy Markdown
Member

Summary

SPI flash driver for the bare-metal agent. Initializes the HiSilicon FMC controller and enables memory-mapped flash reads.

  • FMC init: enable clock, switch to normal mode, set SPI timing, read JEDEC ID
  • Memory-mapped reads via flash window at 0x14000000
  • Data abort handler: prints fault address/DFSR/PC instead of silent hang
  • Word-aligned I/O register reads for ARM peripheral access
  • addr_readable extended for FMC, CRG, SYS_CTRL, and flash regions

Real Hardware Results (hi3516ev300, W25Q128 16MB)

Operation Speed Time
16MB flash dump 85 KB/s 3 min 16 sec
md.b baseline ~2 KB/s ~2 hours

37x faster than md.b, CRC32 verified.

Key Findings

  • FMC I/O buffer is at FLASH_MEM (0x14000000), NOT FMC_BASE + 0x100 on real hardware
  • I/O registers require 32-bit word-aligned access (ldrb → data abort)
  • FMC_CFG bootrom value (0x1820) must be preserved when switching modes
  • Abort handler needs SVC mode switch (ABT mode stack uninitialized)

Test plan

  • All CI checks pass locally
  • Real hardware: JEDEC ID ef4018 (W25Q128, 16MB)
  • 4KB flash read + CRC32 verified
  • 64KB flash read at 72 KB/s (921600 baud)
  • Full 16MB dump: 85 KB/s, 3m16s, CRC32 match
  • CI on PR

🤖 Generated with Claude Code

widgetii and others added 3 commits March 31, 2026 14:33
Data abort handler in startup.S prints fault address, DFSR, and PC
over UART instead of silent hang. Switches to SVC mode for valid
stack before calling C handler.

handle_read uses 32-bit word-aligned access for I/O register regions
(0x10000000-0x13000000) since ARM peripherals require word access.

Tested on hi3516ev300: FMC CRG=0x02 (clock on), VERSION=0x100,
CFG=0x1820 (boot mode, SPI NOR). All registers accessible.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Flash controller (FMC) initialization:
- Enable clock via CRG register
- Switch to normal mode (preserve bootrom config bits)
- Set SPI timing parameters
- Read JEDEC ID via register-mode command

Key fix: FMC I/O buffer is at FLASH_MEM (0x14000000) not FMC_BASE+0x100
on real hardware. U-Boot reads from host->iobase which maps here.

Also: data abort handler prints fault address/DFSR/PC over UART.
Word-aligned 32-bit I/O register reads prevent data aborts.
addr_readable extended for CRG, FMC, SYS_CTRL, and flash regions.

Tested on hi3516ev300: JEDEC ef4018 (W25Q128, 16MB), 4KB flash read
with CRC32 verified, 64KB at 72 KB/s via auto-baud 921600.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
In normal mode, FLASH_MEM window shows the FMC I/O buffer (JEDEC ID
data). In boot mode, it transparently reads flash content. Must switch
back to boot mode after register-mode commands for correct reads.

Verified: binwalk finds U-Boot + XZ kernel/rootfs in dump. First bytes
are ARM branch instruction (bootrom entry), not JEDEC ID.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@widgetii widgetii merged commit 951c89d into master Mar 31, 2026
13 checks passed
@widgetii widgetii deleted the feature/spi-flash-driver branch March 31, 2026 11:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant