Erasing 4kb QSPI ext flash block takes too long 700 - 900 millisec

NRF52840 running 17.1 SDK and using QSPI interface to erase a block of memory from AT25FF321A external flash IC.

When we call erase it takes 930 millisec to finish erasing a 4kb block. The IC datasheet says it should only take 45 millisec or something like that. 

Why is it taking so long?

 

nrfx_err_t nrf_err = nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, start_address);
if (NRFX_SUCCESS == nrf_err)
{
    while(NRFX_SUCCESS != nrf_drv_qspi_mem_busy_check());
}

// this usually takes 770 - 930 millisec to finish
// but the datasheet for the ext falsh says it should only take 45 ms at most

Parents
  • Hi Joshua, 
    Could you try to use a logic analyzer to capture the erase process ? This way we can find what causing the long erase time.
    I did a quick look at the datasheet of the AT25FF321A and it seems to be longer than 45ms ? 

    I would also want to check if the write enable is sent before the block erase command. 

  • I can check the signal on a scope but the other qspi functions write and read work just fine (though I haven't measured the execution time). The qspi speed is set to 16mhz.

    Also, the erase does work without us setting the wren bit and just using the default nrf qspi erase function: 

    nrfx_qspi_erase.

    It seems like wren is taken care of by the nrf qspi erase function in the sdk? Is this not the case?

    If not, can you show me an example of sending the wren cmd using the 17.1 nrf sdk?

    or if possible can you show me an example of using 

    nrfx_qspi_cinstr_xfer to create a custom erase function? I've tried but same behavior.
  • Here is our erase function using the custom transfer command instead of the standard nrf qspi erase.

    It still takes 920 millisec even when explicitly calling wren = true

    static NVM_ERROR erase_qspi_command(uint8_t cmd, uint32_t address, bool wren)
    {
        uint8_t cmd_buffer[3]; //3 bytes for address
    
        cmd_buffer[0] = (address >> 16) & 0xFF;
        cmd_buffer[1] = (address >> 8) & 0xFF;
        cmd_buffer[2] = address & 0xFF;
    
        nrf_qspi_cinstr_conf_t cinstr_cfg = {.opcode    = 0x20, //4kb block erase
                                             .length    = 4, // Command + Address
                                             .io2_level = true,
                                             .io3_level = true,
                                             .wipwait   = false,
                                             .wren      = wren};
    
        nrfx_err_t nrf_err = nrfx_qspi_cinstr_xfer(&cinstr_cfg, cmd_buffer, NULL);
        while (NRFX_SUCCESS != nrf_drv_qspi_mem_busy_check());
        //This takes 920 millisec to finish
        return nrf_err;
    }

Reply
  • Here is our erase function using the custom transfer command instead of the standard nrf qspi erase.

    It still takes 920 millisec even when explicitly calling wren = true

    static NVM_ERROR erase_qspi_command(uint8_t cmd, uint32_t address, bool wren)
    {
        uint8_t cmd_buffer[3]; //3 bytes for address
    
        cmd_buffer[0] = (address >> 16) & 0xFF;
        cmd_buffer[1] = (address >> 8) & 0xFF;
        cmd_buffer[2] = address & 0xFF;
    
        nrf_qspi_cinstr_conf_t cinstr_cfg = {.opcode    = 0x20, //4kb block erase
                                             .length    = 4, // Command + Address
                                             .io2_level = true,
                                             .io3_level = true,
                                             .wipwait   = false,
                                             .wren      = wren};
    
        nrfx_err_t nrf_err = nrfx_qspi_cinstr_xfer(&cinstr_cfg, cmd_buffer, NULL);
        while (NRFX_SUCCESS != nrf_drv_qspi_mem_busy_check());
        //This takes 920 millisec to finish
        return nrf_err;
    }

Children
  • Hi Joshua, 


    Have you tried to use the logic analyzer to capture how the process goes ? 
    If the nRF52 is doing it correctly that it sends WREN and then send Block Erase command 0x20 then continuously check the status (nrf_drv_qspi_mem_busy_check) to know when the AT25FF321A finish erasing then I don't see the problem on the nRF52's side here. 
    You can try to change how often the status bit is checked , there could be a chance that sending too much of that causing a problem  ? Or if there is a problem when doing nrf_drv_qspi_mem_busy_check() that it's not called for 900ms ?

    Have you tried to do a 32kB erase to see how long it takes ? 

  • Yeah, I tried checking the nrf_drv_qspi_mem_busy_check every 5 millisec to put some time in between but that didn't change anything. 

    When I tried 32kb erase it took 7.5 seconds which is way over the spec of the datasheet.

  • Hi Joshua, 
    I don't see any issue with the code and the driver for QSPI. It could be that it's the performance issue with the external flash. 
    Have you tried to test with the external flash on the DK ? From the datasheet it should take less than 240ms for 4kB erase. 

  • I have the nrf52840 dev kit so will try.

    also, we are not using the standard nrf qspi pins, does that make a difference?

    #define GPIO_SPI_MISO 6u // SIO_6 = NVM SPI MISO input pin (QSPI = IO1)
    #define GPIO_SPI_CLK 7u // SIO_7 = NVM SPI CLK output pin
    #define GPIO_SPI_MOSI 8u // SIO_8 = NVM SPI MOSI output pin (QSPI = IO0)
    #define GPIO_SPI_IO3 9u // SIO_9 = NVM SPI IO3 pin
    #define GPIO_SPI_IO2 10u // SIO_10 = NVM SPI IO2 pin

    also, not sure if it makes a difference but our nrf52840 core is integrated into the Laird Connectivity BL654 module...

Related