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

nrf9160 Flash access

Hi.  I need to use some of the flash on the nRF9160 for non-volatile storage.  But I want to do it in a very specific way to save on RAM usage.

Essentially I want to be able to define a character array like;

const char configInformation[32768];

I want to be able to use flash functions to erase and write the data block

flash_erase( device, configInformation);

offset = 0;

loop until configInformation done

     flash_write( device, &configInformation[offset], newData, sizeof(newData) );

     offset += sizeof(newData)

(please excuse the pseudo code, I'm just trying to get a concept accross)

Then I'd like to be able to access configInformation in a bytewise fashion without using a read  function to stuff pieces of it into a RAM buffer.

I'm reading through the flash driver or the non-volatile storage subsystems and they don't seem to provide this functionality.  Is there a way to do this?

Thankss

  • Hi! I'm sorry for not replying sooner. I just wanted to let you know I'm looking into this and I'll update the case when I have some information for you.

    Best regards,

    Heidi

  • I guess I should have replied when I figured it out for myself.  With no replies I didn't know if people weren't interested or it was so simple people thought I was an idiot for asking.  Because solution was pretty simple.  Maybe people could critique my solution.

    Anyway, standard nrf9160 definition includes a scratchpad and storage flash partition.  Although one could also define their own, I'm going to example using the scratchpad partition.

    I create a pointer to constant data;

    const char * scratchData;

    As well as some defines for access to the scratch area;

    #define FLASH_OFFSET            DT_FLASH_AREA_IMAGE_SCRATCH_OFFSET
    #define FLASH_PAGE_SIZE      DT_FLASH_ERASE_BLOCK_SIZE
    #define FLASH_SIZE                  DT_FLASH_AREA_IMAGE_SCRATCH_SIZE

    When I initialize, I assign this to the scratchpad partition; as well as getting a device object for the flash;

    flashDev = device_get_binding( DT_FLASH_DEV_NAME );

    scratchData = (char *)FLASH_OFFSET;

    When I erase/write to the section, I use the flash functions

    // Erase

    flash_write_protection_set( flashDev, false );
    flash_erase( flashDev, FLASH_OFFSET, FLASH_PAGE_SIZE );
    flash_write_protection_set( flashDev, true );

    // Write Block

    if (blockOffset + blockSize) > FLASH_SIZE )
    {
      LOG_ERR( "Write Exceeds Scratchpad Size" );
      return(-1);
    }

    blockOffset += FLASH_OFFSET;
    flash_write_protection_set( flashDev, false );
    flash_write( flashDev, blockOffset, blockData, blockSize );
    flash_write_protection_set( flashDev, true );

    Then I can access the block using the scratchData pointer.  I use the following configuration variables in prj.conf;

    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_MPU_ALLOW_FLASH_WRITE=y
    CONFIG_SOC_FLASH_NRF=y
    CONFIG_SOC_FLASH_NRF_EMULATE_ONE_BYTE_WRITE_ACCESS=y

    The emulate byte access is so that I can write generic data.  I'm not worried about the extra overhead.  If you want to handle 4-byte alignment yourself, you don't have to include this.

    I deleted a lot of the error handling from my code to make the concept easier to see.

    Thanks,

Related