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

Hardfault triggered after p nrf_fstorage_erase

Hi!

Writing to flash memory.

After calling nrf_fstorage_erase (...) a hardfault happens. It only NOT happens if JLink is enabled (using dbg or rtt logs).
So I can not debug it deeply. I did simple de-bug procedure, with LED flashing the number of cfsr_msgs[]. This number is 10,
meaning [10] = "Data bus error (return address in the stack frame is not related to the instruction that caused the error)".

Looks like the flash area is not erased as the result.

Looks like it happens not every time. I load the program into debugger (it works good), then I go out of the debugger session.
The program continues to run, and after 2 or 3 erase/write cycles it fails and calls for hardfault.

This piece of the program is taken from a working program, so looks like the problem depends on the code size, or RAM map, or
FLASH map. Can not understand.

I know this situation happens with NRF52832 not in first time, as there are some answers in this community already. But it does not help.

Anybody could help me?

Alex. 

Parents
  • Thank you for help.

    In sdk_config.h there are the following lines:

    // <i> NRF_FSTORAGE_SD uses the nrf_fstorage_sd backend implementation using the SoftDevice API. Use this if you have a SoftDevice present.
    // <i> NRF_FSTORAGE_NVMC uses the nrf_fstorage_nvmc implementation. Use this setting if you don't use the SoftDevice.
    // <1=> NRF_FSTORAGE_NVMC
    // <2=> NRF_FSTORAGE_SD

    #ifndef FDS_BACKEND
    #define FDS_BACKEND 2
    #endif

    So, I guess, I use NRF_FSTORAGE_SD

    Also, I write:
    #include "nrf_fstorage_sd.h"


    and here too:

    void fstorage_options_init(void)
    {
        uint32_t addr;
        nrf_fstorage_api_t * p_fs_api;
        ret_code_t ret_code;


        p_fs_api = &nrf_fstorage_sd;
        ret_code = nrf_fstorage_init(&fstorage_options, p_fs_api, NULL);
        APP_ERROR_CHECK(ret_code);

        print_flash_info(&fstorage_options);

    /* 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. */
        addr = nrf5_flash_end_addr_get();
        NRF_LOG_INFO("FLASH end address: 0x%x", addr);


    }



  • Your fstorage_options has to be something like that.


    NRF_FSTORAGE_DEF(nrf_fstorage_t fstorage_options) =
    {
        .evt_handler = fstorage_evt_handler,
        .start_addr  = DATA_START_ADDRESS,
        .end_addr    = DATA_END_ADDRESS
    };

    You have to take care in the region between [DATA_START_ADDRESS - DATA_END_ADDRESS] the application does not put anything.

    Maybe you can define an array of that size and mapp it through the Linker script in that region.

  • nRF_Connect_Programmer_1629478104493.hex

    Do not know about NRF Connect, but if to load my Application.hex file into J-Flash program - it shows, that only the region 0x26000 to 0x6EFFF is occupied

  • All right. Looks like there was some mess with the Soft Device and the Bootloader from the previous runs of the program on this device.

    1) I got to J-Flash, and program Application_complete.hex file into my NRF52832. Application_complete.hex is a merged file of s132_nrf52_7.0.1_softdevice.hex + Application.hex + Bootloader.hex + settings_application.hex. This file does not work properly.

    2) I go to Keil IDE, load the project. which generates Application.hex, and start it in Debug mode. It sometimes work, sometimes not. Note: I have NOT erased Whole chip after J-Link session. So the chip has s132_nrf52_7.0.1_softdevice.hex, Bootloader.hex and  settings_application.hex inside.

    3) I go to J-Flash again, make Whole Chip Erase, load ONLY s132_nrf52_7.0.1_softdevice.hex. Return to Keil, and everything looks like working fine. No Bootloader there. No settings_application.hex.

    Why? Why if not to erase Whole Chip, and not to re-load s132_nrf52_7.0.1_softdevice.hex - why it goes to Bootloader portion of ROM? Is that normal?

    4) I am not sure, that if my Application works fine without Bootloader - it will work good WITH bootloader. I will check it tomorrow or on Monday. Why Bootloader cares about BPROT register?

    Attached is the file, read from the chip with "fresh" softdevice and containing no Bootloader.nRF_Connect_Programmer_1629479650636(No Bootloader).hex

  • I found solution to the problem:

    I got to the Bootloader source code, found procedure "ret_code_t nrf_bootloader_flash_protect(uint32_t address, uint32_t size)", and added a "return" instruction right after the procedure entry:

    #elif defined (BPROT_PRESENT)
    ////////!!!!!!!! Alex
    return NRF_SUCCESS;
    ////////!!!!!!!! Alex

    thus - the Bootloader does not touch BPROT register, I do it myself in my application (first thing).

    Why the Bootloader protects ALL memory, when it only must to protect itself, SoftDevice and Settings - who knows.

    This call looks suspicious:
    // Protect MBR and bootloader code from being overwritten.
    ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE);

    It switches on the protection, starting from the address "0" to the address MBR_SIZE, which is the Bootloader area's start address. So - it protects all pages of my program too.

    Then comes the following instruction:
    ret_val = nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE);
    APP_ERROR_CHECK(ret_val);

    Nobody protects (looks like) the Settings area.

    All right. I will better do it myself in my application.

    BR,
    Alex.

  • Alex@harmoniumLED said:
    It switches on the protection, starting from the address "0" to the address MBR_SIZE, which is the Bootloader area's start address. So - it protects all pages of my program too.

     MBR_SIZE shall always correspond to the size of the MBR. This is not a configurable setting.

  • ok. Got it.

    How about the following call (from Bootloader project's procedure):

    ret_val = nrf_bootloader_flash_protect(0,
    nrf_dfu_bank0_start_addr() + ALIGN_TO_PAGE(s_dfu_settings.bank_0.image_size));

    It protects the area, starting from the address "0", and ending at the address nrf_dfu_bank0_start_addr() + ...

    if not everything is o.k., it reports:
    if (ret_val != NRF_SUCCESS)
    {
    NRF_LOG_ERROR("Could not protect SoftDevice and application, 0x%x.", ret_val);
    }

    Meaning, that in case of success, it will protect all the memory, from the address 0 to the application's memory end, supposed to be equal to the Bootloader's area start.

    At the end, the Bootloader protects all the memory, except the tail, 1 page.

    I got this Bootloader from the directory:
    ... nRF5_SDK_17.0.0_9d13099\examples\dfu\secure_bootloader\pca10040_s132_ble\arm5_no_packs

    May be "secure_bootloader" means "all memory will be protected"? Or - what?

Reply
  • ok. Got it.

    How about the following call (from Bootloader project's procedure):

    ret_val = nrf_bootloader_flash_protect(0,
    nrf_dfu_bank0_start_addr() + ALIGN_TO_PAGE(s_dfu_settings.bank_0.image_size));

    It protects the area, starting from the address "0", and ending at the address nrf_dfu_bank0_start_addr() + ...

    if not everything is o.k., it reports:
    if (ret_val != NRF_SUCCESS)
    {
    NRF_LOG_ERROR("Could not protect SoftDevice and application, 0x%x.", ret_val);
    }

    Meaning, that in case of success, it will protect all the memory, from the address 0 to the application's memory end, supposed to be equal to the Bootloader's area start.

    At the end, the Bootloader protects all the memory, except the tail, 1 page.

    I got this Bootloader from the directory:
    ... nRF5_SDK_17.0.0_9d13099\examples\dfu\secure_bootloader\pca10040_s132_ble\arm5_no_packs

    May be "secure_bootloader" means "all memory will be protected"? Or - what?

Children
  • ret_val = nrf_bootloader_flash_protect(0,
    nrf_dfu_bank0_start_addr() + ALIGN_TO_PAGE(s_dfu_settings.bank_0.image_size));

    It protects the area, starting from the address "0", and ending at the address nrf_dfu_bank0_start_addr() + ..

    I don't know why the application data region is being write protected in your case. This function call you mentioned should only protect the MBR + Softdevice + Application.

    Note that the 2nd argument to nrf_bootloader_flash_protect() is the number of bytes to protect, and the bank0 address is really the same as the size of MBR+Softdevice because the flash starts at address zero.

Related