Skip to content

Hardware QSPI flash controller#936

Open
0xa000 wants to merge 15 commits into
MEGA65:developmentfrom
0xa000:new-qspi-controller
Open

Hardware QSPI flash controller#936
0xa000 wants to merge 15 commits into
MEGA65:developmentfrom
0xa000:new-qspi-controller

Conversation

@0xa000
Copy link
Copy Markdown
Contributor

@0xa000 0xa000 commented May 14, 2026

This pull request contains a hardware QSPI controller implementation that aims to replace the current mixed hardware/software implementation.

Currently, the QSPI flash is partly controlled from hardware (several commands in the sdcardio state machine), and partly from software (see the megaflash source directory). This works, but the space available for megaflash is pretty tight, and several variants of megaflash need to be built for the different targets / boards.

This PR introduces a hardware QSPI controller that handles all interactions with the QSPI flash. The QPSI flash controller is no longer part of sdcardio, which simplifies the state machine there. Also, the shared BRAM has been pulled out of sdcardio as a separate component.

The Makefile and vivado *_gen files were updated accordingly (build only a single megaflash variant, add the correct QSPI flash controller VHDL implementation according to the target/board).

0xa000 and others added 15 commits March 26, 2026 19:43
Renumbering was needed to avoid non-QSPI action $57.
Remove the $D6CD/$D6CE size registers; the transfer size is now fixed at
512 bytes in the VHDL and the C driver. Move the status register from
$D6CC to $D6C1 so the three registers occupy the contiguous range
$D6C1-$D6C3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- sdcardio: add $D6C1 to fastio read pass-through (was missing, causing
  busy-wait to never spin and all operations to appear instant); remove
  stale $D6CC/$D6CD/$D6CE entries from read and write paths; reorder
  cases to be in address order.
- $D6C1 status register: remove busy bit (poll $D680 bit 0 instead);
  remove block_mismatch bit; shift remaining bits down to bit 0=error,
  bit 1=initialization error, bit 2=internal fault.
- Replace REJECTED state with ERROR_IDLE, ERROR_UNINITIALIZED, and
  ERROR_INTERNAL_ERROR, isolating all dev_error assignments to these
  dedicated states. Strobe-while-busy now silently ignored.
- Verify mismatch now redirects post_transaction_state to ERROR_IDLE,
  closing the QSPI bus cleanly before reporting the error.
- C driver: busy polls moved to $D680 & 0x01; error checks unified to
  $D6C1 & 0x01. Applied to both s25flxxxs and s25flxxxl controllers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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