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 whith uart

When I use the uart to transparently transmit, there is no problem at around 4k/s. When I increase the transparent transmission rate, there will be NRF_ERROR_SVC_HANDLER_MISSING this error in the APP_UART_COMMUNICATION_ERROR event. 

What is the reason, I have been unable to find the reason, if you want a higher transmission rate, what should I do, I do not want to use flow control, dma is not a better choice?

Parents
  • Hi,

    I believe that the error is really NRF_UARTE_ERROR_OVERRUN_MASK. Please check this by taking a look at the value of app_uart_evt_t::error_communication when the error occurs. As indicated here, the value is 1 when the UART is overrun.

    Please enable the EasyDMA if you have not already done that, and see if it improves the situation.

  • but i find this error only 1kb/s  this sometimes , which is strange,  what happen , is this  error code of myself?

  • My original code is on NRF52810. This problem does not occur, but I have this problem when I ported to 52832. I try I don't change the routine ble_app_uart, just change the logic part, but this problem still occurs.

    When you ported from nRF52810 to nRF52832, did you turn off EasyDMA ?

    How much time are you spending in the uart_event_handle() ?

    I see that you have a function uart_rec_process(), what are you doing here?

    I also see that you are using the FIFO, maybe you could move the processing to main context ? Pop the FIFO in main with app_fifo_get(), and do the proccesing there?

  • /**
     * #brief Ble notify data function.
     * 
     * #called by  ref@uart_rec_process() - #Condition Complete Packet;
     *             ref@uart_rec_process() - #Condition Incomplete Packet;
     *             ref@on_ble_evt()       - #Case      BLE_EVT_TX_COMPLETE.
     */
    static void ble_data_notify_handler(void * p_context)
    {   
        if (is_device_connect() == false) {
            return;
        }
        uint32_t  err_code = ble_nus_string_send(&m_nus, m_temp_array.data, (uint16_t *)&m_temp_array.size);
        if (err_code == NRF_SUCCESS) {
            //! �ɹ�֪ͨһ�����ݣ�����һ�α�ʾ�Է��ɷ���
            nrf_gpio_pin_clear(FIFO_FULL_PIN);
            NRF_LOG_WARNING("noty ok [%d]###\r\n", m_temp_array.size);
    
            //! ��������Э��ջbuffer�ɹ�, �����̬��������.
            memset(&m_temp_array, 0, sizeof(m_temp_array));
            
            //! �ϴ���������Э��ջbufferʧ��, ���γɹ������ٴμ���uart fifo, �鿴ʱ���ж�������.
            if (m_uart_rec_states == UART_REC_DATA_PASS_WAIT /**#Condition.*/) {
                m_uart_rec_states /**#StatesChange.*/ = UART_REC_DATA_PASS;
                APP_ERROR_CHECK(app_sched_event_put((void *)0, 0, uart_rec_process));
            }
        }
    
        else 
        if (err_code == NRF_ERROR_RESOURCES) {
            NRF_LOG_WARNING("buf exce\r\n");
            m_uart_rec_states /**#StatesChange.*/ = UART_REC_DATA_PASS_WAIT;
            return;
        }
    
        else 
        if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING || 
                err_code == NRF_ERROR_INVALID_STATE) {
                NRF_LOG_WARNING("ignor error\r\n");
            //! ������Щ���������Ӵ����Ĵ���.
        } 
        
        else {
            NRF_LOG_WARNING("error check\r\n");
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    /**
     * #brief UART rec process function.
     *
     * #called by ref@uart_event_handle()       - #Case      - APP_UART_DATA_READY;
     * #called by ref@ble_data_notify_handler() - #Condition - NRF_SUCCESS, #Scheduled.
     */
    static void  uart_rec_process(void * p_context, uint16_t data_length) 
    {
        static uint8_t fifo_buffer[32];
        if (is_device_connect() == true /**< ������״̬�£��������ݶ�������Ϊ͸������ */) {
        // if ( 1 ) {
            m_uart_rec_states = (m_uart_rec_states == UART_REC_IDLE)? UART_REC_DATA_PASS : m_uart_rec_states;
    
            APP_ERROR_CHECK(app_simple_timer_stop());
            uint8_t tmp_mid_data = 0;
    
            while (app_fifo_get(&m_uart_rec_fifo, &tmp_mid_data) == NRF_SUCCESS) {
                m_temp_array.data[m_temp_array.size++] = tmp_mid_data;
    
                //! �����ݴﵽ��󳤶ȼ����Խ���������ȫ�����ͳ�ȥ.
                if (m_temp_array.size >= m_ble_nus_max_data_len) {
                    // NRF_LOG_WARNING("size : %d \r\n",m_temp_array.size);
                    ble_data_notify_handler(NULL);
                    if (m_uart_rec_states == UART_REC_DATA_PASS_WAIT /**#Condition.*/) {
                        NRF_LOG_WARNING("uart wait\r\n");
                        //! DPASS WAIT 0
                        return;
                    }
                }
            }
    
    
            if (m_temp_array.size > 0 && /**< ���ݴղ���һ�����ֽڵ����, ��ʱ�жϺ���. */
                m_temp_array.size < m_ble_nus_max_data_len) {
                APP_ERROR_CHECK(app_simple_timer_start(APP_SIMPLE_TIMER_MODE_SINGLE_SHOT, 
                                                       ble_data_notify_handler,
                                                       APP_TIMER_TICKS(600), 
                                                       NULL));
            }
        } else { /**< �ڷ�����״̬�£��������ݶ�������Ϊ��������. */
                
            while (app_fifo_get(&m_uart_rec_fifo, fifo_buffer + m_temp_array.size) == NRF_SUCCESS) {
                APP_ERROR_CHECK(app_timer_stop(uart_clear_id));
                APP_ERROR_CHECK(app_timer_start(uart_clear_id, APP_TIMER_TICKS(200), NULL));
                if (m_temp_array.size >= 9 && m_temp_array.size <= (COMMAND_MAX_LEN-1)) {
                    if (memcmp(fifo_buffer + (m_temp_array.size -1), (uint8_t *)COMMAND_END_STR, 2) == 0) {
                        APP_ERROR_CHECK(app_timer_stop(uart_clear_id));
                        APP_ERROR_CHECK(app_simple_timer_stop());
                        memcpy(m_temp_array.data, fifo_buffer, m_temp_array.size + 1);
                        APP_ERROR_CHECK(app_simple_timer_start(APP_SIMPLE_TIMER_MODE_SINGLE_SHOT, 
                                                   uart_cmd_process_handler,
                                                   APP_TIMER_TICKS(UART_REC_WAIT_INTERVAL), 
                                                   NULL));
                    } 
                } 
    
                m_temp_array.size ++;
            }
    
            /* ���ڷ��͵������������ָ������*/
            if (m_temp_array.size > COMMAND_MAX_LEN) {
                NRF_LOG_RAW_INFO(">COMMAND_MAX_LEN stop timer\r\n");
                APP_ERROR_CHECK(app_simple_timer_stop());
                m_temp_array.size = 0;
                uart_rec_process_clr();
            }
    
            /* ������Ͳ��������.*/
            APP_ERROR_CHECK(app_timer_stop(uart_clear_id));
            APP_ERROR_CHECK(app_timer_start(uart_clear_id, APP_TIMER_TICKS(200), NULL));
    
    
        }
    
        m_uart_rec_states /**#StatesChange.*/ = UART_REC_IDLE;
    }
    
    
    /**
     * #��� ��ѯ���ڽ��մ���ģ�鵱ǰ�Ƿ�æ.
     *
     * #���� true   ���ڽ��մ���ģ�鵱ǰ��æ.
     * #���� false  ���ڽ��մ���ģ�鵱ǰ����.
     */
    static inline bool is_uart_rec_in_process(void) {
        return (m_uart_rec_states == UART_REC_IDLE)? false : true;
    }
    
    
    /**
     * #brief  Function for handling app_uart events.
     */
    void uart_event_handle(app_uart_evt_t * p_event)
    {
        switch (p_event->evt_type)
        {
            /**< An event indicating that UART data has been received. 
                 The data is available in the FIFO and can be fetched using @ref app_uart_get. */
            case APP_UART_DATA_READY:
            {
                uint8_t tmp_rec_data = 0;
    
                UNUSED_VARIABLE(app_uart_get(&tmp_rec_data));
    
                if (app_fifo_put(&m_uart_rec_fifo, tmp_rec_data) == NRF_SUCCESS) {
                    if (is_uart_rec_in_process() == false) {
                        uart_rec_process((void *)0, 0);
                    } else {
                        NRF_LOG_WARNING("uart buzy\r\n");
                        m_uart_rec_states == UART_REC_IDLE;
                        //! Busy
                        return;
                    }
                } else {
                    //! Rec fifo is full
                    NRF_LOG_WARNING("@#$@##@%$#@^@#$%#@$%@#$%fifo full@#!$!#$@!#%#$@%@$##$@%#@$^%$#&@$#%#$%@\r\n");
                    nrf_gpio_pin_set(FIFO_FULL_PIN);
                    return;
                }
                break;
            }
    
            /**< An communication error has occured during reception. */
            case APP_UART_COMMUNICATION_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_communication);
                break;
            
            /**< An error in the FIFO module used by the app_uart module has occured. */
            case APP_UART_FIFO_ERROR:
                APP_ERROR_HANDLER(p_event->data.error_code);
                break;
            case APP_UART_TX_EMPTY:
                NRF_LOG_INFO("UART SEND COMPELETE\r\n");
                // APP_ERROR_CHECK(app_uart_flush());
                uart_rec_process_clr();
                break;
    
            /**< An event indicating that UART has completed transmission of all available data in the TX FIFO. */
            // case APP_UART_TX_EMPTY:
            //     //! TX_EMPTY
            //     break;
    
            default:
                break;
        }
    }
    
    
    /**
     * #brief  Function for initializing the UART module.
     */
    static void uart_init(void)
    {
        uint32_t err_code;
        uint32_t tmp_uart_baud_list[] = UART_BAUDRATE_LIST;
    
        const app_uart_comm_params_t comm_params =
        {
            .rx_pin_no    = RX_PIN_NUMBER,
            .tx_pin_no    = TX_PIN_NUMBER,
            .rts_pin_no   = RTS_PIN_NUMBER,
            .cts_pin_no   = CTS_PIN_NUMBER,
            .flow_control = APP_UART_FLOW_CONTROL_DISABLED,
            .use_parity   = false,
            .baud_rate    = tmp_uart_baud_list[m_cmd_collection.uart_baudrate]
        };
    
        APP_UART_FIFO_INIT(&comm_params,
                           UART_RX_BUF_SIZE,
                           UART_TX_BUF_SIZE,
                           uart_event_handle,
                           APP_IRQ_PRIORITY_LOWEST,
                           err_code);
        APP_ERROR_CHECK(err_code);
    }
    
    
    /**
     * @brief Function for initializing the GATT library. 
     */
    void gatt_init(void)
    {
        APP_ERROR_CHECK(nrf_ble_gatt_init(&m_gatt, gatt_evt_handler));
        NRF_LOG_DEBUG("nrf_ble_gatt_init\r\n");
    
        APP_ERROR_CHECK(nrf_ble_gatt_att_mtu_periph_set(&m_gatt,43));
        NRF_LOG_DEBUG("nrf_ble_gatt_att_mtu_periph_set\r\n");
    }
    
    
    
    * #param[in] length   Length of the data.
     */
    static void nus_data_handler(ble_nus_evt_t * p_evt)
    {
        uint32_t err_code;
    
        switch (p_evt->type) {
            case BLE_NUS_EVT_RX_DATA:
    
                NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART.");
                NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
    
                for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
                {
                    do
                    {
                        err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
                        if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) {
                            NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
                            APP_ERROR_CHECK(err_code);
                        }
                    } while (err_code == NRF_ERROR_BUSY);
                }
                if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length-1] == '\r')
                {
                    while (app_uart_put('\n') == NRF_ERROR_BUSY);
                }
                break;
    
            case BLE_NUS_EVT_TX_RDY:
                if (m_uart_rec_states == UART_REC_DATA_PASS_WAIT) {
                    NRF_LOG_WARNING("uart reboot\r\n");
                    ble_data_notify_handler(NULL);
                }
                break;
            default :   
                break;
        }
    }
    

  • I want to know why this is not the case with the NRF52810, and this is the case with the NRF52832.

    The nRF52810 only have UART with EasyDMA. You should ideally use both flow-control and turn on EasyDMA, but if you don't use flow-control you will need to turn on EasyDMA to mitigate the overrun issue. EasyDMA allows peripherals to transmit/receive data while CPU is busy handling other events/tasks. 

Reply Children
No Data
Related