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

nrf_UART freeze when disconnect during sending message - nrf51822

Good afternoon all,

We have seen something with nrf51822 a little bit unusual that we can't explain and that maybe some of you have already experienced.

In main loop, we have a switch() and, depending on some external command, we run different function. One of this function is emptying our memory and send all messages using ble_nus_buffer_send(Message, sizeof(Message)

However, if the module disconnect precisely during sending a message, nothing is return and the software stay stuck in the main loop (this is what we think is happening).

The only way we have to get out of this situation (stuck in main loop) is to have a function that sends a message using the same ble_nus_buffer_send(Message, sizeof(Message) function but called by static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length) (that is outside main loop). Then the module continue to run properly...

How could we prevent the module to stay stuck in this context (disconnection during ble_nus_buffer_send). Is a timeout possible?

Anyone of you have have a module stuck when disconnection happens during send UART message?

See functions below for details. Thank you very much!

ble_nus_buffer_send called is called in a function called in the main loop...

U8 ble_nus_buffer_send(uint8_t * abuffer, uint32_t alength)
{
uint32_t sublength, err_code;

if(m_conn_handle == BLE_CONN_HANDLE_INVALID) return 0;

LED_Off();

while(alength)
{
if(alength > BLE_NUS_MAX_DATA_LEN)
  sublength = BLE_NUS_MAX_DATA_LEN;
else
  sublength = alength;

BtDataTxComplete = 0;
err_code = ble_nus_string_send(&m_nus, abuffer, sublength);
if(err_code != NRF_SUCCESS) return 0;
while(BtDataTxComplete == 0) {}; //nrf_delay_ms(1);
            
abuffer += sublength;
alength -= sublength;
}

LED_On();

return 1;
}

AND

uint32_t ble_nus_string_send(ble_nus_t * p_nus, uint8_t * p_string, uint16_t length)
{
ble_gatts_hvx_params_t hvx_params;

if (p_nus == NULL)
{
    return NRF_ERROR_NULL;
}

if ((p_nus->conn_handle == BLE_CONN_HANDLE_INVALID) || (!p_nus->is_notification_enabled))
{
    return NRF_ERROR_INVALID_STATE;
}

if (length > BLE_NUS_MAX_DATA_LEN)
{
    return NRF_ERROR_INVALID_PARAM;
}

memset(&hvx_params, 0, sizeof(hvx_params));

hvx_params.handle = p_nus->rx_handles.value_handle;
hvx_params.p_data = p_string;
hvx_params.p_len  = &length;
hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;

return sd_ble_gatts_hvx(p_nus->conn_handle, &hvx_params);
}
  • FormerMember
    0 FormerMember

    How does the sudden disconnect occur? Does the central stop responding? If so, the peripheral device will try to send the ongoing notification until the connection supervision timeout. At connection supervision timeout, the peripheral device will consider the link as lost, and the application will receive the event BLE_GAP_EVT_DISCONNECTED.

    In BLE, all "events" are independent transactions. It means that there should not be a problem to disconnect at any time.

    nus_data_handler is "called" from a BLE event, so it's priority will be the same as for BLE events, APP_IRQ_PRIORITY_MID.

    It may not be relevant for the problem, but when sending notifications, I would recommend you to check the error code so that you can differentiate between the various error codes. BLE_ERROR_NO_TX_PACKETS means for instance that the TX buffer is full, so you should wait for BLE_EVT_TX_COMPLETE before adding new packets to the buffer.

Related