Hello guys,
I am new in the BLE world.
I am currently using a BLE Android application running on a tablet + nrf52832 communication with another chip through UART.
I have this weird bug when I try to disconnect the connection from the tablet the nrf52 firmware just crash.
From the Android app I just call
mBluetoothGatt.disconnect();
When the user press disconnect on the tablet. I expect the event BLE_GAP_EVT_DISCONNECTED to be called in the nrf fw. I know the ble_evt_handler is called at least once since when the tablet connect to the device , the BLE_GAP_EVT_CONNECTED event is triggered and processed. But for some reasons I dont get, I dont think the BLE_GAP_EVT_DISCONNECTED is ever triggered since another module is supposed to receive data through UART when this even occurs and the data is never received. Plus it is supposed to advertise again but it does not. Instead I think it just reboots.
So I tried to used JTT viewer to debug with logs and once I connect to my device something weird happen: the UART message I am supposed to send when a disconnection occurs is sent, and the device start advertising again! How is that possible???
This is the code that handles the ble event:
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) { static const char CONNECT[] = "hello"; static const char DISCONNECT[] = "bye"; ret_code_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: NRF_LOG_INFO("ble_evt_handler Connected"); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle); APP_ERROR_CHECK(err_code); // SEND CONNECT to my module through UART ble_atk_send_UART_data(CONNECT,sizeof(CONNECT)); break; case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_INFO("ble_evt_handler Disconnected"); ble_atk_send_UART_data(DISCONNECT,sizeof(DISCONNECT)); // Start advertising again advertising_start(); break;
My main roughly look lie that (simplified)
log_init(); NRF_LOG_INFO("Initialization"); timers_init(); uart_init(); power_management_init(); ble_stack_init(); set_passkey(); NRF_LOG_INFO("BLE Stack Init done"); waitHello(); // wait until we received hello from UART from another module // Last part of the init, once we received HELLO NRF_LOG_INFO("GAP init..."); gap_params_init(); NRF_LOG_INFO("GATT init..."); gatt_init(); NRF_LOG_INFO("Services init..."); services_init(); NRF_LOG_INFO("Peer manager init..."); peer_manager_init(); NRF_LOG_INFO("Connection parameter init..."); //delete_bonds(); conn_params_init(); NRF_LOG_INFO("Advertising init..."); advertising_init(); advertising_start(); for(;;) { nrf_pwr_mgmt_run(); }
First part of the logs when the device start advertising and the android device connect:
As you can see the connection is ok and the last line shows me that the device is successfully disconnected.
But this happens only when RTT Viewer is running and printing logs!!!
If I disconnect RTT Viewer, the BLE_GAP_EVT_DISCONNECTED seems to be never called since no data is sent through UART and the device doesnt advertise again.
As long as RTT viewer is connected everything is OK, as long it is not running, I have this weird bug on disconnect and the device crash.
I know this might be confusing and hard to explain so if you have any ideas... I can provide everything just ask.
Thanks
EDIT:
I did not notice but I was using Debug mode and optimisation 0, so I moved to no debug flag and -O3 and it is better now. I just put a flag in BLE_GAP_EVT_DISCONNECTED and BLE_GAP_EVT_CONNECTED to notice me this event occurred and I will process it directly in the main loop. Now it did the trick. I think I have a lot of BLE events that the handler is sometimes preempted by another ble interrupt.
I dont know exactly what happened but this post helped me out: https://devzone.nordicsemi.com/f/nordic-q-a/25429/application-crash-after-disconnection
maybe I was calling an interrupt with low priority from an interrupt with high priority?
Somehow heavy process must not be done in the ble handler