This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

QSPI block device issue with S25FS flash part

I am trying to modify the nrf_block_dev_qspi.c to work with S25FS256 flash part in our project. However, i am facing issues. When trying to understand the code I see some things that I don't quite understand.

 

#define BD_ERASE_UNIT_INVALID_ID   0xFFFFFFFF /**< Invalid erase unit number*/

// p_work->erase_unit_idx is initialized to BD_ERASE_UNIT_INVALID_ID in init function
// This means p_work->erase_unit_idx = -1

uint32_t block_to_program = __CLZ(__RBIT(p_work->erase_unit_dirty_blocks));


uint32_t dst_address = (p_work->erase_unit_idx * NRF_BLOCK_DEV_QSPI_ERASE_UNIT_SIZE) +
                               (block_to_program * p_work->geometry.blk_size);

const void * p_src_address = p_work->p_erase_unit_buff +
                                     block_to_program * p_work->geometry.blk_size;

In the above snippet of code, "p_work->erase_unit_dirty_blocks" is initially 0. This results in "block_to_program" being 32. Is this a valid block number? It seems like with a block size of 512, and an erase unit size of 4096, results in 8 blocks only. So block_to_program being 32 is suspicious.

Moreover, the "p_work->erase_unit_idx" is initialized with -1. This results in the "dst_address" being = (-1 * 4096) + (32 * 512). What is the logic here to start with -1.

Another point is, "p_src_address" = p_work->p_erase_unit_buff + (32 * 512 = 16384). The buffer is only allocated with 4096 bytes in the structure. Not sure if this is a bug or some other logic explains this.

Could anyone answer these questions, as it is critical to our project in understanding this code and modifying as necessary for our project.

  • Sumanth,

    64KB erase unit size is something we haven't tested. The implementation assumes that the erase unit is stored in RAM and not sure if you are seeing any behaviour that could be caused by data overflows in RAM. Additionally this implementation supports (maximum) 32 write blocks inside one erase unit. It means that block_size fields in qspi_bdev_config has to be set to 2kB

    It should theoretically work but like I mentioned, we haven't tested those sizes yet.

  • Hi Susheel,

    I have a similar problem, but with a different memory chip (Macronix, mx66u2g45g, 1 Gb):
    when viewing the contents of the disk through the utility "WinHex", I see that the data is repeated every 16 MB (offset 0x0100 0000).

    e.g. original file location is 0x0004 6000, but in memory address 0x0104 6000, 0x0204 6000, ... are located dublicate of my file.

    This patch solves the problem of repeating the file table during formatting, but does not solve the problem of writing files. 

    Also, at some point, the record is made in sector 0 and grinds the file table. Because of this, the data on the map is not available.

    When testing, I used SDK 16.0.0
    I really hope for an ambulance in this matter, since a batch of devices has already been made ...

    Additional information, after full disk format some sectors have the correct content (for NAND flash) for the cleared state (FF), others have an incorrect value (00).

    best Regards,

    Max

  • Thank you very much.

    Yesterday I tried the solutions suggested by the links and everything worked out.

    In addition, I would like to suggest the following change to the file nrf_block_dev_qspi.c.

    static ret_code_t block_dev_qspi_init(nrf_block_dev_t const * p_blk_dev,
                                          nrf_block_dev_ev_handler ev_handler,
                                          void const * p_context)
    {
        ...
        // Enable 32bit address mode if need
        #if QSPI_CONFIG_ADDRMODE == 1
            #if QSPI_FLASH_USE_EN4B_CMD == 1
                // in sdk_config or another place
                #define QSPI_STD_CMD_EN4B  0xB7 // for example for mx66u2g45g
        
                nrf_qspi_cinstr_conf_t cinstr_cfg = {
                        .opcode    = QSPI_STD_CMD_EN4B,
                        .length    = NRF_QSPI_CINSTR_LEN_1B,
                        .io2_level = true,
                        .io3_level = true,
                        .wipwait   = true,
                        .wren      = true
                };
                
                uint32_t err_code = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
                APP_ERROR_CHECK(err_code);
            #endif
        #endif
        
         /* Get 3 byte identification value */
        uint8_t rdid_buf[3] = {0, 0, 0};
        cinstr_cfg.opcode = QSPI_STD_CMD_READ_ID;
        cinstr_cfg.length = NRF_QSPI_CINSTR_LEN_4B;
        ret = nrf_drv_qspi_cinstr_xfer(&cinstr_cfg, NULL, rdid_buf);
        if (ret != NRF_SUCCESS)
        {
            NRF_LOG_INST_ERROR(p_qspi_dev->p_log, "QSPI get 3 byte id error: %"PRIu32"", ret);
            return ret;
        }
        ...
    }

    The universality of the driver is preserved, but it is becoming more flexible. Now the developer can specify the instructions for switching to 32-bit mode, if necessary.


    Nordic team, when to expect the correct driver version with unchecked changes:

    / * Bypass write .... * / ?

  • I am reproducing simmilar problems on nrf52840 devkit (PCA10056) with qspi memory MX25R6435F. The result is that if I write something(block size=256)  to 16 block and then write something to 17 block the previous one(16 block) is corrupted (full of zeros). I dont reproduce this behavior on any of other blocks (I checked almost all flash memory space). The solution you proposed seems to fix this issue. 

    "bypassing unnecessary write when erase_unit_dirty_blocks is zero, the IRQ should reload erase_unit_idx with the correct value.

    Please replace your qspi_block dev driver file with the below"

    I am using sdk 15.3.0. As I see the most important diff from your solution is in block_dev_qspi_write_start function (the rest are additional asserts).  I checked that any of further SDK versions does not contain this fix. My question is if you already fixed this issue in futher SDK's >15.3 ? If yes could you point me how? I am wondering whether fix you proposed 3 years ago is final solution or I should upgrade something else in my sdk version?

Related