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

Flash handling after sdk 14 migration unclear

Edit: Rephrased the question to make it easier to answer.

I used flash storage to store a couple of variables between resets in a app made from SDK 12.2, now I am attempting to migrate to SDK 14, but I can't figure out how to make the fstorage migration correct, in particular the initialization and then how to read from the flash is unclear..

I was thinking of adding DFU later, so if I should handle this differently alltogether, I am totally open for suggestions but i struggle with applying the same principle from the other examples (hrs etc)

I get this err_code = 0x00000010 which I guess translates to NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address when calling nrf_fstorage_erase(&m_fs, m_fs.start_addr, 4, NULL);

I get that I am using start_addr wrong but I can't figure how to fix it..

The project is built on peripheral examples\ble_app_uart

main routine:

NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) =
{
    .evt_handler = fs_event_handler,
};


/**@brief Application main function.
 */
int main(void)
{
    uint32_t err_code;
    bool     erase_bonds;
    
    uint32_t data;
    uint32_t flash_data[4];
    

    // Initialize.
    err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);

    uart_init();
    log_init();
    
    err_code = nrf_fstorage_init(&m_fs, &nrf_fstorage_sd, NULL);
    APP_ERROR_CHECK(err_code);
    
    buttons_leds_init(&erase_bonds);
    ble_stack_init();
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();

    printf("\r\nUART Start!");
    NRF_LOG_INFO("UART Start!");
    err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
    NRF_LOG_FLUSH();
    // Enter main loop.
    for (;;)
    {
        if(do_flash_operation)
        {   
            do_flash_operation = false;
            // Erase one page
            NRF_LOG_INFO("Erasing a flash page at address 0x%X\r\n", (uint32_t)m_fs.start_addr);
            fs_callback_flag = 1;
            err_code = nrf_fstorage_erase(&m_fs, m_fs.start_addr, 4, NULL);
            APP_ERROR_CHECK(err_code);
            if (err_code != NRF_SUCCESS)
            {
                bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                NRF_LOG_ERROR("erase error");
            }
            while(fs_callback_flag == 1)  { power_manage(); }
            
            //Read the first 4 words of the page
            NRF_LOG_INFO("Data read from flash address 0x%X: \r\n", (uint32_t)m_fs.start_addr);
            err_code = nrf_fstorage_read(&m_fs, m_fs.start_addr, flash_data, 32);
            APP_ERROR_CHECK(err_code);
            for(int i=0; i<4; i++)
            {                  
                NRF_LOG_INFO("%X ", flash_data[i]);
            }
            NRF_LOG_INFO("\r\n");
            
            data = 0xAAAAAAAA;
            NRF_LOG_INFO("Writing data 0x%X to address 0x%X\r\n", data, (uint32_t)m_fs.start_addr);
            fs_callback_flag = 1;
            err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
            APP_ERROR_CHECK(err_code);
            if (err_code != NRF_SUCCESS)
            {
                bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                NRF_LOG_ERROR("write error");
            }
            while(fs_callback_flag == 1)  { power_manage(); }
            
            data = 0xBBBBBBBB;
            NRF_LOG_INFO("Writing data 0x%X to address 0x%X\r\n", data, (uint32_t)m_fs.start_addr + 4);
            fs_callback_flag = 1;
            err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 1, &data, 4, NULL);
            APP_ERROR_CHECK(err_code);
            if (err_code != NRF_SUCCESS)
            {
                bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                NRF_LOG_ERROR("write error");
            }
            while(fs_callback_flag == 1)  { power_manage(); }
            
            //Read the first 4 words of the page
            NRF_LOG_INFO("Data read from flash address 0x%X: \r\n", (uint32_t)m_fs.start_addr);
            err_code = nrf_fstorage_read(&m_fs, m_fs.start_addr, flash_data, 32);
            APP_ERROR_CHECK(err_code);
            for(int i=0; i<4; i++)
            {
                NRF_LOG_INFO("%X ", flash_data[i]);
            }
            NRF_LOG_INFO("\r\n");
        }
        
        if (NRF_LOG_PROCESS() == false)
        {
            NRF_LOG_FLUSH();
            power_manage();
        }
        NRF_LOG_FLUSH();
    }
}

temp.link to project (upload file doesn't work??)

  • Yes. In the previous sdk this address was calculated automaticly when initializing the module I think? Do I have to set it manually now? How do i pick the right address? @petter An example with "best practise" of handling persistent storing of variables with either fds or fstorage I think would be useful to add to your examples in the SDK..

  • Added start_addr and end_addr to NRF_FSTORAGE_DEF and made sure the page(s) I want to delete is within the constraints of start and end.

    /**
     * @brief event handler for flash storage
     * @details this is triggered each time a flash operation is done
     */
    static void fs_event_handler(nrf_fstorage_evt_t * evt){
        if (evt->result != NRF_SUCCESS){
            NRF_LOG_ERROR("Flash error");
            while(1);
        } else {
            fs_callback_flag = 0;
            NRF_LOG_INFO("Flash evt ok");
        }
    }
    
    NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) =
    {
        .evt_handler = fs_event_handler,
        .start_addr = 0x0007F000,
        .end_addr = 0x000FF000,
    };
    
    
    /**@brief Application main function.
     */
    int main(void)
    {
        uint32_t err_code;
        bool     erase_bonds;
        
        uint32_t data;
        uint32_t flash_data[4];
        do_flash_operation = true;
    
        // Initialize.
        err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
        uart_init();
        log_init();
        
        err_code = nrf_fstorage_init(&m_fs, &nrf_fstorage_sd, NULL);
        APP_ERROR_CHECK(err_code);
        
        buttons_leds_init(&erase_bonds);
        ble_stack_init();
        gap_params_init();
        gatt_init();
        services_init();
        advertising_init();
        conn_params_init();
    
        NRF_LOG_INFO("BLE NUS with UART and FSTORAGE Start!");
        err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
        APP_ERROR_CHECK(err_code);
        NRF_LOG_FLUSH();
        // Enter main loop.
        for (;;)
        {
            if(do_flash_operation)
            {   
                do_flash_operation = false;
                // Erase one page
                NRF_LOG_INFO("Erasing a flash page at address 0x%X\n", (uint32_t)m_fs.start_addr);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_erase(&m_fs, m_fs.start_addr, 1, NULL);
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("erase error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                data = 0xAAAAAAAA;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\n", data, (uint32_t)m_fs.start_addr);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                data = 0xBBBBBBBB;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\n", data, (uint32_t)m_fs.start_addr + 4);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 4, &data, 4, NULL);
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                            
                data = 0xCCCCCCCC;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\n", data, (uint32_t)m_fs.start_addr + 8);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 8, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                            
                data = 0xDDDDDDDD;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\n", data, (uint32_t)m_fs.start_addr + 12);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 12, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                //Read the first 4 words of the page
                NRF_LOG_INFO("Data read from flash address 0x%X: \n", (uint32_t)m_fs.start_addr);
                err_code = nrf_fstorage_read(&m_fs, m_fs.start_addr, flash_data, 32);
                APP_ERROR_CHECK(err_code);
                for(int i=0; i<4; i++)
                {                  
                    NRF_LOG_INFO("%X ", flash_data[i]);
                }
                NRF_LOG_INFO("Read Done\n");
                            
                data = 0xEEEEEEEE;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\n", data, (uint32_t)m_fs.start_addr + 16);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 16, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                            
                data = 0x00000000;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\r\n", data, (uint32_t)m_fs.start_addr + 20);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 20, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                            
                data = 0x11111111;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\r\n", data, (uint32_t)m_fs.start_addr + 24);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 24, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                            
                data = 0x22222222;
                NRF_LOG_INFO("Writing data 0x%X to address 0x%X\r\n", data, (uint32_t)m_fs.start_addr + 28);
                fs_callback_flag = 1;
                err_code = nrf_fstorage_write(&m_fs, m_fs.start_addr + 28, &data, 4, NULL);      //Write data to memory address. Check it with command: nrfjprog --memrd addr --n 32
                APP_ERROR_CHECK(err_code);
                if (err_code != NRF_SUCCESS)
                {
                    bsp_indication_set(BSP_INDICATE_FATAL_ERROR);
                    NRF_LOG_ERROR("write error");
                }
                NRF_LOG_FLUSH();
                while(fs_callback_flag == 1)  { power_manage(); }
                
                //Read the first 4 words of the page
                NRF_LOG_INFO("Data read from flash address 0x%X: \r\n", (uint32_t)m_fs.start_addr + 16);
                err_code = nrf_fstorage_read(&m_fs, m_fs.start_addr + 16, flash_data, 32);
                APP_ERROR_CHECK(err_code);
                for(int i=0; i<4; i++)
                {
                    NRF_LOG_INFO("%X ", flash_data[i]);
                }
                NRF_LOG_INFO("Read Done\n");
            }
            
            if (NRF_LOG_PROCESS() == false)
            {
                NRF_LOG_FLUSH();
                power_manage();
            }
            NRF_LOG_FLUSH();
        }
    }
    

    Link to project (Only valid for 30 days)

  • Could you explain how you selected the start and end addresses, and how you made sure they don't conflict with the application or softdevice?

  • I used the "will it float or sink" method.. ;) I picked an arbitrary high address and used the nrf tool thingy to male sure norhing was on it after i had flashed the application, and put end address more than one page higher. I seem to recall it used to be picked from the top of the memory and down depending on many pages, but I was not sure and could not find it again. If i remember correctly the soft device aleays gets the first addresses, then you application, and the rest you can use from the top down

Related