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

ble_nus_data_send return value invokes hardfault_interrupt

Hey everyone,

I've got an nRF52840 DK on my hands. There's an interesting crash occurring when the return value from ble_nus_data_send() is passed to APP_ERROR_CHECK(). Here's what's going on.

The device (nRF52840 DK) is collecting some information and passing it on through Nordic UART Service (NUS); I've basically modified the ble_app_uart example that came with SDK 15.2 and mashed it with peripheral_long_range example (from 15.0, I think). NUS service is initialized at the beginning before the main loop. There's also a timer that is initialized to execute every second and its timeout handler sends data using ble_nus_data_send(). The code compiles ok and runs well on the first instance that a device connects to it. There are no random disconnection issues.

However, when the connected device disconnects and tries to reconnect, nRF52840 crashes and resets. I've managed to trace back the issue with the debugger to the timeout handler of the mentioned timer. Here's the Call Stack:

void app_error_fault_handler(unsigned int id=0x00000000, unsigned int pc = 0x3ff00000, unsigned int info = 0x00000000)

void app_error_handler_bare(unsigned int error_code = 0x00003401)

void packet_tx_event_handler(void* p_context = 0x00000000)

void RTC1_IRQHandler()

Specifically, the APP_ERROR_CHECK(err_code) line in the following code block is what causes the hardfault_interrupt to be invoked:

do
{
    uint16_t length = (uint16_t)strlen((char *)output_data);
    err_code = ble_nus_data_send(&m_nus, output_data, &length, m_conn_handle);
    
    if ((err_code != NRF_ERROR_INVALID_STATE) &&
        (err_code != NRF_ERROR_RESOURCES) &&
        (err_code != NRF_ERROR_NOT_FOUND))
    {
        APP_ERROR_CHECK(err_code);
    }
} while (err_code == NRF_ERROR_RESOURCES);

Interestingly, if I comment out the APP_ERROR_CHECK(err_code) line, the crash goes away and the device works just fine on reconnection.

Here are additional information on the development environment:

  • IDE: SES
  • SDK: 15.2
  • Mobile Device: Samsung S10+ (for Coded PHY / Long Range)

What's causing the crash? Debugging shows that the usual value of err_code is 0x00 which I think is the same as NRF_SUCCESS. So, I can't understand why commenting out APP_ERROR_CHECK() would cause this behavior on reconnection.

  • Hi,

     

    The error_code of 0x3400 indicates this base:

    #define NRF_GATTS_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x400) /**< GATT server specific errors. */

    And 0x3401 is:
    BLE_ERROR_GATTS_SYS_ATTR_MISSING

    This means that the CCCDs have not been set, ie. the permissions for the peripheral to send data via indication/notification to the central, has not been enabled by the central device yet.
    You can either omit this returned err_code for this specific use-case, or just wait until the central has set these.

     

    Kind regards,
    Håkon

  • Hi Hakon,

    Looks like I commented out this part of the code while merging the two projects:

    static void conn_params_init(void)
    {
      uint32_t               err_code;
      ble_conn_params_init_t cp_init;
    
      memset(&cp_init, 0, sizeof(cp_init));
    
      cp_init.p_conn_params                  = NULL;
      cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
      cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
      cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
      cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
      cp_init.disconnect_on_fail             = false;
      cp_init.evt_handler                    = on_conn_params_evt;
      cp_init.error_handler                  = conn_params_error_handler;
    
      err_code = ble_conn_params_init(&cp_init);
      APP_ERROR_CHECK(err_code);
    }

    Making this call in the main along with a few other adjustments has made the code work fine. I'll have a look at CCCD and what it does.

    By any chance, would CCCD be related to GATT error (0x85) and GATTC error (0x8)?

  • Those sound like peer side errors.

    CCCDs are essentially the permission fields that allows the peripheral to send to the central, so I suspect yes.

     

    Kind regards,

    Håkon

Related