I am working on reading and writing data to an external QSPI flash (MX35LF4GE4AD) that has an internal cache mechanism. I have been able to read/write to the flash using standard SPI but would like to improve throughput so I am trying to get it working with QSPI.
The (standard) SPI interaction for writing a page of data is:
- Send program load command + data which writes the buffer to an internal cache (which is 1 page) at the page offset (address of data relative to specific page)
- note: program load payload: 1 byte command (PROGRAM_LOAD) + 16 bit address + data buffer
- Send program execute command so the flash chip will write the cached page to actual flash at a specified address
- note. program execute payload: 1 byte command (PROGRAM_EXECUTE) + 24 bit address
I have been trying to figure out how to get this interaction working using the QSPI API but am running into some issues. I see the following QSPI API's available:
-
nrfx_qspi_read(void * p_rx_buffer, size_t rx_buffer_length, uint32_t src_address)
- nrfx_qspi_write(void const *p_tx_buffer, size_t tx_buffer_length, uint32_t dst_address);
- nrfx_qspi_cinstr_xfer(nrf_qspi_cinstr_conf_t const *p_config, void const * p_tx_buffer, void * p_rx_buffer);
I tried using the following combination:
- nrfx_qspi_cinstr_xfer to send the program load command
- nrfx_qspi_write to send the actual buffer
but this fails because the CS line is toggled between step 1 and 2 which aborts the write from the flash chip's perspective. I tried manually controlling the CS chip by configuring the QSPI peripheral CS pin as NRF_QSPI_PIN_NOT_CONNECTED but the peripheral won't initialize when CS is not connected. My thought here was to set CS low before step 1 and then wait until step 2 completes to set CS high. This way the flash chip would think it was all 1 QSPI transfer.
I also tried using nrfx_qspi_write and packing the program load payload (PROGRAM_LOAD + 16 bit address) into the dst_address field but the Nordic was stuck spinning waiting for the transfer to complete when I tried that. I have not been able to figure out why the transfer did not complete in that case.
Does anyone have suggestions on how I can write data to a flash chip that uses a page cache mechanism?
I was reading through the Nordic and MX35 data sheets and have found some info that may explain why read and writes are failing:
Here is the MX35 page program timing diagram (notice the 16 bit address width):

Here is the Nordic page program timing diagram (notice the 32 bit address width):

Am I correct in assuming the Nordic and MX35 are not compatible via QSPI since the address width on the MX35 is only 16 bits? I realize the Nordic also supports 24 bit addressing but that still is not 16 bits. Is there any way to send a 16 bit address when doing a QSPI read/write?
Side note:
I'm also trying to figure out how nrfx_qspi_mem_busy_check is supposed to work. Internally that method is sending a QSPI_STD_CMD_RDSR (05h) which is not a valid command for the MX35 chip. The MX35 series uses a GET_FEATURE command (0Fh) to report if there is an operation in progress.
Is there a QSPI standard that the MX35 series chip is not adhering to?
Hardware/Software info:
SDK version: nRF5_SDK_17.0.0_9d13099
Nordic chip: NRF52840 on custom hardware
External Flash: MX35LF4GE4AD (4 Gb QSPI external flash)
Softdevice: sd140