Problems with QSPI device initialization

Hi all,
My project uses nRF52840 microcontroller and nRF5_SDK_17.1.0.
My project uses AT25SF161B flash memory and The little filesystem to store data and everything works fine.
Now I need to use S25FL064L flash memory and I have some problems.

This is my QSPI configuration:

#define QSPI_ENABLED 1
#define QSPI_CONFIG_SCK_DELAY 1
#define QSPI_CONFIG_XIP_OFFSET 0
#define QSPI_CONFIG_READOC 4		// <4=> Read4IO 
#define QSPI_CONFIG_WRITEOC 2		// <2=> PP4O 
#define QSPI_CONFIG_ADDRMODE 0		// <0=> 24bit 
#define QSPI_CONFIG_MODE 0			// <0=> Mode 0 
#define QSPI_CONFIG_FREQUENCY 15	// <15=> 32MHz/16

#define BSP_QSPI_SCK_PIN    	    	NRF_GPIO_PIN_MAP(0, 19)
#define BSP_QSPI_CSN_PIN    	    	NRF_GPIO_PIN_MAP(0, 17)
#define BSP_QSPI_IO0_PIN    	    	NRF_GPIO_PIN_MAP(0, 20)
#define BSP_QSPI_IO1_PIN    	    	NRF_GPIO_PIN_MAP(0, 21)
#define BSP_QSPI_IO2_PIN    	    	NRF_GPIO_PIN_MAP(0, 22)
#define BSP_QSPI_IO3_PIN    	    	NRF_GPIO_PIN_MAP(0, 23)

The first problem is that sometimes the QSPI device initialization fails, that is, the instruction

err_code = nrf_drv_qspi_init(&config, NULL, NULL);
APP_ERROR_CHECK(err_code); 

returns the following error:

<error> app: ERROR 13 [NRF_ERROR_TIMEOUT] at C:\[my project folder]\Flash.cpp:266
PC at: 0x0004ED0B
<error> app: End of error report

The problem persists despite numerous restart commands. To clear the error, you must remove power from the microcontroller.

If the QSPI device initialization is OK, the second problem occurs when executing the nrf_drv_qspi_read or nrf_drv_qspi_write function. What happens is that the firmware gets stuck inside the while loop of the qspi_task_perform function.

static nrfx_err_t qspi_task_perform(nrf_qspi_task_t task)
{
    // Wait for peripheral
    if (m_cb.is_busy)
    {
        return NRFX_ERROR_BUSY;
    }

    nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);

    if (m_cb.handler)
    {
        m_cb.is_busy = true;
        nrf_qspi_int_enable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
    }

    nrf_qspi_task_trigger(NRF_QSPI, task);

    if (m_cb.handler == NULL)
    {
        while (!nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY))   // the firmware gets stuck here
        {};
    }
    return NRFX_SUCCESS;
}

Can anyone help me understand and solve my problems?

Below is the code to initialize the memory

uint8_t Configure(void)
{
	uint8_t jedecId[3];
	uint32_t err_code;

	nrf_qspi_cinstr_conf_t cinstr_cfg = {
		.opcode    = 0x66,
		.length    = NRF_QSPI_CINSTR_LEN_1B,
		.io2_level = true,
		.io3_level = true,
		.wipwait   = true,
		.wren      = true
	};

	// Send reset enable
	err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
	APP_ERROR_CHECK(err_code);

	// Send reset command
	cinstr_cfg.opcode = 0x99;
	err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
	APP_ERROR_CHECK(err_code);

	// Read JEDEC ID
	cinstr_cfg.opcode = READ_JEDEC_ID;
	cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_4B;
	cinstr_cfg.wren   = false;
	err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, jedecId);
	APP_ERROR_CHECK(err_code);

	FLASH_DEBUG("JEDEC ID: %02X %02X %02X", jedecId[0], jedecId[1], jedecId[2]);

	if (memcmp(jedecId, AT25SF161B_JEDEC_ID, sizeof(jedecId)) == 0)
	{
		// AT25SF161B flash management
		// This part of the code enables communication with 4 data bits.
	}
	else if (memcmp(jedecId, S25FL064L_JEDEC_ID, sizeof(jedecId)) == 0)
	{
		FLASH_DEBUG("S25FL064L flash detected");

		FLASH_SECTOR_SIZE        = 0x10000U;					// 64 kBytes
		FLASH_BLOCK_SIZE         = 0x1000U;						// 4 kBytes

		uint8_t SR1V;
		uint8_t CR1V;
		uint8_t data[2];

		// The code below enables writing the flash.
		
		// Read Status Register 1 (SR1V)
		cinstr_cfg.opcode = 0x05;			    // RDSR1
		cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B;
		cinstr_cfg.wren   = false;
		err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, &SR1V);
		APP_ERROR_CHECK(err_code);

		if ((SR1V & 0x02) != 0x02)
		{
			// Write Enable.
			cinstr_cfg.opcode = 0x06;		    // WREN
			cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_1B;
			cinstr_cfg.wren   = true;
			err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
			APP_ERROR_CHECK(err_code);
		}
		
		// The following code allows communication with 4 bits of data.

		// Read Configuration Register 1 Volatile (CR1V)
		cinstr_cfg.opcode = 0x35;			    // RDCR1
		cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_2B;
		cinstr_cfg.wren   = false;
		err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, &CR1V);
		APP_ERROR_CHECK(err_code);

		if ((CR1V & 0x02) != 0x02)
		{
			data[0] = SR1V | 0x02;
			data[1] = CR1V | 0x02;

			// Write Registers (Status Register 1 and Configuration Register 1)
			cinstr_cfg.opcode = 0x01;		    // WRR
			cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_3B;
			cinstr_cfg.wren = true;
			err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, data, NULL);
			APP_ERROR_CHECK(err_code);
		}
	}
	else
	{
		FLASH_DEBUG("Memory not supported");
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}

I would like to point out that I currently use a custom electronic board created to host the AT25SF161B flash. In order to mount a S25FL064L flash I had to make a very difficult manual modification because the devices are small (while waiting for the final board that mounts the S25FL064L to arrive).
Can the errors I detect be due to incorrect electrical connections? The JEDEC code reads it correctly anyway.
Thanks.

Parents Reply Children
No Data
Related