I'm currently working with the MX25R6435F flash chip on board the nRF52840 DK and I'm running into issues with it. I don't know whether it's down to my lack of understanding of the flash programming procedure, or there's simply something I'm missing. As it stands, I cannot program a flash sector without first erasing it.
The code to write the flash is buried deep in a wider project, but the relevant extracts are as follows.
Flash Init
nrfx_qspi_config_t qspi_cfg = NRFX_QSPI_DEFAULT_CONFIG;
qspi_cfg.pins.csn_pin = 17;
qspi_cfg.pins.sck_pin = 19;
qspi_cfg.pins.io0_pin = 20;
qspi_cfg.pins.io1_pin = 21;
qspi_cfg.pins.io2_pin = 22;
qspi_cfg.pins.io3_pin = 23;
nrfx_err_t err = nrfx_qspi_init(&qspi_cfg,(nrfx_qspi_handler_t)_static_qspi_callback,NULL);
uint8_t temporary = 0x40;
uint32_t err_code;
nrf_qspi_cinstr_conf_t cinstr_cfg = {
.opcode = QSPI_STD_CMD_RSTEN,
.length = NRF_QSPI_CINSTR_LEN_1B,
.io2_level = true,
.io3_level = true,
.wipwait = true,
.wren = true
};
// Send reset enable
err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
APP_ERROR_CHECK(err_code);
// Send reset command
cinstr_cfg.opcode = QSPI_STD_CMD_RST;
err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
APP_ERROR_CHECK(err_code);
// Switch to qspi mode
cinstr_cfg.opcode = QSPI_STD_CMD_WRSR;
cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B;
err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, &temporary, NULL);
APP_ERROR_CHECK(err_code);
// Enable writing
cinstr_cfg.opcode = QSPI_STD_CMD_WREN;
cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B;
err_code = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
APP_ERROR_CHECK(err_code);
Flash Write
nrfx_err_t err;
//Enable writing
nrf_qspi_cinstr_conf_t cinstr_cfg = {
.opcode = QSPI_STD_CMD_WREN,
.length = NRF_QSPI_CINSTR_LEN_1B,
.io2_level = true,
.io3_level = true,
.wipwait = true,
.wren = true
};
err = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
APP_ERROR_CHECK(err);
/*Target address determination omitted*/
//Set state to busy and log the last action for callback
_lastAction = FLASH_ERASE_REQ;
size_t size = sizeof(imuData_t) * length;
/*_state = FLASH_BUSY;
err = nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB,target_address);
APP_ERROR_CHECK(err);
while(_state != FLASH_BUSY){
__WFE();
}
APP_ERROR_CHECK(err);*/
//Check status register
uint8_t status_value = 0;
nrf_qspi_cinstr_conf_t const config =
NRFX_QSPI_DEFAULT_CINSTR(0x05,
NRF_QSPI_CINSTR_LEN_2B);
err = nrfx_qspi_cinstr_xfer(&config, &status_value, &status_value);
APP_ERROR_CHECK(err);
printf("S: 0x%02x\n",status_value);
_lastAction = FLASH_WRITE_REQ;
printf("W: 0x%x\n",target_address);
printf("Ex: %d\n",data[0].acc.x);
err = nrfx_qspi_write(data,size,target_address);
APP_ERROR_CHECK(err);
return err;
When attempting the write, the status register is reading as 0x42 (Quad enabled and write enabled), and the QSPI write instruction returns sucessfuly, but the actual write request is ignored by the flash chip.
If I uncomment the erase request, however, and wait for it it complete before attempting the write, the write completes successfully. However, a sector erase time of 40ms is a huge overhead for regular sensor write, so I'd like to avoid it if possible.