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

HardFault_Handler() called when NRF_LOG_ENABLED is disabled

In my application when I disable NRF_LOG_ENABLED, HardFault_Handler() is getting called. To debug this issue I defined a HardFault_Handler() in my code and inserted a break point in it. Below is the backtrace

#0  HardFault_Handler () at main.c:165
#1  <signal handler called>
#2  0x0002b870 in fs_init () at ../../../../Tools/nrf_SDK/nRF5x/components/libraries/fstorage/fstorage.c:290
#3  0x0002af96 in fds_init () at ../../../../Tools/nrf_SDK/nRF5x/components/libraries/fds/fds.c:1621
#4  0x00023630 in pds_init () at ../../../../Tools/nrf_SDK/nRF5x/components/ble/peer_manager/peer_data_storage.c:334
#5  0x000245e2 in pm_init () at ../../../../Tools/nrf_SDK/nRF5x/components/ble/peer_manager/peer_manager.c:470
#6  0x00030744 in peer_manager_init (erase_bonds=false) at main.c:1453
#7  0x00030b04 in main () at main.c:1626

I guess something is breaking when fs_init() is called. Note that the application runs just fine when NRF_LOG_ENABLED is set to 1. I am clueless about reason that must be triggering this hard fault? Or how to debug this hardware fault?

Parents
  • Short answer

    This is a memory alignment issue and it got fixed by adding . = ALIGN(4) in my linker script.

    Long answer

    I debugged the code in GDB. Problem gets manifested in the below snippet from fstorage.c

    for (uint32_t i = 0; i < total_users; i++)
    {
        fs_config_t const * const p_config = FS_SECTION_VARS_GET(i);
    
        ==>if ((p_config->p_start_addr != NULL) &&
            (p_config->p_end_addr   != NULL))
        {
            configs_to_init--;
        }
    }
    

    When I step over from this point I end up in the HardFault_Handler(). After investigation, I found that FS_SECTION_VARS_GET(i) is not returning the correct address of fs_config. Then with objdum I checked the addresses of __start_fs_data and fs_config in the object file.

    When NRF_LOG_ENABLED = 1

    200029e4 g       .data  00000000 __start_fs_data
    200029e4 l     O .data  00000010 fs_config
    

    When NRF_LOG_ENABLED = 0

    2000202a g       .data  00000000 __start_fs_data
    2000202c l     O .data  00000010 fs_config
    

    You can see that when NRF_LOG_ENABLED = 0, __start_fs_data is not aligned with fs_config and hence the macro FS_SECTION_VARS_GET(i) returns an address where valid data doesn’t exist, causing a hardware fault.

    Resolution is to add . = ALIGN(4) in your linker file as show below.

    .data : AT(_sidata)
    {
    	. = ALIGN(4);
    	_sdata = .;
    
    	PROVIDE(__data_start__ = _sdata);
    	*(.data)
    	*(.data*)
    
    ==>	. = ALIGN(4);
    
    	PROVIDE(__start_fs_data = .);
    	KEEP(*(.fs_data))
    	PROVIDE(__stop_fs_data = .);
    	
    	. = ALIGN(4);
    	_edata = .;
    
    	PROVIDE(__data_end__ = _edata);
    } > SRAM
    

    I chose to fix it this way, if anyone knows of a better solution then please let me know.

Reply
  • Short answer

    This is a memory alignment issue and it got fixed by adding . = ALIGN(4) in my linker script.

    Long answer

    I debugged the code in GDB. Problem gets manifested in the below snippet from fstorage.c

    for (uint32_t i = 0; i < total_users; i++)
    {
        fs_config_t const * const p_config = FS_SECTION_VARS_GET(i);
    
        ==>if ((p_config->p_start_addr != NULL) &&
            (p_config->p_end_addr   != NULL))
        {
            configs_to_init--;
        }
    }
    

    When I step over from this point I end up in the HardFault_Handler(). After investigation, I found that FS_SECTION_VARS_GET(i) is not returning the correct address of fs_config. Then with objdum I checked the addresses of __start_fs_data and fs_config in the object file.

    When NRF_LOG_ENABLED = 1

    200029e4 g       .data  00000000 __start_fs_data
    200029e4 l     O .data  00000010 fs_config
    

    When NRF_LOG_ENABLED = 0

    2000202a g       .data  00000000 __start_fs_data
    2000202c l     O .data  00000010 fs_config
    

    You can see that when NRF_LOG_ENABLED = 0, __start_fs_data is not aligned with fs_config and hence the macro FS_SECTION_VARS_GET(i) returns an address where valid data doesn’t exist, causing a hardware fault.

    Resolution is to add . = ALIGN(4) in your linker file as show below.

    .data : AT(_sidata)
    {
    	. = ALIGN(4);
    	_sdata = .;
    
    	PROVIDE(__data_start__ = _sdata);
    	*(.data)
    	*(.data*)
    
    ==>	. = ALIGN(4);
    
    	PROVIDE(__start_fs_data = .);
    	KEEP(*(.fs_data))
    	PROVIDE(__stop_fs_data = .);
    	
    	. = ALIGN(4);
    	_edata = .;
    
    	PROVIDE(__data_end__ = _edata);
    } > SRAM
    

    I chose to fix it this way, if anyone knows of a better solution then please let me know.

Children
No Data
Related