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

NRF_ERROR_SVC_HANDLER_MISSING error when sending data via UART nRF52840

Hello,

Hardware: nRF52840

SKD: nRF5_SDK_16.0.0

SoftDevice v7.0.1

I am working on creating a multilink central application where my central device connects to 3 peripherals. I used the multilink_central and the ble_app_uart_c examples to start my project. My code mostly works as expected. I can connect to the 3 devices and send data back and forth. However, sometimes I get the NRF_ERROR_SVC_HANDLER_MISSING error in APP_UART_COMMUNICATION_ERROR when I use the UART to send data. The error mostly appears when I try to send data via the UART once I reach the BLE_GAP_EVT_AUTH_STATUS.

case BLE_GAP_EVT_AUTH_STATUS:
    NRF_LOG_INFO("BLE_GAP_EVT_AUTH_STATUS: status=0x%x bond=0x%x lv4: %d kdist_own:0x%x kdist_peer:0x%x",
                  p_gap_evt->params.auth_status.auth_status,
                  p_gap_evt->params.auth_status.bonded,
                  p_gap_evt->params.auth_status.sm1_levels.lv4,
                  *((uint8_t *)&p_gap_evt->params.auth_status.kdist_own),
                  *((uint8_t *)&p_gap_evt->params.auth_status.kdist_peer));
    ble_uart_handler_t event;
    event.conn_handle = p_gap_evt->conn_handle;
    event.auth_status = p_gap_evt->params.auth_status.auth_status;
    event.bonded      = p_gap_evt->params.auth_status.bonded;
    event.evt_state   = EVT_BOND_STATE;
    response_send(event);  
    
break;

void response_send(ble_uart_handler_t p_data)
{
... // Collecting the read information and filling output_buffer

    // Send response.
    ret_code_t ret_val;
    for(uint32_t i = 0; i < output_length; i++){
        do
        {
            ret_val = app_uart_put(output_buffer[i]);
            if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
            {
                NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
                APP_ERROR_CHECK(ret_val);
            }
        } while (ret_val == NRF_ERROR_BUSY);
    }
    
    memset(p_data.rsp_buf, 0, index);
    memset(output_buffer, 0, sizeof(output_buffer));
}

Additionally from the above area, sometimes, the error also appears randomly when sending data via the UART using the same "response_send" function mentioned above. 

I am currently using the app_uart_fifo library (as used in the ble_app_uart_c example) with a baud rate of 115200.

I tried fixing this issue increasing the UART_TX_BUF_SIZE and the RAM, but this didn't help. Also, researching online, the majority of the people recommended to use flow control to fix this problem, but my device does not have access to the CTS and RTS pins, so I cannot take that route. 

Error message: 

<info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x0 bond=0x1 lv4: 0 kdist_own:0x3 kdist_peer:0x3
<debug> app: Sending signal
<error> app: Communication error occurred while handling UART
<error> app: ERROR 1 [NRF_ERROR_SVC_HANDLER_MISSING] at C:\nano\nano2_5\ble_nrf\app\src\main.c:675
PC at: 0x00033783
<error> app: End of error report

I am kinda lost right now, so any input will be really appreciated. 

Parents
  • Hi AAtpa

     I get the NRF_ERROR_SVC_HANDLER_MISSING error in APP_UART_COMMUNICATION_ERROR when I use the UART to send data

    I think the error here is a bit misleading. When you get  APP_UART_COMMUNICATION_ERROR  the error number that is passed to the APP_ERROR_HANDLER is p_event->data.error.error_mask which is equal to nrf_uarte_errorsrc_get_and_clear(p_uarte); from the nrfx_uartx.c . This is the value of the ERRORSRC register of the UART with BIT A set. This is the OVERRUN error. The error number 1 in APP_ERROR_CHECK is misleading but let us focus on the main problem.

    The main problem you have is the overrun error. This is caused mostly when you do not have hardware flowcontrol and your application/uart_driver is not able to pull enough bytes in time from the RX register of the uart. There are many reasons why this happens but mostly due to higher priority contexts not giving uart driver CPU time to pull data. I would suggest you to try to init the uart with higher priority APP_IRQ_PRIORITY_HIGH. This is the best shot we have without the flow control, giving the uart_drv a bit higher priority (still lower than SD BLE activity) and we can this way reduce the probability of this error.

    Irrespective of that, I would suggest you to handle this error gracefully in your application since without flowcontrol, there is always a possibility of overrun error and you should handle this in your application.

  • Hi Susheel, thank you for the recommendations. By increasing the UART priority fixed the issue of the error appearing randomly after all connections were fully successful. Unfortunately, the error still happening when I use the UART at BLE_GAP_EVT_AUTH_STATUS while establishing the connection to a peripheral.

    I included a function on app_uart_fifo.c following the code from https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk5.v14.2.0/lib_fifo.html?cp=4_0_2_3_14_7#lib_app_fifo_size  to verify if the FIFO was full before sending the message. But, it doesn't appear it is my issue since I am still getting the error.

    while(app_uart_fifo_free(output_length) < 0){}
    
    // Send response.
    ret_code_t ret_val;
    for(uint32_t i = 0; i < output_length; i++){
        do
        {
            ret_val = app_uart_put(output_buffer[i]);
            if ((ret_val != NRF_SUCCESS) && (ret_val != NRF_ERROR_BUSY))
            {
                NRF_LOG_ERROR("app_uart_put failed for index 0x%04x.", i);
                APP_ERROR_CHECK(ret_val);
            }
        } while (ret_val == NRF_ERROR_BUSY);
    }
    
    ...
    
    int32_t app_uart_fifo_free(uint32_t needed_size)
    {
       uint32_t err_code;
       uint32_t data_len;
    
       // Request number of elements that can be written to the FIFO
       err_code = app_fifo_write(&m_tx_fifo, NULL, &data_len);
       
       // Check if request was successful
       if (err_code == NRF_ERROR_NO_MEM || needed_size > data_len)
       {
          // FIFO is full
          return -1;
       }
       else if (err_code == NRF_SUCCESS)
       {
          // data_len contains the number of bytes that can be written
          return data_len;
       }
       else
       {
          // API parameters incorrect, should not happen
          return -2;
       }
    }

  • You have a while(app_uart_fifo_free(output_length) < 0) {} instide an event handler which is an interrupt handler? Normally you should avoid as much as possible any busy waiting or and busy loops inside any interrupt handlers (events come to application in the SWI interrupt context). Many times they cause deadlocks or timeouts.

  • Hi Susheel, sorry for the confusion. I added that while loop there just to verify if the FIFO was full at the moment of getting the error. This loop is not intended to be part of the final coded.


    I ran an additional test reducing the baud rate from 115200 to 9600 to verify if the error was still present. After a couple of hours running multiple tests, I didn't see the error even once. This indicates, as you mentioned above, that the error may be originated at the moment of reading the UART. Do you have any other suggestions that I could try at this point? 

  • AAtpa,

    There are only three ways to remove the error.

    1. Add HW flow control
    2. reduce the operational baudrate
    3. Make sure that the uart post processing of one transaction is faster than the bytes received into the FIFO (including worst case scenarios of any other higher priority context stealing the CPU). 

    The 3rd one will be very hard for you to fine tune and would need you to understand the details timings of all the BLE activity. it would also need you to optimize your UART RX post processing to a bare minimal in the interrupt context.

  • Thank you Susheel for your suggestions. I was able to run the code without issue by dropping the baud rate from 115200 to 76800. I am focusing my investigation following your suggestions and also investigating the DLE and MTU connection with all the peripherals. 

Reply Children
No Data
Related