HardFault in SoftDevice @ 0x20B55

Hi

I have a hardfault which was triggered at address 0x20B55. The memory region from the SoftDevice is from 0x1000 – 0x26633.

Can you tell me what is the root cause of this HardFault? I have no access to this region because its inside of the softdevice.

I found this, but the I don't know the root cause to fix the problem asap.

HardFault Status Register (HFSR) - 0xE000ED2C

This registers explains the reason a HardFault exception was triggered.

There’s not too much information in this register but we will go over the fields real quickly

  • DEBUGEVT- Indicates that a debug event (i.e executing a breakpoint instruction) occurred while the debug subsystem was not enabled
  • FORCED- This means a configurable fault (i.e. the fault types we discussed in previous sections) was escalated to a HardFault, either because the configurable fault handler was not enabled or a fault occurred within the handler.
  • VECTTBL- Indicates a fault occurred because of an issue reading from an address in the vector table. This is pretty atypical but could happen if there is a bad address in the vector table and an unexpected interrupt fires.

Parents Reply
  • 1) Unfurtenatly we have no debugger connected

    The hardfault handler is enabled.

    #define HARDFAULT_HANDLER_ENABLED 1

    The call is from this code:

    void HardFault_Handler(void)
    {
    	uint32_t* sp = (uint32_t*) __get_MSP();  // Get stack pointer
    	uint32_t ia = sp[12]; // Get instruction address from stack
    	m_hardfault_type = hardfault_hardfault;
    	m_hardfault_address = ia;
    	printf("Hard Faults at address: 0x%08x\r\n", (unsigned int)ia);
    	hal_ext_uart_buffer_flush();    // print out all bytes
    
    	while (1)
    		;
    }
    

    I will try to get some more detialed information about the hardfault

Children
  • We got additional information about an occured HardFault right now, maybe you can help us to clarify the root cause of this:

    CFSR Bit 17 ->  [17] = "The processor has attempted to execute an instruction that makes illegal use of the EPSR",

    HFSR Bit 30 ->   FORCED - This means a configurable fault (i.e. the fault types we discussed in previous sections) was escalated to a HardFault, either because the configurable fault handler was not enabled or a fault occurred within the handler.

    We are working with the SoftDevice 7.2.0 S140, the 7.3.0 is available, could this be a try to upadte or what do you guess?

    Thank you

  • Dominik Eugster said:
    We are working with the SoftDevice 7.2.0 S140, the 7.3.0 is available, could this be a try to upadte or what do you guess?

    No, I don't think SD version have something to do with this.

    Dominik Eugster said:

    Most common way to get a hardfault when calling a sd_ function, is that it's called from a context that is in a too high interrupt priority level. So you should try lowering the interrupt priority for the context you are calling sd_ble_gatts_value_set() from.

  • this is called from a app_timer_create with interrupt priority 6.

    // <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #define APP_TIMER_CONFIG_IRQ_PRIORITY 6
    
    ret_code_t app_timer_init(void)
    
    #define SWI_IRQ_PRI             APP_TIMER_CONFIG_IRQ_PRIORITY               /**< Priority of the SWI  interrupt (used for updating the timer list). */
    
    NVIC_ClearPendingIRQ(SWI_IRQn);
    NVIC_SetPriority(SWI_IRQn, SWI_IRQ_PRI);
    NVIC_EnableIRQ(SWI_IRQn);

  • Dominik Eugster said:

    this is called from a app_timer_create with interrupt priority 6.

    Ok, good.

    Is this consistent? Does it always happen when you call sd_ble_gatts_value_set()?

    Could you show your code that calls sd_ble_gatts_value_set() ?

  • No, it's not alway happening. It happens during runnning realease without debugger every some days which makes it really difficult to get the root-cause. Its running in a mesh struct of 28 devices connected over the BLE-mesh.

    uint32_t common_ble_gatt_custon_name_write(ble_cus_t* p_cus, uint8_t* p_msg, uint8_t len)
    {
    	BLE_CUS_PRINTF("-- ble gatt custom name write\r\n");
    
    	if (p_cus == NULL)
    	{
    		return NRF_ERROR_NULL;
    	}
    
    	uint32_t err_code = NRF_SUCCESS;
    	ble_gatts_value_t gatts_value;
    	// Initialize value struct.
    	memset(&gatts_value, 0, sizeof(gatts_value));
    	gatts_value.len     = len;
    	gatts_value.offset  = 0;
    	gatts_value.p_value = p_msg;
    	// Update database.
    	err_code = sd_ble_gatts_value_set(p_cus->conn_handle,
    	                                  p_cus->custom_value_2_handles.value_handle,
    	                                  &gatts_value);
    	return err_code;
    }
    
    .... 
    
    uint32_t common_ble_gatt_custon_uart_write(ble_cus_t* p_cus, uint8_t* p_msg, uint8_t len)
    {
    	if (p_cus == NULL)
    	{
    		return NRF_ERROR_NULL;
    	}
    
    	//BLE_CUS_PRINTF("-- ble gatt custom uart write\r\n");
    	BLE_CUS_PRINTF("send msg size %d, 0x", len);
    
    	for (uint8_t i = 0; i < len; i++)
    	{
    		BLE_CUS_PRINTF("%02X", p_msg[i]);
    	}
    
    	//BLE_CUS_PRINTF("\r\n");
    	BLE_CUS_PRINTF(" - ");
    	uint32_t err_code = NRF_SUCCESS;
    	ble_gatts_value_t gatts_value;
    	// Initialize value struct.
    	memset(&gatts_value, 0, sizeof(gatts_value));
    	gatts_value.len     = len;
    	gatts_value.offset  = 0;
    	gatts_value.p_value = p_msg;
    	// Update database.
    	err_code = sd_ble_gatts_value_set(p_cus->conn_handle,
    	                                  p_cus->custom_value_1_handles.value_handle,
    	                                  &gatts_value);
    
    	if (err_code != NRF_SUCCESS)

Related