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

Hardfault in freeRTOS MTU Exchange (MTU>=200)

I'm using the ble_app_grs_freertos example.  I'm trying to maximize its thru-put potential for Central devices which can support the high data rates.  For this I've used the follow GAP Setup parameters.

NRF_SDH_BLE_GAP_DATA_LENGTH 251

NRF_SDH_BLE_GAP_EVENT_LENGTH 6

NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

with a stack configuration of: 

ble_cfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = 4;
err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_cfg, ram_start);

Everything initializes fine and starts advertising.  However when I connect to an iOS nRF Connect App everything crashes.  I hit a hardfault @ 0x0002C03A which lies in the           vTaskSwitchContext call inside the freeRTOS source code.  With the nrf_log on debug I see the following messages from start-up to connection.

<debug> nrf_sdh: State request: 0x00000000
<debug> nrf_sdh: Notify observer 0x00037A9C => ready
<debug> nrf_sdh: State change: 0x00000000
<debug> nrf_sdh: State change: 0x00000001
<debug> nrf_sdh_ble: RAM starts at 0x20002D88
<debug> nrf_sdh_freertos: Creating a SoftDevice task.
<debug> nrf_sdh_freer<debug> nrf_sdh_ble: BLE event: 0x10.
<debug> nrf_ble_gatt: Requesting to update ATT MTU to 247 bytes on connection 0x0.
<debug> nrf_ble_gatt: Updating data length to 251 on connection 0x0.
<info> app: Connected
<debug> nrf_sdh_ble: BLE event: 0x24.
<debug> nrf_ble_gatt: Data length updated to 27 on connection 0x0.
<debug> nrf_ble_gatt: max_rx_octets: 27
<debug> nrf_ble_gatt: max_tx_octets: 27
<debug> nrf_ble_gatt: max_rx_time: 328
<debug> nrf_ble_gatt: max_tx_time: 328
<debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
<debug> nrf_sdh_ble: BLE event: 0x3A.
<debug> nrf_ble_gatt: ATT MTU updated to 185 bytes on connection 0x0 (response).
<debug> app: ATT MTU exchange completed. central 0xF7 peripheral 0xF7
<error> hardfault: HARD FAULT at 0x0002C03A
<error> hardfault: R0: 0x00000040 R1: 0x20005EDC R2: 0x20005E04 R3: 0x002B5E18
<error> hardfault: R12: 0xA5A5A5A5 LR: 0x0002A791 PSR: 0x8100020E
<error> hardfault: Cause: Data bus error (PC value stacked for the exception return points to the instruction that caused the fault).
<error> hardfault: Bus Fault Address: 0x002B5E24

As a note I did update the linker file to the following settings: RAM (rwx) :  ORIGIN = 0x20002d88, LENGTH = 0xC8E8

The odd thing is if I reduce the MTU size to 198 everything works fine.  Any ideas?  This whole data-thruput maximization seem to have alot of moving parts, making it.  

EDIT:  This was addressed in the latest SDK update.  Thanks

  • This seems like a classic stack overflow symptom.  Try increasing the size of the FreeRTOS stack used to handle SoftDevice events in nrf_sdh_freertos.c.

    Events from the SoftDevice are polled in nrf_sdh_ble.c.  Each event is retrieved into a RAM buffer allocated on the stack prior to handling.  As you increase NRF_SDH_BLE_GATT_MAX_MTU_SIZE, the size of the buffer on the stack required to receive events from the SoftDevice also increases.

    The default NRF_BLE_FREERTOS_SDH_TASK_STACK size is 256, so as your MTU approaches that limit, the buffer required during event handling is likely spanning over the the allocated task stack, resulting in a stack overflow.

    Although not always reliable, it's probably a good idea to turn on stack overflow detection within FreeRTOS.

    It would be possible to add a compile time check in nrf_sdh_freertos.c which reports an error when the MTU is too large for the allocated stack.  The stack size needs to be larger than the MTU to allow for event handler function calls and their stack usage.

  • I tried increasing the size of NRF_BLE_FREERTOS_SDH_TASK_STACK to 4096  and even moved the definition of this to FreeRTOSConfig as it makes more sense to control it there.  However I still the same hardfault with the follow BLE settings:

    NRF_SDH_BLE_GAP_DATA_LENGTH 251

    NRF_SDH_BLE_GAP_EVENT_LENGTH 6

    NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

    Is there any guide for both setting these parameters and adjusting RAM allocation accordingly?

  • I would have thought that this is FreeRTOS stack corruption, which is most likely too little stack size left for either app or freertos. How much RAM was left for the app overall?

  • I set the linker file to:

    RAM (rwx) :  ORIGIN = 0x20002d88, LENGTH = 0xC8E8

    After initializing the stack the ram_start shows I could reduce the App RAM start to 0x20002CC0

    Also in FreeRTOSConfig.h

    configTOTAL_HEAP_SIZE                                                     ( 28000 )

  • i did not get any hardfault .. when i changed those two macros. I tested this on hrs freertos example on SDK15. what am i doing wrong(or right?)

Related