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

flashwrite persistence

Using sdk12.3 on pca10040.

I wanted to test persistence so I modified the example from the SDK as follows:  log what's already there.  don't erase.  enter new data.  log it again.

Using the provided example /peripheral/flashwrite to get the starting address

pg_size = NRF_FICR->CODEPAGESIZE;
pg_num = NRF_FICR->CODESIZE - 1; // Use last page in flash
addr = (uint32_t *)(pg_size * pg_num);

I then say:

flash_word_write(addr, (uint32_t)patwr);
NRF_LOG_INFO("'%c' was written to flash at %08x\r\n", patwr, (unsigned long) addr);
patrd = (uint8_t)*addr;
NRF_LOG_INFO("'%c' %08x was read from flash at %08x\r\n\r\n", patrd, *addr, (unsigned long) addr);

Regardless of the value of patwr (a character from the console) written to 0007F000 the read value is 00000000.

(So the fact that it does not persist across a reset is not surprising.)

Causes could be that the address is wrong or that writing to flash is somehow being blocked.

Any suggestions pls.

Parents
  • Sorry, something I did not try was to re-instate the call to flash_page_erase(addr);

    That makes the sketch work but of course this prevents it from persisting across a reset.

  • Hello,

    The flash works in the way that you can only flip bits from 1 to 0. In order to flip them back to 1, you need to delete the entire flash page, unfortunately. This means that you need to somehow work around this, by figuring out where your latest data is written. 

    One way to work around this is to use the FDS module, which stores records with record IDs, which you can use to update a record, delete records, or write new records. 

    You can check out the guide in or documentation on how to use the FDS module.

    So there you would typically use functions like fds_record_write(), fds_record_delete(), fds_record_update(), and so on. The FDS module will also evenly distribute the flash tear, so it will ensure maximum durance for the flash.

    Best regards,

    Edvin

  • OK Thx Edvin.  I guess I saw flashwrite and not fds in the 12.3 examples and jumped to a conclusion. :-(

    I see that 12.3 does include the fds library so I made an example using the document you mention.

    The example talks about softdevice but I assume it should work without one.

    The first error I get is

    ../../../main.c:77:18: error: initializer element is not constant

    ret_code_t ret = fds_register(fds_evt_handler);

                      ^

    .. which seems odd.  Is this code viable in 12.3 with the 12.3 fds library?

    Thx.

  • Hello,

    The fds module should work without the softdevice as well. Just make sure to include the correct fstorage files (that are used by the fds files). 

    There are two fstorage.c files. One called fstorage.c, and one called fstorage_nosd.c (no softdevice). Use the last one.

    Your compiler error, "initializer element is not constant" is probably because you are trying to add 

    ret_code_t ret = fds_register(fds_evt_handler);

    outside a function.

    These instructions can't be copy-pasted into a main.c file. You must have all function calls inside a function, e.g. your main() function, or another function that you create. Something like this:

    static void fds_evt_handler(fds_evt_t const * p_fds_evt)
    {
        switch(p_fds_evt->id)
        {
            case FDS_EVT_INIT:
                if(p_fds_evt->result != FDS_SUCCESS)
                {
                    // initialization failed.
                }
                break;
            
            default:
                break;
        }
    }
    
    void my_fds_init_function(void)
    {
        ret_code_t ret = fds_register(fds_evt_handler);
        if(ret != FDS_SUCCESS)
        {
            //registering failed. 
        }
        ret = fds_init();
        if(ret != FDS_SUCCESS)
        {
            // Handle error.
        }
    }

    BR,

    Edvin

  • Thx Edvin and apologies for forgetting the main()

    Now when I try to build this as above I find that  fds_record_t  is undefined.

    I think I have the right stuff in the attached Makefile.

    Again, I'm wondering if I can do this on SDK 12.3?

    Thx. Paul

    PROJECT_NAME     := flashwrite_pca10040
    TARGETS          := nrf52832_xxaa
    OUTPUT_DIRECTORY := _build
    
    SDK_ROOT := ../../../../../..
    PROJ_DIR := ../../..
    
    $(OUTPUT_DIRECTORY)/nrf52832_xxaa.out: \
      LINKER_SCRIPT  := flashwrite_gcc_nrf52.ld
    
    # Source files common to all targets
    SRC_FILES += \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_serial.c \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \
      $(SDK_ROOT)/components/libraries/util/app_error.c \
      $(SDK_ROOT)/components/libraries/util/app_error_weak.c \
      $(SDK_ROOT)/components/libraries/util/app_util_platform.c \
      $(SDK_ROOT)/components/libraries/util/nrf_assert.c \
      $(SDK_ROOT)/components/libraries/util/sdk_errors.c \
      $(SDK_ROOT)/components/libraries/fds/fds.c \
      $(SDK_ROOT)/components/libraries/fstorage/fstorage_nosd.c \
      $(SDK_ROOT)/components/boards/boards.c \
      $(SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \
      $(SDK_ROOT)/components/drivers_nrf/uart/nrf_drv_uart.c \
      $(PROJ_DIR)/main.c \
      $(SDK_ROOT)/external/segger_rtt/RTT_Syscalls_GCC.c \
      $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \
      $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \
      $(SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.S \
      $(SDK_ROOT)/components/toolchain/system_nrf52.c \
    
    # Include folders common to all targets
    INC_FOLDERS += \
      $(SDK_ROOT)/components \
      $(SDK_ROOT)/components/libraries/util \
      $(SDK_ROOT)/components/toolchain/gcc \
      $(SDK_ROOT)/components/drivers_nrf/uart \
      ../config \
      $(SDK_ROOT)/components/drivers_nrf/common \
      $(PROJ_DIR) \
      $(SDK_ROOT)/external/segger_rtt \
      $(SDK_ROOT)/components/libraries/bsp \
      $(SDK_ROOT)/components/libraries/fds \
      $(SDK_ROOT)/components/libraries/fstorage \
      $(SDK_ROOT)/components/libraries/experimental_section_vars \
      $(SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd \
      $(SDK_ROOT)/components/toolchain \
      $(SDK_ROOT)/components/device \
      $(SDK_ROOT)/components/libraries/log \
      $(SDK_ROOT)/components/boards \
      $(SDK_ROOT)/components/drivers_nrf/delay \
      $(SDK_ROOT)/components/toolchain/cmsis/include \
      $(SDK_ROOT)/components/drivers_nrf/hal \
      $(SDK_ROOT)/components/libraries/log/src \
    
    # Libraries common to all targets
    LIB_FILES += \
    
    # C flags common to all targets
    CFLAGS += -DNRF52_PAN_12
    CFLAGS += -DNRF52_PAN_15
    CFLAGS += -DNRF52_PAN_58
    CFLAGS += -DNRF52_PAN_20
    CFLAGS += -DNRF52_PAN_54
    CFLAGS += -DNRF52
    CFLAGS += -DNRF52_PAN_51
    CFLAGS += -DNRF52_PAN_36
    CFLAGS += -DCONFIG_GPIO_AS_PINRESET
    CFLAGS += -DNRF52_PAN_64
    CFLAGS += -DNRF52_PAN_55
    CFLAGS += -DBOARD_PCA10040
    CFLAGS += -DNRF52_PAN_31
    CFLAGS += -DNRF52832
    CFLAGS += -DBSP_DEFINES_ONLY
    CFLAGS += -mcpu=cortex-m4
    CFLAGS += -mthumb -mabi=aapcs
    CFLAGS +=  -Wall -Werror -O3 -g3
    CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
    # keep every function in separate section, this allows linker to discard unused ones
    CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
    CFLAGS += -fno-builtin --short-enums 
    
    # C++ flags common to all targets
    CXXFLAGS += \
    
    # Assembler flags common to all targets
    ASMFLAGS += -x assembler-with-cpp
    ASMFLAGS += -DNRF52_PAN_12
    ASMFLAGS += -DNRF52_PAN_15
    ASMFLAGS += -DNRF52_PAN_58
    ASMFLAGS += -DNRF52_PAN_20
    ASMFLAGS += -DNRF52_PAN_54
    ASMFLAGS += -DNRF52
    ASMFLAGS += -DNRF52_PAN_51
    ASMFLAGS += -DNRF52_PAN_36
    ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
    ASMFLAGS += -DNRF52_PAN_64
    ASMFLAGS += -DNRF52_PAN_55
    ASMFLAGS += -DBOARD_PCA10040
    ASMFLAGS += -DNRF52_PAN_31
    ASMFLAGS += -DNRF52832
    ASMFLAGS += -DBSP_DEFINES_ONLY
    
    # Linker flags
    LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
    LDFLAGS += -mcpu=cortex-m4
    LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
    # let linker to dump unused sections
    LDFLAGS += -Wl,--gc-sections
    # use newlib in nano version
    LDFLAGS += --specs=nano.specs -lc -lnosys
    
    
    .PHONY: $(TARGETS) default all clean help flash 
    
    # Default target - first one defined
    default: nrf52832_xxaa
    
    # Print all targets that can be built
    help:
    	@echo following targets are available:
    	@echo 	nrf52832_xxaa
    
    TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
    
    include $(TEMPLATE_PATH)/Makefile.common
    
    $(foreach target, $(TARGETS), $(call define_target, $(target)))
    
    # Flash the program
    flash: $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex
    	@echo Flashing: $<
    	nrfjprog --program $< -f nrf52 --sectorerase
    	nrfjprog --reset -f nrf52
    
    erase:
    	nrfjprog --eraseall -f nrf52
    

Reply
  • Thx Edvin and apologies for forgetting the main()

    Now when I try to build this as above I find that  fds_record_t  is undefined.

    I think I have the right stuff in the attached Makefile.

    Again, I'm wondering if I can do this on SDK 12.3?

    Thx. Paul

    PROJECT_NAME     := flashwrite_pca10040
    TARGETS          := nrf52832_xxaa
    OUTPUT_DIRECTORY := _build
    
    SDK_ROOT := ../../../../../..
    PROJ_DIR := ../../..
    
    $(OUTPUT_DIRECTORY)/nrf52832_xxaa.out: \
      LINKER_SCRIPT  := flashwrite_gcc_nrf52.ld
    
    # Source files common to all targets
    SRC_FILES += \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_serial.c \
      $(SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \
      $(SDK_ROOT)/components/libraries/util/app_error.c \
      $(SDK_ROOT)/components/libraries/util/app_error_weak.c \
      $(SDK_ROOT)/components/libraries/util/app_util_platform.c \
      $(SDK_ROOT)/components/libraries/util/nrf_assert.c \
      $(SDK_ROOT)/components/libraries/util/sdk_errors.c \
      $(SDK_ROOT)/components/libraries/fds/fds.c \
      $(SDK_ROOT)/components/libraries/fstorage/fstorage_nosd.c \
      $(SDK_ROOT)/components/boards/boards.c \
      $(SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \
      $(SDK_ROOT)/components/drivers_nrf/uart/nrf_drv_uart.c \
      $(PROJ_DIR)/main.c \
      $(SDK_ROOT)/external/segger_rtt/RTT_Syscalls_GCC.c \
      $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \
      $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \
      $(SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.S \
      $(SDK_ROOT)/components/toolchain/system_nrf52.c \
    
    # Include folders common to all targets
    INC_FOLDERS += \
      $(SDK_ROOT)/components \
      $(SDK_ROOT)/components/libraries/util \
      $(SDK_ROOT)/components/toolchain/gcc \
      $(SDK_ROOT)/components/drivers_nrf/uart \
      ../config \
      $(SDK_ROOT)/components/drivers_nrf/common \
      $(PROJ_DIR) \
      $(SDK_ROOT)/external/segger_rtt \
      $(SDK_ROOT)/components/libraries/bsp \
      $(SDK_ROOT)/components/libraries/fds \
      $(SDK_ROOT)/components/libraries/fstorage \
      $(SDK_ROOT)/components/libraries/experimental_section_vars \
      $(SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd \
      $(SDK_ROOT)/components/toolchain \
      $(SDK_ROOT)/components/device \
      $(SDK_ROOT)/components/libraries/log \
      $(SDK_ROOT)/components/boards \
      $(SDK_ROOT)/components/drivers_nrf/delay \
      $(SDK_ROOT)/components/toolchain/cmsis/include \
      $(SDK_ROOT)/components/drivers_nrf/hal \
      $(SDK_ROOT)/components/libraries/log/src \
    
    # Libraries common to all targets
    LIB_FILES += \
    
    # C flags common to all targets
    CFLAGS += -DNRF52_PAN_12
    CFLAGS += -DNRF52_PAN_15
    CFLAGS += -DNRF52_PAN_58
    CFLAGS += -DNRF52_PAN_20
    CFLAGS += -DNRF52_PAN_54
    CFLAGS += -DNRF52
    CFLAGS += -DNRF52_PAN_51
    CFLAGS += -DNRF52_PAN_36
    CFLAGS += -DCONFIG_GPIO_AS_PINRESET
    CFLAGS += -DNRF52_PAN_64
    CFLAGS += -DNRF52_PAN_55
    CFLAGS += -DBOARD_PCA10040
    CFLAGS += -DNRF52_PAN_31
    CFLAGS += -DNRF52832
    CFLAGS += -DBSP_DEFINES_ONLY
    CFLAGS += -mcpu=cortex-m4
    CFLAGS += -mthumb -mabi=aapcs
    CFLAGS +=  -Wall -Werror -O3 -g3
    CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
    # keep every function in separate section, this allows linker to discard unused ones
    CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
    CFLAGS += -fno-builtin --short-enums 
    
    # C++ flags common to all targets
    CXXFLAGS += \
    
    # Assembler flags common to all targets
    ASMFLAGS += -x assembler-with-cpp
    ASMFLAGS += -DNRF52_PAN_12
    ASMFLAGS += -DNRF52_PAN_15
    ASMFLAGS += -DNRF52_PAN_58
    ASMFLAGS += -DNRF52_PAN_20
    ASMFLAGS += -DNRF52_PAN_54
    ASMFLAGS += -DNRF52
    ASMFLAGS += -DNRF52_PAN_51
    ASMFLAGS += -DNRF52_PAN_36
    ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
    ASMFLAGS += -DNRF52_PAN_64
    ASMFLAGS += -DNRF52_PAN_55
    ASMFLAGS += -DBOARD_PCA10040
    ASMFLAGS += -DNRF52_PAN_31
    ASMFLAGS += -DNRF52832
    ASMFLAGS += -DBSP_DEFINES_ONLY
    
    # Linker flags
    LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
    LDFLAGS += -mcpu=cortex-m4
    LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
    # let linker to dump unused sections
    LDFLAGS += -Wl,--gc-sections
    # use newlib in nano version
    LDFLAGS += --specs=nano.specs -lc -lnosys
    
    
    .PHONY: $(TARGETS) default all clean help flash 
    
    # Default target - first one defined
    default: nrf52832_xxaa
    
    # Print all targets that can be built
    help:
    	@echo following targets are available:
    	@echo 	nrf52832_xxaa
    
    TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc
    
    include $(TEMPLATE_PATH)/Makefile.common
    
    $(foreach target, $(TARGETS), $(call define_target, $(target)))
    
    # Flash the program
    flash: $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex
    	@echo Flashing: $<
    	nrfjprog --program $< -f nrf52 --sectorerase
    	nrfjprog --reset -f nrf52
    
    erase:
    	nrfjprog --eraseall -f nrf52
    

Children
  • Hello Paul,

    Yes. This is possible in SDK12.3.0

    fds_record_t is defined in fds.h, so you must add the folder including this in your INC_FOLDERS in your makefile.

    $(SDK_ROOT)/components/libraries/fds \

    I see that you have included it in your makefile, but there must be something wrong with it. 

    Do you intend to use the softdevice in your final appliaction?

    Can you please paste the compiler output log?

    BR,

    Edvin

  • Thx Edvin,

    Initially without softdevice.  Will add that later.

    Compiling file: main.c

    ../../../main.c: In function 'main':

    ../../../main.c:100:13: error: 'struct <anonymous>' has no member named 'p_data'

      record.data.p_data       = &m_deadbeef;

                 ^

    ../../../main.c:101:13: error: 'struct <anonymous>' has no member named 'length_words'

      record.data.length_words = 1;   /* one word is four bytes. */

                 ^

    ../../../main.c:110:13: error: 'struct <anonymous>' has no member named 'p_data'

      record.data.p_data       = &m_hello;

                 ^

    ../../../main.c:112:13: error: 'struct <anonymous>' has no member named 'length_words'

      record.data.length_words = (sizeof(m_hello) + 3) / 4;

                 ^

    make: *** [_build/nrf52832_xxaa_main.c.o] Error 1

     

    I may have misinterpreted the above?

    Thx. Paul

  • Where do you declare "record"? and what does it look like?

  • I used the code from the FDS document you suggested above.

    "You can check out the guide in or documentation on how to use the FDS module."

    In main()

    ..

    fds_record_t        record;

    ..

    BR. Paul

  • Check out the attached project.

    It is a project that uses the softdevice. I recommend that you start directly with this if you intend to use the softdevice in the end. Also because the fstorage_nosd.c is blank in SDK12.3.0. You can probably downport it from a newer SDK version, but if you intend to use the softdevice in the end anyway, I don't see any reason why to not use it from the start. 

    Note that this example is just initializing the fds. It doesn't write or read anything. It only initializes the FDS module.

    Note that I also added the lines:

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

    in ble_stack_init() and the sys_evt_dispatch() in order to register the fstorage events.

    ble_app_uart_fds.zip

    Are you able to compile this using armgcc? I tested this makefile, and it worked here. If not, what version of armgcc do you use?

    Note that when you initialize, write or delete a record, wait for the corresponding events before you countinue.

    example:

    volatile bool m_init = false;
    volatile bool m_write = false;
    volatile bool m_delete = false;
    
    static void fds_evt_handler(fds_evt_t const * p_fds_evt)
    {
        switch(p_fds_evt->id)
        {
            case FDS_EVT_INIT:
                if(p_fds_evt->result != FDS_SUCCESS)
                {
                    // initialization failed.
                }
                else
                {
                    m_init = 1;
                }
                break;
                
            // Add the events for write and delete and set the corresponding m_write m_delete to true in these events.
            
            default:
                break;
        }
    }
    
    main()
    {
        ...
        //init all other things
        my_fds_init_function();
        while(!m_init){};
        
        my_fds_write_function();
        while(!m_fds_write){};
        m_fds_write = false;
        
        my_fds_delete_function();
        while(!m_delete){};
        m_delete = false;
        // Enter main loop.
        
        for (;;)
        {
            //if (NRF_LOG_PROCESS() == false)
            {
                power_manage();
            }
        }
    }

    BR,

    Edvin

Related