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

Writing Data to Flash without Pstorage module

Hello Guys,

I am newbie to nrf51822 programming. Currently using nrf51822 (raytac's MDBT40) with S130, SDK11. I am programming the nrf51822 using arduino IDE using this github repo: github.com/.../arduino-nRF5

I want to store data such that even if I update the application, the data should not get erase. There are two options : UICR or flash. I tried using customer register, but it cannot be rewritten unless entire memory is erased. Based on memory map of nrf51822 (infocenter.nordicsemi.com/.../bledfu_memory.html , I can write data to upper part of flash just below the bootloader at page address: 0x3C000. Since NVMC has restricted use (infocenter.nordicsemi.com/index.jsp so I using SD API ( sd_flash_page_erase(60); sd_flash_write(addrloc,dataloc, 8);

When I am printing data at location: printd.printIntDataln(*(uint32_t )addr); printd.printIntDataln((uint32_t *)patwr); Output is : "-1" Data is not getting written to location: 0x3c000. Am I doing something wrong? Is the above mentioned method correct.

complete code snippet I am trying:

    uint32_t patwr=0x0FF0;
     uint32_t *addrloc;
     const uint32_t *dataloc;
     addr = (uint32_t) 0x3C000; //(uint32_t *)(pg_size * pg_num);
     addrloc = &addr;
     dataloc = &patwr;
     sd_flash_page_erase(60);
     sd_flash_write(addrloc,dataloc, 8);


Another try:

pg_size = NRF_FICR->CODEPAGESIZE;
 pg_num  = NRF_FICR->CODESIZE - 5;  // Use last page in flash
  addr = (uint32_t *)(pg_size * pg_num);
 dataloc = &patwr;
 
    sd_flash_page_erase(pg_num);
    /* addr points to the first byte in the last page */
    sd_flash_write(addr, dataloc,  pg_size / sizeof(uint32_t));

 patrd = (uint8_t)*(addr-1);


  printd.printIntDataln(pg_size);
   printd.printIntDataln(pg_num);
  printd.printIntDataln(patrd);
  • You should check the returned error code of sd_flash_page_erase() and sd_flash_write(). If they are not NRF_SUCCESS (0x00000000) the erase/write is not performed.

    If you have enabled the SoftDevice you should wait for the NRF_EVT_FLASH_OPERATION_SUCCESS event before you assume the operation is complete, for example when you erase before you write.

  • Hello Petter, Thank you for the reply. The softdevice is enabled in my case. So if I don't receive " NRF_EVT_FLASH_OPERATION_SUCCESS " I should loop back to erasing again and writing again to flash?

        Pseudo code:
     eraseback:
     while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
        {
            // Do nothing.
        }    
    error= sd_flash_page_erase(pg_num);
            if (error != NRF_EVT_FLASH_OPERATION_SUCCESS) goto eraseback;
        
            printd.printStringData("Error in erasing: ");
            printd.printIntDataln(error);
        
            writeback:
        
             while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
            {
                // Do nothing.
            }
        
            /* addr points to the first byte in the last page */
            error= sd_flash_write(addr, dataloc,  pg_size / sizeof(uint32_t));
            if (error!=NRF_EVT_FLASH_OPERATION_SUCCESS) goto writeback;
        
            if (error != 0) goto writeback;
            printd.printStringData("Error in Writing: ");
            printd.printIntDataln(error);
    

    I came across this library : github.com/.../arduino-NVM Which is similar to persistant storage module. However sometime the code freezes at Erase command.

  • You should erase. Then wait for NRF_EVT_FLASH_OPERATION_SUCCESS. Then write. Then wait for NRF_EVT_FLASH_OPERATION_SUCCESS.

  • Hello Petter,

    Pseudo code:
    
            eraseback: 
            error= sd_flash_page_erase(pg_num);
            if (error != NRF_EVT_FLASH_OPERATION_SUCCESS) goto eraseback; // go back to erasing
    
            writeback:
            error= sd_flash_write(addr, dataloc,  pg_size / sizeof(uint32_t));
            if (error!=NRF_EVT_FLASH_OPERATION_SUCCESS) goto writeback; // go to back to writing
    

    Is this code snippet correct? With this the code freezes at erase step and doesn't move forward.

  • It is not correct. Seems you are mixing returned error code and events. You should check the error code returned from sd_* functions, it should be 0x00000000 (NRF_SUCCESS). I'm not sure what your setup is, but typically you use the SoftDevice handler library to set up a handler where system events can be received, typically called sys_evt_dispatch.

    If you look at for example ble_app_hrs you can see

    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);
    

    in ble_stack_init().

    And something like:

    /**@brief Function for dispatching a system event to interested modules.
     *
     * @details This function is called from the System event interrupt handler after a system
     *          event has been received.
     *
     * @param[in] sys_evt  System stack event.
     */
    static void sys_evt_dispatch(uint32_t sys_evt)
    {
        pstorage_sys_event_handler(sys_evt);
        ble_advertising_on_sys_evt(sys_evt);
    }
    

    In there you can have something like:

        switch (sys_evt)
        {
            case NRF_EVT_FLASH_OPERATION_SUCCESS:
                break;
            
            case NRF_EVT_FLASH_OPERATION_ERROR:            
                break;
                
            default:
                // No implementation needed.
                break;
        }
    
Related