The Quad Serial Peripheral Interface (QSPI) driver includes two layers: the hardware access layer (HAL) and the driver layer (DRV).
The hardware access layer provides basic APIs for accessing the registers of the QSPI peripheral. For details, see the API documentation for QSPI HAL .
The driver layer provides APIs on a higher level than the HAL. For details, see the API documentation for QSPI driver - legacy layer .
Key features include:
- Three standard operations: write, read, and erase.
- Custom instruction sending feature.
- Support for the extended 32-bit addressing mode.
The QSPI Example provides sample code that you can use to quickly get started. Note that before the transmission starts, both the peripheral and memory must be configured, unlike for other drivers, where only the peripheral must be configured.
Driver configuration
The configurable parameters include:
- Pins to be used for QSPI peripheral signals.
- Frequency settings that define the divider of base frequency.
- Clock delay configuration (tSHSL, tWHSL, and tSHWL).
- QSPI mode for read and write operations.
- Extended address mode configuration.
- SPI mode options (Polarization and phase).
Using the QSPI driver with the memory device for asynchronous transfers
Writing an application that uses QSPI involves two steps:
- QSPI peripheral configuration using the nrf_drv_qspi_init function.
- Memory configuration using the custom instruction functionality - nrf_drv_qspi_cinstr_xfer .
Defining a data handling function
Define a helper Boolean and the data handling function for QSPI. Example:
Initializing and configuring the driver
Call nrf_drv_qspi_init to initialize and configure the driver. For possible configuration options, refer to the nrf_drv_qspi_config_t structure documentation. Values in fields configured by NRF_DRV_QSPI_DEFAULT_CONFIG can be found in the sdk_config.h file (see the QSPI_ prefix). Remember that the default configuration of pins is fetched from the pca10056.h file which can be found in the components/boards directory.
Example:
Configuring memory
Configure the memory using proper custom instructions. This task depends on the chosen memory. Refer to the memory documentation before writing code. The example code below works with MX25L6435F memory which can be find on the PCA10056 Development Kit.
Remember that nrf_drv_qspi_cinstr_xfer is a synchronous function and it does not require checking the status flags in peripheral registers.
- Note
- Before peripheral initialization, if the memory used in the system supports the 32-bit addressing mode, set the addrmode field in the nrf_drv_qspi_config_t instance. Then, after peripheral initialization, send a proper custom instruction to the memory device.
Transferring data
You can now use nrf_drv_qspi_write and nrf_drv_qspi_read to transfer data. Memory status is checked automatically before the start of read, write, and erase operations. The event comes after the last operation is finished.
Remember to align the adress to four bytes. You do not need to check how much data will be transfered into memory during one transfer. The peripheral splits data into 256-byte transfers.
- Note
- In many cases, memories have a 256-byte page buffer and it is important to wait for the transfer to finish before filling the buffer with new data to avoid data corruption.
Erasing data
- If an erase step is required, nrf_drv_qspi_erase can be used to erase one block or nrf_drv_qspi_chip_erase to erase the whole chip. Remember that the erase operation takes a lot of time. If an erase operation is executed before a read or write operation, a long delay is observed.
Another option is to prepare a function that waits for Erase Finished state. Additionally, a timeout feature can be implemented in such case:
When the QSPI driver is no longer needed or its configuration must be changed, call nrf_drv_qspi_uninit .