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

Flash Storage Write API has issues

Hello,

I am trying to use the flash API of fstorage in my code. I have called below function at the start of my code. I want to save some integer values every 1 min interval.

Flash reading is working fine, but when writing was tried my whole code gets problem. When write api called debug messaged also doesn’t get print. I have included my c code for flash below. Kindly suggest what should be done.

Thank You.

NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
{
    /* Set a handler for fstorage events. */
    .evt_handler = fstorage_evt_handler,

    /* These below are the boundaries of the flash space assigned to this instance of fstorage.
     * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
     * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
     * last page of flash available to write data. */
    .start_addr = FLASH_START_ADDR,         //    0x70ff0
    .end_addr   = FLASH_END_ADDR,          //     0x80000
};


void Flash_init(void)
{
 uint32_t data_1=5;
      ret_code_t rc;

      #ifdef  FLASH_12
      nrf_fstorage_api_t * p_fs_api;

     /* 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;



      rc = nrf_fstorage_init(&fstorage, p_fs_api, NULL);
      APP_ERROR_CHECK(rc);

      /* It is possible to set the start and end addresses of an fstorage instance at runtime.
     * They can be set multiple times, should it be needed. The helper function below can
     * be used to determine the last address on the last page of flash memory available to
     * store data. */
//     (void) nrf5_flash_end_addr_get();


//       print_flash_info(&fstorage);

      #ifdef  UART_Flash
      printf("Flash Init=%d\n",rc);
      #endif
//
    
            wait_for_flash_ready(&fstorage);


    #endif

}


void Flash_Operation(void)
{
 ret_code_t rc;
 uint32_t local_var=0, data=5;
 uint8_t  len=0;
  
  /***********************************Flash Read *****************************************/
    #ifdef  FLASH_12
      wait_for_flash_ready(&fstorage);
//    printf("Done.");

      rc = nrf_fstorage_read(&fstorage, FLASH_START_ADDR, &local_var, sizeof(local_var));
       
       APP_ERROR_CHECK(rc);
        wait_for_flash_ready(&fstorage);
                   
      #ifdef  UART_Flash
        printf("local_var=%x , RC=%x \n",local_var,rc); 
        printf("Flash read Done.\n");
      #endif


      #endif
     /***********************************Flash read end *****************************************/

      /***********************************Flash write *****************************************/
          
           rc = nrf_fstorage_erase(&fstorage, FLASH_START_ADDR , 1, NULL);
        
            APP_ERROR_CHECK(rc);
            wait_for_flash_ready(&fstorage);
            rc = nrf_fstorage_write(&fstorage, FLASH_START_ADDR , &data, sizeof(data), NULL);
    
            APP_ERROR_CHECK(rc);
            wait_for_flash_ready(&fstorage);
            
                #ifdef  UART_Flash
                printf("ERR code=%d,Flash write %x\n",rc,data);
                #endif
        /***********************************Flash write end *****************************************/

}

  • Hi,

       As per flash storage example, I have added the code in my project. I have copied all the code as it is just changed the starting location and end of the flash. Which I have added in the below code.

    Now the error coming which was occurred last time with me. Here is the link fs_data issue which is coming now again. Last time I have used his suggestions to clear this fs_data error. should I use this answer now..

    The logs are shown below.

    1> "C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld" -X --omagic -eReset_Handler --defsym=__vfprintf=__vfprintf_long --defsym=__vfscanf=__vfscanf_int -EL --gc-sections "-TD:/LTPL_Oct2019/PIR/Scrap Folder/Current_code/FW1_PIR-KNX_R1_working/nRF5_SDK_15.2.0_9412b96/examples/peripheral/twi_master_with_twis_slave/pca10040/blank/ses/Output/twi_master_with_twis_slave_pca10040 Debug/Obj/twi_master_with_twis_slave_pca10040.ld" -Map Output/Debug/Exe/twi_master_with_twis_slave_pca10040.map -u_vectors -o Output/Debug/Exe/twi_master_with_twis_slave_pca10040.elf --emit-relocs --start-group "@D:/LTPL_Oct2019/PIR/Scrap Folder/Current_code/FW1_PIR-KNX_R1_working/nRF5_SDK_15.2.0_9412b96/examples/peripheral/twi_master_with_twis_slave/pca10040/blank/ses/Output/twi_master_with_twis_slave_pca10040 Debug/Obj/twi_master_with_twis_slave_pca10040.ind" --end-group
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/Debug/Exe/twi_master_with_twis_slave_pca10040.elf section `.fs_data' will not fit in region `UNPLACED_SECTIONS'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: region `UNPLACED_SECTIONS' overflowed by 20 bytes
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/twi_master_with_twis_slave_pca10040 Debug/Obj/nrf_fstorage.o: in function `nrf_fstorage_is_busy':
    1> D:\LTPL_Oct2019\PIR\Scrap Folder\Current_code\FW1_PIR-KNX_R1_working\nRF5_SDK_15.2.0_9412b96\components\libraries\fstorage/nrf_fstorage.c:219: undefined reference to `__start_fs_data'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: D:\LTPL_Oct2019\PIR\Scrap Folder\Current_code\FW1_PIR-KNX_R1_working\nRF5_SDK_15.2.0_9412b96\components\libraries\fstorage/nrf_fstorage.c:219: undefined reference to `__stop_fs_data'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/twi_master_with_twis_slave_pca10040 Debug/Obj/nrf_sdh.o:D:\LTPL_Oct2019\PIR\Scrap Folder\Current_code\FW1_PIR-KNX_R1_working\nRF5_SDK_15.2.0_9412b96\components\softdevice\common/nrf_sdh.c:83: undefined reference to `__start_sdh_req_observers'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/twi_master_with_twis_slave_pca10040 Debug/Obj/nrf_sdh.o:(.rodata.sdh_req_observers+0x4): undefined reference to `__stop_sdh_req_observers'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/twi_master_with_twis_slave_pca10040 Debug/Obj/nrf_sdh.o:D:\LTPL_Oct2019\PIR\Scrap Folder\Current_code\FW1_PIR-KNX_R1_working\nRF5_SDK_15.2.0_9412b96\components\softdevice\common/nrf_sdh.c:86: undefined reference to `__start_sdh_state_observers'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/twi_master_with_twis_slave_pca10040 Debug/Obj/nrf_sdh.o:(.rodata.sdh_state_observers+0x4): undefined reference to `__stop_sdh_state_observers'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/twi_master_with_twis_slave_pca10040 Debug/Obj/nrf_sdh.o:D:\LTPL_Oct2019\PIR\Scrap Folder\Current_code\FW1_PIR-KNX_R1_working\nRF5_SDK_15.2.0_9412b96\components\softdevice\common/nrf_sdh.c:89: undefined reference to `__start_sdh_stack_observers'
    1> C:/Program Files/SEGGER/SEGGER Embedded Studio for ARM 4.52c/gcc/arm-none-eabi/bin/ld: Output/twi_master_with_twis_slave_pca10040 Debug/Obj/nrf_sdh.o:(.rodata.sdh_stack_observers+0x4): undefined reference to `__stop_sdh_stack_observers'
    Build failed

    
    /*****************************************************************************
    * Include section
    * Include Files from the Compiler libraries
    *****************************************************************************/
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    #include "stddef.h"
    //#include "config.h"
    #include "nrf_drv_twi.h"
    #include "nrf_gpio.h"
    #include "app_error.h"
    #include "nrf.h"
    #include "bsp.h"
    #include "app_util_platform.h"
    #include "app_timer.h"
    #include "nrf_drv_clock.h"
    #include "boards.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_cli.h"
    #include "nrf_cli_uart.h"
    #include "nrf_soc.h"
    #include "nordic_common.h"
    #include "app_util.h"
    #include "nrf_fstorage.h"
    
    
    #include "nrf_sdh.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_fstorage_sd.h"
    
    
    /*****************************************************************************
    * Include section
    * User Prepared Include Files
    *****************************************************************************/
    #include "GPIOTE_driver.h"
    #include "Relay_driver.h"
    #include "TC78H620FNG.h"
    #include "relay.h"
    #include"Timer.h"
    #include "nrf_delay.h"
    #include "OPT3001_sensor.h"
    #include "PIR.h"
    #include "LED.h"
    #include "config_relay.h"
    #include "main.h"
    
    #include "Definations.h"
    
    #include "KNX_Timer.h"
    #include "INIT.h"
    #include "Test_Code1.h"
    #include "Lighting_channel.h"
    #include "Lighting_operation.h"
    #include "Local_Relay.h"
    #include "Presence_Channel.h"
    #include "Presence_Operation.h"
    #include "KNX_Operation_Handling.h"
    #include "KNX_Datapoint_Handling.h"
    #include "General_Settings.h"
    
    
    //----------------------------------------------------------------------------
    // Constants section
    //----------------------------------------------------------------------------
    
    #define FLASH_START_ADDR   0x26000
    #define FLASH_END_ADDR     0x27000
    //----------------------------------------------------------------------------
    // Boolean variables section
    //----------------------------------------------------------------------------
    
    bool gb_PIR_Operation_Start=0;
    
    //-----------------------------------------------------------------------------
    // Character variables section
    //----------------------------------------------------------------------------
    
    uint8_t gb_Power_ON_flag=0;
    //----------------------------------------------------------------------------
    // unsigned integer variables section
    //----------------------------------------------------------------------------
    
    
    uint16_t  gb_OPT_RAW_DATA, gb_OPT_CONFIGURATION_REG_DATA;
    //----------------------------------------------------------------------------
    // Signed integer variables section
    //----------------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------
    // unsigned long integer variables section
    //----------------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------
    // signed long integer variables section
    //----------------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------
    // unsigned long long integer variables section
    //----------------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------
    // signed long long integer variables section
    //----------------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------
    // Float variables section
    //----------------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------
    // Double variables section
    //----------------------------------------------------------------------------
    
    
    //----------------------------------------------------------------------------
    // Structure or Union variables section
    //----------------------------------------------------------------------------
    
    
    
    
    //----------------------------------------------------------------------------
    // Local Functions Prototypes
    //----------------------------------------------------------------------------
    
    void Flash_init(void);
    //----------------------------------------------------------------------------
    // Global Functions
    //----------------------------------------------------------------------------
    
    
    #define BUTTON_DETECTION_DELAY  APP_TIMER_TICKS(50)
    #define APP_BLE_CONN_CFG_TAG    1
    
    
    /* Defined in cli.c */
    extern void cli_init(void);
    extern void cli_start(void);
    extern void cli_process(void);
    
    static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
    
    
    NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage) =
    {
        /* Set a handler for fstorage events. */
        .evt_handler = fstorage_evt_handler,
    
        /* These below are the boundaries of the flash space assigned to this instance of fstorage.
         * You must set these manually, even at runtime, before nrf_fstorage_init() is called.
         * The function nrf5_flash_end_addr_get() can be used to retrieve the last address on the
         * last page of flash available to write data. */
        .start_addr = FLASH_START_ADDR,
        .end_addr   = FLASH_END_ADDR,
    };
    
    /* Dummy data to write to flash. */
    static uint32_t m_data          = 0xBADC0FFE;
    uint32_t R_data=0;
    static char     m_hello_world[] = "hello world";
    
    
    /**@brief   Helper function to obtain the last address on the last page of the on-chip flash that
     *          can be used to write user data.
     */
    static uint32_t nrf5_flash_end_addr_get()
    {
        uint32_t const bootloader_addr = NRF_UICR->NRFFW[0];
        uint32_t const page_sz         = NRF_FICR->CODEPAGESIZE;
        uint32_t const code_sz         = NRF_FICR->CODESIZE;
    
        return (bootloader_addr != 0xFFFFFFFF ?
                bootloader_addr : (code_sz * page_sz));
    }
    
    
    #ifdef SOFTDEVICE_PRESENT
    /**@brief   Function for initializing the SoftDevice and enabling the BLE stack. */
    static void ble_stack_init(void)
    {
        ret_code_t rc;
        uint32_t   ram_start;
    
        /* Enable the SoftDevice. */
        rc = nrf_sdh_enable_request();
        APP_ERROR_CHECK(rc);
    
        rc = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(rc);
    
        rc = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(rc);
    }
    #else
    static void clock_init(void)
    {
        /* Initialize the clock. */
        ret_code_t rc = nrf_drv_clock_init();
        APP_ERROR_CHECK(rc);
    
        nrf_drv_clock_lfclk_request(NULL);
    
        // Wait for the clock to be ready.
        while (!nrf_clock_lf_is_running()) {;}
    }
    #endif
    
    
    /**@brief   Initialize the timer. */
    static void timer_init_1(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**@brief   Sleep until an event is received. */
    static void power_manage(void)
    {
    #ifdef SOFTDEVICE_PRESENT
        (void) sd_app_evt_wait();
    #else
        __WFE();
    #endif
    }
    
    
    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("--> Event received: wrote %d bytes at address 0x%x.",
                             p_evt->len, p_evt->addr);
            } break;
    
            case NRF_FSTORAGE_EVT_ERASE_RESULT:
            {
                NRF_LOG_INFO("--> Event received: erased %d page from address 0x%x.",
                             p_evt->len, p_evt->addr);
            } break;
    
            default:
                break;
        }
    }
    
    
    static void print_flash_info(nrf_fstorage_t * p_fstorage)
    {
        NRF_LOG_INFO("========| flash info |========");
        NRF_LOG_INFO("erase unit: \t%d bytes",      p_fstorage->p_flash_info->erase_unit);
        NRF_LOG_INFO("program unit: \t%d bytes",    p_fstorage->p_flash_info->program_unit);
        NRF_LOG_INFO("==============================");
    }
    
    
    void wait_for_flash_ready(nrf_fstorage_t const * p_fstorage)
    {
        /* While fstorage is busy, sleep and wait for an event. */
        while (nrf_fstorage_is_busy(p_fstorage))
        {
            power_manage();
        }
    }
    
    
    static void log_init(void)
    {
        ret_code_t rc = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(rc);
    }
    
    //***************************************************************************/
    void main(void)
    {
              // Hardware initialization 
              Hardware_INIT();
    
              // flash initialization 
              Flash_init();
    
             
           
    
         
    
              //Power ON Flag set
              gb_Power_ON_flag=1;
    
              // config all function 
              // Config_all();
    
              //nrf_delay_ms(2000);
              gb_Calibration_Time_flag_for_OPT=0;
    
    
    
              // load 30 sec to timer for PIR to configure 
              gb_PIR_config_time=35;
          
              // wait time 30 sec for PIR sensor to calibrate itself 
              while(gb_PIR_config_time!=0){   /* do nothing */}
          
              printf("delay_1\n");
              // nrf_drv_gpiote_out_set(const_LED);   // LED can be made ON to indicate PIR is active now
    
    
              gb_PIR_Operation_Start=0;
    
              /* Main loop */
    
    
        while (1)
        {
        //operation 
        }
        
    }
    void Flash_init(void)
    {  ret_code_t rc;
    
        timer_init_1();
        log_init();
    //    cli_init();
    
        NRF_LOG_INFO("fstorage example started.");
    
        nrf_fstorage_api_t * p_fs_api;
    
    #ifdef SOFTDEVICE_PRESENT
        NRF_LOG_INFO("SoftDevice is present.");
        NRF_LOG_INFO("Initializing 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("SoftDevice not present.");
        NRF_LOG_INFO("Initializing 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
    
        rc = nrf_fstorage_init(&fstorage, p_fs_api, NULL);
        APP_ERROR_CHECK(rc);
    
        print_flash_info(&fstorage);
    
        /* It is possible to set the start and end addresses of an fstorage instance at runtime.
         * They can be set multiple times, should it be needed. The helper function below can
         * be used to determine the last address on the last page of flash memory available to
         * store data. */
        (void) nrf5_flash_end_addr_get();
    
        /* Let's write to flash. */
        NRF_LOG_INFO("Writing \"%x\" to flash.", m_data);
        rc = nrf_fstorage_write(&fstorage, 0x3e000, &m_data, sizeof(m_data), NULL);
        APP_ERROR_CHECK(rc);
    
        wait_for_flash_ready(&fstorage);
        NRF_LOG_INFO("Done.");
    
    #ifdef SOFTDEVICE_PRESENT
        /* Enable the SoftDevice and the BLE stack. */
        NRF_LOG_INFO("Enabling the SoftDevice.");
        ble_stack_init();
    
        m_data = 0xDEADBEEF;
    
        NRF_LOG_INFO("Writing \"%x\" to flash.", m_data);
        rc = nrf_fstorage_write(&fstorage, 0x3e100, &m_data, sizeof(m_data), NULL);
        APP_ERROR_CHECK(rc);
    
        wait_for_flash_ready(&fstorage);
        NRF_LOG_INFO("Done.");
    #endif
    
        NRF_LOG_INFO("Writing \"%s\" to flash.", m_hello_world);
        rc = nrf_fstorage_write(&fstorage, 0x3f000, m_hello_world, sizeof(m_hello_world), NULL);
        APP_ERROR_CHECK(rc);
    
        wait_for_flash_ready(&fstorage);
        NRF_LOG_INFO("Done.");
    
    //    NRF_LOG_INFO("Use 'read' to read bytes from the flash.");
    //    NRF_LOG_INFO("Use 'write' to write bytes to the flash.");
    //    NRF_LOG_INFO("Use 'erase' to erase flash pages.");
    //    NRF_LOG_INFO("Use 'flasharea' to print and configure the flash read boundaries.");
    
        rc = nrf_fstorage_read(&fstorage, 0x3e100, &R_data, sizeof(R_data));
        APP_ERROR_CHECK(rc);
        NRF_LOG_INFO("R_data=%x",R_data);
        printf("R_data=%x",R_data);
    }
    
    
    /*****************************************************************************
    * End of file.
    *****************************************************************************/
    
    
    
    

  • Hi,

    Yes, you need to update the linker configuration with fs_data, sdh_stack_obervers etc. You can just refer to the example project or Vidar's post and copy from there. It is easy to miss a few tings, but in that case you can do as here and just search for whatever is missing in the example project files and you usually see what you need to add.

Related