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

Writing to nvram

I would like help in understanding the limitations of the NVRAM. The documentation for the nRF52840 and the nRF52832 are different. This is what the nRF52840 reads:

Nvram write 52840 doc

Do I understand correctly that, for any word in a 4K block, it can only be written twice before the entire page must be erased?

The nRF52832 seems to have a different limitation:

nvram writing nRF52840

This is more complicated. Here the page is divided into 512 byte blocks and the limitations is 181 writes per block before page erase is needed. Here nothing is said about a 32 bit word write.

The reason I ask is that I am using Gazell pairing. It seems to me that, for part of the database in nvram, it partitions up its information into 4bit chunks, 8 to a 32 bit word. It shuffles bits and requires a byte to be written, I think for each pairing, which of course turns into a 32 bit word being written per byte demanded i.e. potentially 8 times. It would appear therefore that the nRF52840 is incompatible with the current version of Gazell, which, to say the least is worrying to me since I am sort-of committed to both. What is wrong with my understanding above?

Parents
  • Just a suggestion to your software gurus, once you have checked that writing a 1 to an already written zero in nvram has no impact, here is my suggestion for a much simplified byte write routine:

    //Here is a suggestion. Perhaps only for the nRF52840??
    //I have no test harness to check if it is valid.
    //This is simple but relies entirely that writing a 1 to an existing zero does no harm.
    //You have to be a bit careful in C with type casting here.
    
    void nrf_nvmc_write_byte(uint32_t address, uint8_t value)
    {
        uint32_t byte_shift = address & (uint32_t)0x03; //the address of the byte in a 32 bit word.
        uint32_t address32 = address & ~byte_shift; // Address of the word this byte is in.
        //Then, take the value to be written, negate it as 8 bits only, convert to 32 bits,
        //shift it into position and XOR to 0xFFFFFFFF.
        //Thus the result will all ones outside the byte to be written.
        uint32_t value32 = 0xFFFFFFFF ^ (((uint32_t)(uint8_t)(~value)) << (byte_shift << 3));
    
        // Enable write.
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
        __ISB();
        __DSB();
        //actually do the write.
        *(uint32_t*)address32 = value32;
        wait_for_flash_ready();
    
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
        __ISB();
        __DSB();
    }

    Unless the same byte is written to more than once, zeros are only written once.

    I hope that I have given sufficient explanation and my proposal for modification is not too presumptious.

    Ray

    PS, there is a "word write" which I have not yet checked.

Reply
  • Just a suggestion to your software gurus, once you have checked that writing a 1 to an already written zero in nvram has no impact, here is my suggestion for a much simplified byte write routine:

    //Here is a suggestion. Perhaps only for the nRF52840??
    //I have no test harness to check if it is valid.
    //This is simple but relies entirely that writing a 1 to an existing zero does no harm.
    //You have to be a bit careful in C with type casting here.
    
    void nrf_nvmc_write_byte(uint32_t address, uint8_t value)
    {
        uint32_t byte_shift = address & (uint32_t)0x03; //the address of the byte in a 32 bit word.
        uint32_t address32 = address & ~byte_shift; // Address of the word this byte is in.
        //Then, take the value to be written, negate it as 8 bits only, convert to 32 bits,
        //shift it into position and XOR to 0xFFFFFFFF.
        //Thus the result will all ones outside the byte to be written.
        uint32_t value32 = 0xFFFFFFFF ^ (((uint32_t)(uint8_t)(~value)) << (byte_shift << 3));
    
        // Enable write.
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
        __ISB();
        __DSB();
        //actually do the write.
        *(uint32_t*)address32 = value32;
        wait_for_flash_ready();
    
        NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
        __ISB();
        __DSB();
    }

    Unless the same byte is written to more than once, zeros are only written once.

    I hope that I have given sufficient explanation and my proposal for modification is not too presumptious.

    Ray

    PS, there is a "word write" which I have not yet checked.

Children
No Data
Related