H753_CPP_W25Q_QSPI_Flash_Read_Write_01 1.0
STM32H753 W25Q QSPI flash (Adafruit 5632/5633/5634) read/write tutorial
Loading...
Searching...
No Matches
H753 W25Q QSPI Flash Read/Write

A bare-metal (no RTOS) C++ firmware for an STM32H753ZI that drives a Winbond W25Q-series NOR flash chip (Adafruit 5632/5633/5634 QSPI DIP breakout boards – W25Q16/W25Q64/W25Q128) over the STM32's dedicated QUADSPI peripheral, with a from-scratch driver class matching the public API shape of the companion SPI project's driver.

Status: written, not yet hardware-validated. The driver code, C/C++ bridge, and demo path are complete and compile, but this project has not yet been run on real hardware – the QUADSPI clock prescaler is still CubeMX's very conservative default (255), and no validation suite run has confirmed a working clock speed the way the companion SPI project's did. Treat the current clock setting as a starting point for hardware testing, not a validated value.

How it works

After clock and peripheral init, the normal (non-validation) demo path:

  1. Reads the chip's JEDEC ID and prints it (manufacturer + memory type + capacity bytes) – proves basic communication before attempting anything destructive.
  2. Erases the first 4KB sector.
  3. Writes a short message into that sector.
  4. Reads the message back and compares it byte-for-byte against what was written, printing whether the round trip matched.

A separate, opt-in destructive validation suite (W25Q_VALIDATION_TEST_ENABLE in main.c) runs instead of the demo when enabled: an erased-state check, a small read/write round trip, a 20-pattern stuck-at/bit-coupling sweep, and a page-boundary write test exercising the driver's internal page-splitting. Running this suite – not just a light JEDEC-ID spot-check – is exactly how the companion SPI project's clock speed was actually validated, and is the recommended first step once this project is on real hardware.

Hardware

Peripheral Interface Pins Notes
W25Q flash (Adafruit breakout) QUADSPI (Bank 1) PF10 (CLK) / PF8 (IO0) / PF9 (IO1) / PE2 (IO2) / PF6 (IO3) Single-line instruction/address/data phases in this first pass – see "Firmware architecture" below
Chip select QUADSPI hardware NCS PB10 Hardware-managed, not a manual GPIO – see "Why chip-select is hardware NCS" below
Debug console USART1 PA9 (TX) / PA10 (RX) 19200 baud, 8N1, via external FTDI adapter (not the onboard ST-LINK VCP)

MCU: STM32H753ZITx (LQFP144). Cortex-M7 D-Cache is disabled in this project's .ioc – required for QUADSPI safety on this core, and already handled at the peripheral-configuration level rather than left as a gotcha for later.

Why chip-select is hardware NCS

The companion SPI project's driver manages chip-select with a manual GPIO, because generic SPI hardware has no concept of a multi-phase command – each HAL_SPI_Transmit/Receive call is an independent transaction, so software has to bracket chip-select across several calls itself. QUADSPI's peripheral is different: it natively understands the instruction/address/ dummy-cycle/data phase structure of a single command, expressed as one QSPI_CommandTypeDef passed to HAL_QSPI_Command(), so the peripheral can safely own NCS in hardware for the whole command with no software gap to land in. Same underlying command structure as the SPI chip – solved by hardware here instead of manually, because this peripheral (unlike SPI1) actually models the concept of a command phase.

Firmware architecture

No RTOS – a single superloop in Core/Src/main.c, with the flash driver written as a C++ class bridged into plain-C main.c:

  • **W25Q/** – the driver itself:
    • w25q_commands.h – JEDEC command opcodes and chip geometry constants, shared verbatim with the companion SPI project (transport-agnostic).
    • W25QFlashQSPI.hpp/.cpp – the driver class: same public API shape as the SPI version (JEDEC ID, status/ready polling, sector/block/chip erase plus eraseRange(), paged read/write). Built on HAL_QSPI_Command/Transmit/Receive in indirect mode, single-line phases only for now – not yet using the chip's 4-line Quad Read/Quad Page Program commands, which is QUADSPI's actual throughput advantage over plain SPI. Not thread-safe – see the class-level Doxygen @warning for the QSPI-specific mechanism (each individual command is hardware-atomic; a sequence of commands is not).
    • w25q_validation.hpp/.cpp – the destructive validation suite described above, ported from the SPI project (only the constructor's parameter type differs – the suite itself is transport-agnostic).
  • **Core/Inc/entryPointCPP.hpp, Core/Src/entryPointCPP.cpp** – the C/C++ bridge: extern "C" functions wrapping the driver object, guarded against use before initW25QFlash() has run.
  • **Core/Src/main.c** – CubeMX-generated peripheral init plus the application code described above.

Building

This is an STM32CubeIDE project, but it can also be built headlessly from the command line using CubeIDE's bundled ARM GCC toolchain:

cd Debug
TOOLCHAIN_BIN="/opt/st/stm32cubeide_1.18.1/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3.rel1.linux64_1.0.0.202410170706/tools/bin"
export PATH="$TOOLCHAIN_BIN:$PATH"
make -j4 all

This produces H753_CPP_W25Q_QSPI_Flash_Read_Write_01.elf. Grep the make output for warning:/error: to check a change compiles cleanly. Note: the W25Q/ folder needs to be added as a source/include location in the CubeIDE project settings before this will find W25QFlashQSPI.hpp – adding the files to disk doesn't register them with the build configuration by itself.

Debug output

Not yet captured – this project hasn't been run on hardware. Once working, a successful run of the normal demo path is expected to print something equivalent to the companion SPI project's output (JEDEC ID, write/read-back round trip confirmation).

Documentation

Doxygen-generated documentation covers the driver, the validation suite, and the C/C++ bridge layer – including the QSPI-specific thread-safety mechanism in the class-level @warning (each individual command is hardware-atomic; a sequence of commands is not). Generate it locally with doxygen Doxyfile.

Contributing

No direct commits to master – branch, open a PR, and merge. This project specifically should not be considered working until it has been tested on real hardware with the full validation suite, not just a successful compile.