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.

Parents
  • Your questions seem very valid, and I do not have answers to them, I have asked the experts to pitch in and help us to understand the code you provided. I hope they respond soon.

  • Hi Susheel,

    Thanks for the update. However i still see issues when i change the NRF_BLOCK_DEV_QSPI_ERASE_UNIT_SIZE to 64KB and m_sflash_params.erase_size = 64KB.

    For some reason the code only works for 4KB erase unit size. The flash part we are using has 64 KB erase size. Any idea why?

  • 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 .... * / ?

Reply
  • 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 .... * / ?

Children
No Data
Related