-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Description
Describe the bug
In drivers/flash/nrf_qspi_nor.c, the function qspi_send_cmd by default sets the IO2 and IO3 pins on the QSPI bus to high:
nrf_qspi_cinstr_conf_t cinstr_cfg = {
.opcode = cmd->op_code,
.length = xfer_len,
.io2_level = true,
.io3_level = true,
.wipwait = false,
.wren = wren,
};
ref:
zephyr/drivers/flash/nrf_qspi_nor.c
Line 470 in da6549c
| .io2_level = true, |
Later in this file, the function qspi_device_uninit calls the function nrfx_qspi_mem_busy_check to execute a status register read on the flash to see if the WIP bit is set. It then waits in an idle loop while the bit is set
qspi_device_uninit:
zephyr/drivers/flash/nrf_qspi_nor.c
Line 400 in da6549c
| while (nrfx_qspi_mem_busy_check() != NRFX_SUCCESS) { |
nrfx_qspi_mem_busy_check: https://github.com/NordicSemiconductor/nrfx/blob/55305292a2a8e4149869951451311452f4566e9a/drivers/src/nrfx_qspi.c#L478
The problem I have found is that in this nrfx function, the qspi configuration is initialised to have io2_level and io3_level as false through the NRFX_QSPI_DEFAULT_CINSTR macro which is defined as such:
/** @brief QSPI custom instruction helper with the default configuration. */
#define NRFX_QSPI_DEFAULT_CINSTR(opc, len) \
{ \
.opcode = (opc), \
.length = (len), \
.io2_level = false, \
.io3_level = false, \
.wipwait = false, \
.wren = false \
}
--
I have discovered this because I am working on a device which has a Puya Semiconductor P25Q16H which appears to have an undocumented issue where the HOLD pin behaviour is unusual - I am not exactly sure where this behaviour is standardised, but in most devices HOLD pin is supposed to be ignored for status commands I think. However, for this device it is not, so the MISO pin is held high when HOLD is low, causing the status register to always read as 0xFF. The LSB of this read is the Write In Progress (WIP) bit, and so the qspi_device_uninit hangs forever because the device never reads the WIP bit as 0.
My suggestions to fix the problem are (either would solve this):
- Remove calls to
nrfx_qspi_mem_busy_checkand instead callqspi_send_cmdwith the ReaD Status Register (RDSR) command - Change
nrfxlibrary to default both IO2 and IO3 lines to high
Expected behavior
QSPI peripheral should hold IO2 and IO3 high (ie, deasserted) during all QSPI operations that do not use those pins.
Additional context
I patched my local nrfx library to set IO2 and IO3 to high in NRFX_QSPI_DEFAULT_CINSTR and the P25Q16H flash chip started working fine. I ran the samples/subsys/fs/littlefs sample and everything worked great.
The board is a custom one (seeedstudio_xiao_ble with the nrf52840 and P25Q16H)