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

flash not completely written with fstorage

I am using a custom board based on nRF52840. Application is working perfectly, and then a new feature was requested. I need to count the number of minutes the application has been running, up to a small number.

I used the example fstorage code to find the end of flash, backed up a page and initialized fstorage to use that page. I use app_timer to set a 60-second timer, and when it fires I use nrf_fstorage_write to write 32 bits of zero to the previously erased flash. 

When running with the debugger the 32-bit word is always written to zeros. But when I "free run" the board from power-up, and then later (minutes later) attach the debugger and have a look, I see that where I have written zeros the words in flash are not entirely zero. 

This is not a crisis, as *some* of the bits are written to zero and I only need know on the next boot whether the words are non-0xffffffff. But I am bothered and a little puzzled. 

The code, simplified, is essentially as below. Note that I just extracted this from my code and have not actually run this extract. If someone wishes to do so I can update the code to make it runnable. 

NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
{
   .end_addr = 0x100000,
   .start_addr = 0xfd000,
   .evt_handler = fstorage_evt_handler,
};


static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
    if (p_evt->result != NRF_SUCCESS)
    {
        NRF_LOG_INFO("--> Event received: ERROR while executing an fstorage operation.");
        return;
    }

    switch (p_evt->id)
    {
        case NRF_FSTORAGE_EVT_WRITE_RESULT:
        {
            NRF_LOG_INFO("\n--> Event received: wrote %d bytes at address 0x%x.",
                         p_evt->len, p_evt->addr);
        } break;

        default:
            break;
    }
}

uint32_t g_minutes_used = 0;
uint32_t g_minutes_left = MAX_RUNTIME_MINUTES;


static void timer_runtime_event_handler(void* p_context)
{
   UNUSED_PARAMETER(p_context);

   /*
   ** this handler is called every minute.
   */


   const uint32_t zero_value = 0;

   nrf_fstorage_write(&fstorage, (uint32_t)&my_flash_start[g_minutes_used], &zero_value, sizeof(zero_value), NULL);

   NRF_LOG_INFO("\n    Wrote zero to 0x%x. minutes left = %d.",(uint32_t)&my_flash_start[g_minutes_used],g_minutes_left);


}


#define  MAX_RUNTIME_MINUTES  250

int fstorage_init(void)
{
    ret_code_t rc;

    NRF_LOG_INFO("\nfstorage example started.");

    nrf_fstorage_api_t * p_fs_api;

#ifdef SOFTDEVICE_PRESENT
    NRF_LOG_INFO("\nSoftDevice is present.");
    NRF_LOG_INFO("\nInitializing nrf_fstorage_sd implementation...");
    /* Initialize an fstorage instance using the nrf_fstorage_sd backend.
     * nrf_fstorage_sd uses the SoftDevice to write to flash. This implementation can safely be
     * used whenever there is a SoftDevice, regardless of its status (enabled/disabled). */
    p_fs_api = &nrf_fstorage_sd;
#else
    NRF_LOG_INFO("\nSoftDevice not present.");
    NRF_LOG_INFO("\nInitializing nrf_fstorage_nvmc implementation...");
    /* Initialize an fstorage instance using the nrf_fstorage_nvmc backend.
     * nrf_fstorage_nvmc uses the NVMC peripheral. This implementation can be used when the
     * SoftDevice is disabled or not present.
     *
     * Using this implementation when the SoftDevice is enabled results in a hardfault. */
    p_fs_api = &nrf_fstorage_nvmc;
#endif
    /*
    ** initialize flash storage code
    */
    rc = nrf_fstorage_init(&fstorage, p_fs_api, NULL);
    APP_ERROR_CHECK(rc);


    /*
    ** count how many minutes we've used so far
    */
    uint32_t ix;

    for (ix = 0; ix < MAX_RUNTIME_MINUTES;ix++)
    {
       if (0xffffffff == my_flash_start[ix])
       {
          g_minutes_used = ix; // index into flash
          g_minutes_left = MAX_RUNTIME_MINUTES - g_minutes_used ; // number of minutes left
          break;
       }
    }

    /*
    ** check to see if we've used all our minutes
    */
    if (ix >= MAX_RUNTIME_MINUTES)
    {
       g_minutes_used = MAX_RUNTIME_MINUTES;
       g_minutes_left = 0;
    }

    NRF_LOG_INFO("\nStartup: minutes used = %d.",g_minutes_used);
    NRF_LOG_INFO("\nStartup: minutes left = %d.",g_minutes_left);


    /*
    ** create the & start the runtime timer
    */
    uint32_t err_code;

    #define TICKS_ONE_MINUTE   APP_TIMER_TICKS(60000)


    err_code = app_timer_create(&m_runtime_timer_id,
                                APP_TIMER_MODE_REPEATED,
                                timer_runtime_event_handler);

    err_code = app_timer_start(m_runtime_timer_id,TICKS_ONE_MINUTE,NULL);

}

Parents
  • Here's what I'm seeing in flash at 0xFF000 through 0xff104. All zeros were written each time. 

    00000001 00000001 00000000 00000001 00000001 00000000 00000000 00000000
    00000000 00000000 00000001 00000001 002D4000 003C4000 004B4000 005A4000
    00694000 00784000 00874000 00964000 00A54000 00B44000 00C34000 00000000
    00E14000 00F04000 00000000 00000000 00000000 002C4000 003B4000 004A4000
    00594000 00684000 00774000 00864000 00954000 00A44000 00B34000 00C24000
    00000000 00E04000 00EF4000 00FE4000 000D4000 001C4000 002B4000 003A4000
    00494000 00584000 00674000 00764000 00854000 00000000 00A34000 00B24000
    00C14000 00D04000 00DF4000 00EE4000 00FD4000 000C4000 001B4000 002A4000
    00394000 00484000 

Reply
  • Here's what I'm seeing in flash at 0xFF000 through 0xff104. All zeros were written each time. 

    00000001 00000001 00000000 00000001 00000001 00000000 00000000 00000000
    00000000 00000000 00000001 00000001 002D4000 003C4000 004B4000 005A4000
    00694000 00784000 00874000 00964000 00A54000 00B44000 00C34000 00000000
    00E14000 00F04000 00000000 00000000 00000000 002C4000 003B4000 004A4000
    00594000 00684000 00774000 00864000 00954000 00A44000 00B34000 00C24000
    00000000 00E04000 00EF4000 00FE4000 000D4000 001C4000 002B4000 003A4000
    00494000 00584000 00674000 00764000 00854000 00000000 00A34000 00B24000
    00C14000 00D04000 00DF4000 00EE4000 00FD4000 000C4000 001B4000 002A4000
    00394000 00484000 

Children
No Data
Related