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

ble_app_nus_multilink_central error analysis

I use SDK16.0.0 and SD7.0.1-S132 Implement NUS functions, 1 * ble_central and 6 * ble_peripheral.
The uart of ble_central connect to STM32MCU.
My system run as follows, 6 * ble_peripheral data upload per second, 1 * ble_central send command to ble_peripheral one by one per 200ms.
When it runs for a while, the host is error "NRF_ERROR_SVC_HANDLER_MISSING", source code as below.

void uart_event_handle(app_uart_evt_t * p_event)//串口事件回调函数,串口初始化时注册,该函数中判断事件类型并进行处理
{
    //当接收的数据长度达到设定的最大值或者接收到换行符后,则认为一包数据接收完成,之后将接收的数据发送给从机
    static uint8_t data_array[BLE_NUS_MAX_DATA_LEN];
    static uint16_t index = 0;
    uint32_t ret_val;
    uint16_t con_handle;
    static uint8_t len = 6;
    switch (p_event->evt_type)//判断事件类型
    {
        /**@snippet [Handling data from UART] */
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
            //回传接收到的串口数据
            //app_uart_put(data_array[index]);
            index++;
            if (((data_array[index - 2] == '\r') &&
                 (data_array[index - 1] == '\n')) ||
                 (index >= (m_ble_nus_max_data_len)))//串口数据接收完成
            {
                //NRF_LOG_INFO("index: 0x%x",index);
                con_handle =set_con_handle(&m_ble_nus_c[0],data_array);

                NRF_LOG_DEBUG("Ready to send data over BLE NUS");
                NRF_LOG_HEXDUMP_DEBUG(data_array, index);

                if(con_handle != 0xFFFF)
                {
                    do
                    {
                        //NRF_LOG_INFO("send con_handle 0x%x",con_handle);
                      //index:   会把最后两个字节结束符0D 0A发送给从站
                      //index-2: 从站可以接收完整数据,但是解析错误
                      //index-1: 把第一个结束符0D和数据一起发送给从站,解析正确
                        ret_val = ble_nus_c_string_send(&m_ble_nus_c[con_handle], data_array, index-1);
                        if ( (ret_val != NRF_ERROR_INVALID_STATE) && (ret_val != NRF_ERROR_RESOURCES) )
                        {
                            APP_ERROR_CHECK(ret_val);
                        }
                    } while (ret_val == NRF_ERROR_RESOURCES);

                    ret_val = bsp_indication_set(BSP_INDICATE_SENT_OK);
                    APP_ERROR_CHECK(ret_val);
                }
                index = 0;
            }
            break;

        /**@snippet [Handling data from UART] */
        case APP_UART_COMMUNICATION_ERROR://通讯错误事件,进入错误处理
            NRF_LOG_ERROR("Communication error occurred while handling UART.");
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR://FIFO错误事件,进入错误处理
            NRF_LOG_ERROR("Error occurred in FIFO module used by UART.");
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}

Why appear APP_UART_COMMUNICATION_ERROR, Is it that the host(STM32MCU) sends the commands too fast? Line 771 of code, the error code "NRF_ERROR_NO_MEM" appears before
When disconnect, some ble_peripheral is error "Unknown error code", source code as below.

uint8_t ble_send(uint8_t * str, uint16_t length)
{
    uint32_t err_code;
	
	if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
		return 0;
	err_code = ble_nus_data_send(&m_nus, str, &length, m_conn_handle);

	if (err_code != NRF_ERROR_INVALID_STATE)
	{	
		APP_ERROR_CHECK(err_code);
	}
	
//	for (uint32_t i = 0; i < length; i++)
//        {
//				NRF_LOG_INFO("%02x", str[i]);
//        }
		
	err_code = bsp_indication_set(BSP_INDICATE_SENT_OK);
	APP_ERROR_CHECK(err_code);
	
	return 1;
}

I wonder if the release program needs to block error code detection?
if (p_event->data.error_communication == NRF_ERROR_SVC_HANDLER_MISSING)
{
    NVIC_SystemReset();
}
else
    APP_ERROR_HANDLER(p_event->data.error_communication);

Many thanks and best regards!
John

Parents
  • Hi John, 
    I don't think the error is actually NRF_ERROR_SVC_HANDLER_MISSING. 

    error_communication doesn't point to NRF_ERROR_* error. It contain the ERRORSRC register from UART. and here error number 1 equal OVERRUN error (please check the product product specification):

    "A start bit is received while the previous data still lies in RXD."

    Seems that the UART was overrun because the data still in RX and new start bit already started. 

    Do you use HWFC ? 

    When you have multiple devices connected to the device, the latency caused by the softdevice can be large and you can be overruned if you don't use Easy DMA properly and don't use HWFC.

  • Hi Hung,

    Update. Use the below code to help me analyze the cause of the error is OVERRUN_Msk. If there is a better solution instead of me commenting out error detection?

    case APP_UART_COMMUNICATION_ERROR:
        NRF_LOG_ERROR("Communication error occurred while handling UART: %08X", p_event->data.error_communication );
    
        if( p_event->data.error_communication & UART_ERRORSRC_OVERRUN_Msk )
        {
            NRF_LOG_ERROR("   Overrun");
        }
        // ### Ignore: APP_ERROR_HANDLER(p_event->data.error_communication);            break;
        break;

    Many thanks and best regards!

    John

  • If you don't use HWFC this is something expected especially when you have high BLE activity (that the softdevice occupies the CPU). 

    You may want to reduce the UART baudrate or define a protocol on how the UART should work, use EasyDMA could be an option. Have a look at this libuarte here: https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.0.0/libuarte_example.html?cp=7_1_4_6_17

    If the Overrun error (the previous and current packet will be corrupted) is not and issue and you can ignore it and retransmit then you can ignore the event. 

Reply Children
No Data
Related