QSPI Flash

QSPI Flash Usage

The following code snippet demonstrates the basic usage of an QSPI flash device.

#include <xs1.h>
#include "qspi_flash.h"

qspi_flash_ctx_t qspi_flash_ctx;
qspi_io_ctx_t *qspi_io_ctx = &qspi_flash_ctx.qspi_io_ctx;

uint8_t data[4];

// Setup the flash device
qspi_flash_ctx.custom_clock_setup = 1;
qspi_flash_ctx.quad_page_program_cmd = qspi_flash_page_program_1_4_4;
qspi_flash_ctx.source_clock = qspi_io_source_clock_xcore;

qspi_io_ctx->clock_block = FLASH_CLKBLK;
qspi_io_ctx->cs_port = PORT_SQI_CS;
qspi_io_ctx->sclk_port = PORT_SQI_SCLK;
qspi_io_ctx->sio_port = PORT_SQI_SIO;

// Full speed clock configuration
qspi_io_ctx->full_speed_clk_divisor = 5; // 600 MHz / (2*5) -> 60 MHz
qspi_io_ctx->full_speed_sclk_sample_delay = 1;
qspi_io_ctx->full_speed_sclk_sample_edge = qspi_io_sample_edge_rising;

// SPI read clock configuration
qspi_io_ctx->spi_read_clk_divisor = 12;  // 600 MHz / (2*12) -> 25 MHz

qspi_io_ctx->spi_read_sclk_sample_delay = 0;
qspi_io_ctx->spi_read_sclk_sample_edge = qspi_io_sample_edge_falling;
qspi_io_ctx->full_speed_sio_pad_delay = 0;
qspi_io_ctx->spi_read_sio_pad_delay = 0;

// Initialize the flash device
qspi_flash_init(&qspi_flash_ctx);

// Read some data
qspi_flash_read(&qspi_flash_ctx, *data, 0x64, 4);

QSPI Flash API

The following structures and functions are used to QSPI flash I/O.

enum qspi_flash_page_program_cmd_t

Values:

enumerator qspi_flash_page_program_1_1_1

Programs pages using only MOSI. Most, if not all, QSPI flashes support this command. Use this if in doubt.

enumerator qspi_flash_page_program_1_1_4

Programs pages by sending the command and address over just SIO0, but the data over all four data lines. Many QSPI flashes support either this or qspi_flash_page_program_1_4_4, but not both. Check the datasheet. If the particular flash chip that will be used is unknown, then qspi_flash_page_program_1_1_1 should be used.

enumerator qspi_flash_page_program_1_4_4

Programs pages by sending the command over just SIO0, but the address and data over all four data lines. Many QSPI flashes support either this or qspi_flash_page_program_1_1_4, but not both. Check the datasheet. If the particular flash chip that will be used is unknown, then qspi_flash_page_program_1_1_1 should be used.

enum qspi_flash_erase_length_t

Most QSPI flashes allow data to be erased in 4k, 32k or 64k chunks, as well as the entire chip. However, these values are not always available on all chips. The erase info table in the qspi flash context structure defines the size of each erasable sector size. This is typically populated automatically by qspi_flash_init() from the SFDP data in the flash.

Values:

enumerator qspi_flash_erase_1

Erase the first available sector size. This should always be available and will be the smallest available erasable sector size.

enumerator qspi_flash_erase_2

Erase the second available sector size. This should be smaller than qspi_flash_erase_3 if both are available.

enumerator qspi_flash_erase_3

Erase the third available sector size. This should be smaller than qspi_flash_erase_4 if both are available.

enumerator qspi_flash_erase_4

Erase the fourth available sector size. This is typically not available, but will be the largest available erasable sector size if it is.

enumerator qspi_flash_erase_chip

Erase the entire chip

inline size_t qspi_flash_erase_type_size(qspi_flash_ctx_t *ctx, qspi_flash_erase_length_t erase_type)
inline uint32_t qspi_flash_erase_type_size_log2(qspi_flash_ctx_t *ctx, qspi_flash_erase_length_t erase_type)
bool qspi_flash_quad_enable_write(qspi_flash_ctx_t *ctx, bool set)

Sets or clears the quad enable bit in the flash.

Note

The quad enable bit is fixed to ‘1’ in some QSPI flash chips, and cannot be cleared.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • set – When true, the quad enable bit is set. When false, the quad enable bit is cleared if possible.

Returns

  • true – if the QE bit was already at the requested value, or if the write was successful.

  • false – if the write did not complete successfully. This can happen when trying to clear the QE bit on parts where it is fixed to ‘1’.

void qspi_flash_write_enable(qspi_flash_ctx_t *ctx)

Sets the write enable latch in the QSPI flash. This must be called prior to erasing, programming, or writing to a register.

Parameters

ctx – The QSPI flash context associated with the QSPI flash.

void qspi_flash_write_disable(qspi_flash_ctx_t *ctx)

This clears the write enable latch in the QSPI flash. This is cleared automatically at the end of write operations, so normally does not need to be called.

Parameters

ctx – The QSPI flash context associated with the QSPI flash.

bool qspi_flash_write_in_progress(qspi_flash_ctx_t *ctx)

This checks to see if the QSPI flash has a write operation in progress.

Parameters

ctx – The QSPI flash context associated with the QSPI flash.

Returns

  • true – if there is a flash write in progress.

  • false – if the flash is not writing and is ready to accept another read or write command.

void qspi_flash_wait_while_write_in_progress(qspi_flash_ctx_t *ctx)

This waits while the QSPI flash has a write operation in progress. It returns when the write operation is complete, or immediately if there is not one in progress to begin with.

Parameters

ctx – The QSPI flash context associated with the QSPI flash.

void qspi_flash_erase(qspi_flash_ctx_t *ctx, uint32_t address, qspi_flash_erase_length_t erase_length)

This performs an erase operation. qspi_flash_write_enable() must be called prior to this.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • address – Any byte address within the data block to erase.

  • erase_length – The data block size to erase. See qspi_flash_erase_length_t. If qspi_flash_erase_chip, then address is ignored.

void qspi_flash_write_register(qspi_flash_ctx_t *ctx, uint32_t cmd, const uint8_t *val, size_t len)

This writes to a register in the QSPI flash. This allows an application to write to non-standard registers specific to its flash chip.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • cmd – The command required for writing to the desired register. Must be the value returned by QSPI_IO_BYTE_TO_MOSI().

  • val – Pointer to the data to write to the register.

  • len – The number of bytes from val to write to the register.

void qspi_flash_write_status_register(qspi_flash_ctx_t *ctx, const uint8_t *val, size_t len)

This writes to the status register in the QSPI flash. qspi_flash_write_enable() must be called prior to this.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • val – Pointer to the data to write to the register.

  • len – The number of bytes from val to write to the register.

void qspi_flash_read_register(qspi_flash_ctx_t *ctx, uint32_t cmd, uint8_t *val, size_t len)

This reads from a register in the QSPI flash. This allows an application to read from non-standard registers specific to its flash chip.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • cmd – The command required for reading from the desired register. Must be the value returned by QSPI_IO_BYTE_TO_MOSI().

  • val – Pointer to the buffer to store the data read from the register.

  • len – The number of bytes to read from the register and save to val.

void qspi_flash_read_status_register(qspi_flash_ctx_t *ctx, uint8_t *val, size_t len)

This reads from the status register in the QSPI flash.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • val – Pointer to the buffer to store the data read from the register.

  • len – The number of bytes to read from the register and save to val.

void qspi_flash_read_id(qspi_flash_ctx_t *ctx, uint8_t *val, size_t len)

This reads the JEDEC ID of the QSPI flash.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • val – Pointer to the buffer to write the ID to.

  • len – The number of ID bytes to read and save to val.

void qspi_flash_poll_register(qspi_flash_ctx_t *ctx, uint32_t cmd, const uint8_t mask, const uint8_t val)

This polls a register in the QSPI flash. This allows an application to poll non-standard registers specific to its flash chip. The register must be one byte and repeatedly sent out over MISO following the read register command.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • cmd – The command required for reading from the desired register. Must be the value returned by QSPI_IO_BYTE_TO_MOSI().

  • mask – The bitmask to apply to the received register value before comparing it to val;

  • val – The value that the register value, masked with mask, must match before returning.

void qspi_flash_poll_status_register(qspi_flash_ctx_t *ctx, const uint8_t mask, const uint8_t val)

This polls the status register in the QSPI flash.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • mask – The bitmask to apply to the received register value before comparing it to val;

  • val – The value that the register value, masked with mask, must match before returning.

void qspi_flash_fast_read(qspi_flash_ctx_t *ctx, uint8_t *data, uint32_t address, size_t len)

This reads data from the flash in fast mode. This is a normal SPI read, using only SIO0 (MOSI) and SIO1 (MOSI), but includes eight dummy cycles between the address and data.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the buffer to save the read data to.

  • address – The byte address in the flash to begin reading at. Only bits 23:0 contain the address. The byte in bits 31:24 is not sent.

  • len – The number of bytes to read and save to data.

void qspi_flash_read(qspi_flash_ctx_t *ctx, uint8_t *data, uint32_t address, size_t len)

This reads data from the flash in quad I/O mode. All four lines are used to send the address and to read the data.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the buffer to save the read data to.

  • address – The byte address in the flash to begin reading at. Only bits 23:0 contain the address. Bits 31:24 are actually transmitted to the flash during the first two dummy cycles following the three address bytes. Some flashes read the SIO lines during these first two dummy cycles to enable certain features, so this might be useful for some applications.

  • len – The number of bytes to read and save to data.

void qspi_flash_read_nibble_swapped(qspi_flash_ctx_t *ctx, uint8_t *data, uint32_t address, size_t len)

This is the same as qspi_flash_read() except that the nibbles in each byte of the data returned are swapped.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the buffer to save the read data to.

  • address – The byte address in the flash to begin reading at. Only bits 23:0 contain the address. Bits 31:24 are actually transmitted to the flash during the first two dummy cycles following the three address bytes. Some flashes read the SIO lines during these first two dummy cycles to enable certain features, so this might be useful for some applications.

  • len – The number of bytes to read and save to data.

void qspi_flash_xip_read(qspi_flash_ctx_t *ctx, uint8_t *data, uint32_t address, size_t len)

This reads data from the flash in quad I/O “eXecute In Place” mode. All four lines are used to send the address and to read the data. No command is sent. The flash must already have been put into “XIP” mode.

The method used to put the flash into XIP mode, as well as to take it out, is flash dependent. See your flash’s datasheet.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the buffer to save the read data to.

  • address – The byte address in the flash to begin reading at. Only bits 23:0 contain the address. Bits 31:24 are actually transmitted to the flash during the first two dummy cycles following the three address bytes. Some flashes read the SIO lines during these first two dummy cycles to enable certain features, so this might be useful for some applications.

  • len – The number of bytes to read and save to data.

void qspi_flash_xip_read_nibble_swapped(qspi_flash_ctx_t *ctx, uint8_t *data, uint32_t address, size_t len)

This is the same as qspi_flash_xip_read() except that the nibbles in each byte of the data returned are swapped.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the buffer to save the read data to.

  • address – The byte address in the flash to begin reading at. Only bits 23:0 contain the address. Bits 31:24 are actually transmitted to the flash during the first two dummy cycles following the three address bytes. Some flashes read the SIO lines during these first two dummy cycles to enable certain features, so this might be useful for some applications.

  • len – The number of bytes to read and save to data.

void qspi_flash_write(qspi_flash_ctx_t *ctx, const uint8_t *data, uint32_t address, size_t len)

This writes data to a page in the QSPI flash. If ctx->quad_page_program_enable is true, then the command in ctx->quad_page_program_cmd is sent and all four SIO lines are used to send the address and data. Otherwise, the standard page program command is sent and only SIO0 (MOSI) is used to send the address and data.

qspi_flash_write_enable() must be called prior to this.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the data to write to the flash.

  • address – The byte address in the flash to begin writing at. Only bits 23:0 contain the address. The byte in bits 31:24 is not sent.

  • len – The number of bytes to write to the flash.

void qspi_flash_write_nibble_swapped(qspi_flash_ctx_t *ctx, const uint8_t *data, uint32_t address, size_t len)

This is the same as qspi_flash_write() except that the nibbles in each byte of the data written are swapped.

qspi_flash_write_enable() must be called prior to this.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the data to write to the flash.

  • address – The byte address in the flash to begin writing at. Only bits 23:0 contain the address. The byte in bits 31:0 is not sent.

  • len – The number of bytes to write to the flash.

void qspi_flash_sfdp_read(qspi_flash_ctx_t *ctx, uint8_t *data, uint32_t address, size_t len)

This reads the SFDP data from the flash in 1-1-1 mode.

Parameters
  • ctx – The QSPI flash context associated with the QSPI flash.

  • data – Pointer to the buffer to save the read data to.

  • address – The byte address in the SFDP area to begin reading at. Only bits 23:0 contain the address. The byte in bits 31:24 is not sent.

  • len – The number of bytes to read and save to data.

void qspi_flash_deinit(qspi_flash_ctx_t *ctx)

Deinitializes the QSPI I/O interface associated with the QSPI flash.

Parameters

ctx – The QSPI flash context associated with the QSPI flash. This should have been previously initialized with qspi_flash_init().

void qspi_flash_init(qspi_flash_ctx_t *ctx)

Initializes the QSPI I/O interface associated with the QSPI flash. The ports and clock block in the ctx->qspi_io_ctx must be set prior to calling this.

If ctx->custom_clock_setup is false, then the QSPI I/O clock configuration is set to safe default values that should work for all QSPI flashes. Otherwise, the clock configuration values must be supplied by the application.

Parameters

ctx – The QSPI flash context associated with the QSPI flash.

QSPI_FLASH_SANITY_CHECKS

When QSPI_FLASH_SANITY_CHECKS is true then some run-time sanity checks are made at the expense of some extra overhead.

QSPI_FLASH_STATUS_REG_WIP_BM

The bit mask for the status register’s write in progress bit.

QSPI_FLASH_STATUS_REG_WEL_BM

The bit mask for the status register’s write enable latch bit.

struct qspi_flash_ctx_t
#include <qspi_flash.h>

The context structure that must be passed to each of the qspi_flash functions.