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

Writing to and reading from flash on nRF5340

Hello,

I am trying to use part of the code from this example https://github.com/zephyrproject-rtos/zephyr/blob/master/samples/subsys/nvs

to write to and read from flash on nRF5340 SoC. However, I am getting the following linking error when building the project in Segger.

I am using Segger v5.34a, NCS v1.5.0-rc1 and Zephyr v2.4.99-ncs1-rc1.

I am including the following header files

#include <zephyr.h>
#include <power/reboot.h>
#include <device.h>
#include <string.h>
#include <drivers/flash.h>
#include <storage/flash_map.h>
#include <fs/nvs.h>

Can you please help ?

1> Linking ‘zephyr_prebuilt.elf’
1> C:\Zypher\v1.5.0-rc1\toolchain\opt/bin/arm-none-eabi-gcc zephyr/CMakeFiles/zephyr_prebuilt.dir/misc/empty_file.c.obj -Wl,-T zephyr/linker.cmd -Wl,-Map=C:/Sandbox/PID4-Firmware/app_core/build_nrf5340pdk_nrf5340_cpuapp_flash/zephyr/zephyr_prebuilt.map -Wl,--whole-archive app/libapp.a zephyr/libzephyr.a zephyr/arch/common/libarch__common.a zephyr/arch/arch/arm/core/aarch32/libarch__arm__core__aarch32.a zephyr/arch/arch/arm/core/aarch32/cortex_m/libarch__arm__core__aarch32__cortex_m.a zephyr/arch/arch/arm/core/aarch32/cortex_m/mpu/libarch__arm__core__aarch32__cortex_m__mpu.a zephyr/arch/arch/arm/core/aarch32/cortex_m/cmse/libarch__arm__core__aarch32__cortex_m__cmse.a zephyr/lib/libc/newlib/liblib__libc__newlib.a zephyr/lib/posix/liblib__posix.a zephyr/soc/arm/common/cortex_m/libsoc__arm__common__cortex_m.a zephyr/boards/boards/arm/nrf5340pdk_nrf5340_cpuapp/libboards__arm__nrf5340dk_nrf5340.a zephyr/drivers/adc/libdrivers__adc.a zephyr/drivers/gpio/libdrivers__gpio.a zephyr/drivers/ipm/libdrivers__ipm.a zephyr/drivers/spi/libdrivers__spi.a modules/nrf/lib/fatal_error/lib..__nrf__lib__fatal_error.a modules/nrf/drivers/hw_cc310/lib..__nrf__drivers__hw_cc310.a modules/hal_nordic/libmodules__hal_nordic.a -Wl,--no-whole-archive zephyr/kernel/libkernel.a zephyr/CMakeFiles/offsets.dir/./arch/arm/core/offsets/offsets.c.obj -Lc:/zypher/v1.5.0-rc1/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/thumb/v8-m.main/nofp -LC:/Sandbox/PID4-Firmware/app_core/build_nrf5340pdk_nrf5340_cpuapp_flash/zephyr -lgcc -Wl,--print-memory-usage zephyr/arch/common/libisr_tables.a C:/Zypher/v1.5.0-rc1/nrfxlib/crypto/nrf_cc312_platform/lib/cortex-m33/soft-float/no-interrupts/libnrf_cc312_platform_0.9.7.a -mcpu=cortex-m33 -mthumb -mabi=aapcs -Wl,--gc-sections -Wl,--build-id=none -Wl,--sort-common=descending -Wl,--sort-section=alignment -Wl,-u,_OffsetAbsSyms -Wl,-u,_ConfigAbsSyms -nostdlib -static -no-pie -Wl,-X -Wl,-N -Wl,--orphan-handling=warn -lm -Wl,-lc -LC:/Zypher/v1.5.0-rc1/toolchain/opt/arm-none-eabi/lib/thumb/v8-m.main/nofp -u_printf_float -Wl,-lgcc -lc -specs=nano.specs -o zephyr\zephyr_prebuilt.elf
1> Memory region Used Size Region Size %age Used
1> FLASH: 73512 B 1 MB 7.01%
1> SRAM: 28680 B 448 KB 6.25%
1> c:/zypher/v1.5.0-rc1/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: app/libapp.a(pid4_flash.c.obj): in function `flash_get_page_info_by_offs':
1> C:\Sandbox\PID4-Firmware\app_core\build_nrf5340pdk_nrf5340_cpuapp_flash/zephyr/include/generated/syscalls/flash.h:85: undefined reference to `z_impl_flash_get_page_info_by_offs'
1> c:/zypher/v1.5.0-rc1/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: app/libapp.a(pid4_flash.c.obj): in function `flash_init':
1> C:\Sandbox\PID4-Firmware\app_core\build_nrf5340pdk_nrf5340_cpuapp_flash/../src/flash/pid4_flash.c:45: undefined reference to `nvs_init'
1> collect2.exe: error: ld returned 1 exit status
1> IDT_LIST: 104 B 2 KB 5.08%
Build failed

Kind regards

Mohamed

Parents
  • Hello,

    I have just realised what the problem was. I needed to add this to my prj.conf file

    CONFIG_FLASH=y
    CONFIG_NVS=y

    I have also noticed the existence of other APIs flash_read() and flash_write(). 

    What is the difference between flash_read() and nvs_read() and the corresponding write APIs?

    Kind regards

    Mohamed

  • Hi!

    Great that you managed to fix the issue. The flash API is a more low level API used for interacting directly with the flash peripheral. The NVS API uses the flash API for easier organization and usage of storage. What you chose depends on your application, but NVS is commonly used for storing BLE bonding data for example.

    Best regards,
    Carl Richard

  • Hi Carl,

    Elements are appended to a sector until storage space in the sector is exhausted. Then a new sector in the flash area is prepared for use (erased). Before erasing the sector it is checked that identifier - data pairs exist in the sectors in use, if not the id-data pair is copied.

    From this it's clear that NVS is not wasteful when it comes to using flash, rather the other way around. The historical data will be overwritten over time, and the NVS subsystem will always ensure that the newest version id-data pair is kept. 

    I have read the documentation again and even after reading it many times I am just about beginning to understand better how NVS works. It is not very easy to read and digest how it all works for someone new to NVS. It would have been much better to complement the worded description with an illustrated example showing for example what happens when the current sector is full and writing to a new sector starts. Also, what happens when all sectors allocated are full.

    I would appreciate a great deal if you could do that for me. HandshakeMask

    I am beginning to warm up to NVS much more than I did a day ago thanks to your explanation. I think I am going to stick with NVS and delay my move to flash API.

    Thank you.

    Kind regards

    Mohamed

  • Hi again, Mohamed!

    Thank you for your patience and good to hear that NVS is more understandable now. I'm glad I could help! This is a part of the Zephyr RTOS so I think it's better if you open an issue for your suggestions in their GitHub issue tracker, as they likely can provide better help than me on the specifics of the NVS API.

    Good luck on your project!

    Best regards,
    Carl Richard

  • Hi Carl,

    I've recently ported the code developed for the nRF5340 to the nRF52833 SoC and I am seeing this error when I call nvs_init(),

    <error> fs_nvs: NVS not initialized

    Any idea what could be causing this?

    Kind regards

    Mohamed

  • Hi!

    That error should not be possible to get from nvs_init(...). Have you made sure that nvs_init is called before any other NVS functions? A complete log might help me identify the issue. I also suggest debugging the code to see where it fails.

    Best regards,
    Carl Richard

  • Hi Carl,

    My NVS initialisation code looks like this and I am seeing the message in red below "Flash Init failed".

    I think the returned value rc = 0xffffffd3

    void flash_init( void )
    {
    uint32_t rc = 0;
    struct flash_pages_info info;

    /* define the nvs file system by settings with:
    * sector_size equal to the pagesize,
    * 3 sectors
    * starting at FLASH_AREA_OFFSET(storage)
    */
    fs.offset = FLASH_AREA_OFFSET( storage );
    flash_dev = device_get_binding( DT_CHOSEN_ZEPHYR_FLASH_CONTROLLER_LABEL );
    if ( flash_dev == NULL )
    {
    printk( "Flash device not bound!\n" );
    return;
    }
    else
    {
    rc = flash_get_page_info_by_offs( flash_dev, fs.offset, &info );
    if ( rc )
    {
    printk( "Unable to get page info" );
    }
    fs.sector_size = info.size;
    fs.sector_count = 3U;

    rc = nvs_init( &fs, DT_CHOSEN_ZEPHYR_FLASH_CONTROLLER_LABEL );
    if ( rc )
    {
    printk( "Flash Init failed\n" );
    }

    size_t page_count = flash_get_page_count(flash_dev);
    printk( "Flash contains %d pages of 4kB each\n", page_count );

    ...

    ...

    Kind regards

    Mohamed

Reply
  • Hi Carl,

    My NVS initialisation code looks like this and I am seeing the message in red below "Flash Init failed".

    I think the returned value rc = 0xffffffd3

    void flash_init( void )
    {
    uint32_t rc = 0;
    struct flash_pages_info info;

    /* define the nvs file system by settings with:
    * sector_size equal to the pagesize,
    * 3 sectors
    * starting at FLASH_AREA_OFFSET(storage)
    */
    fs.offset = FLASH_AREA_OFFSET( storage );
    flash_dev = device_get_binding( DT_CHOSEN_ZEPHYR_FLASH_CONTROLLER_LABEL );
    if ( flash_dev == NULL )
    {
    printk( "Flash device not bound!\n" );
    return;
    }
    else
    {
    rc = flash_get_page_info_by_offs( flash_dev, fs.offset, &info );
    if ( rc )
    {
    printk( "Unable to get page info" );
    }
    fs.sector_size = info.size;
    fs.sector_count = 3U;

    rc = nvs_init( &fs, DT_CHOSEN_ZEPHYR_FLASH_CONTROLLER_LABEL );
    if ( rc )
    {
    printk( "Flash Init failed\n" );
    }

    size_t page_count = flash_get_page_count(flash_dev);
    printk( "Flash contains %d pages of 4kB each\n", page_count );

    ...

    ...

    Kind regards

    Mohamed

Children
No Data
Related