How to deal with NRF_ERROR_NO_MEM when APP_UART_FIFO_ERROR occurred?

I'm developing with SDK 17 in custom board using nrf52832.

 It's always happened after running for some time that APP_UART_FIFO_ERROR.

By observe the p_evt->data.error_code field,I find the error is NRF_ERROR_NO_MEM.

How I write the code deal with the case that APP_UART_FIFO_ERROR to repair it automatically so that I can keep it communicate normally in almost all time?

  • Hello,

    Please see the uart_event_handler() in app_uart_fifo.c. This is the part that generates the APP_UART_FIFO_ERROR event, and it happens if app_fifo_put() returns anything other than NRF_SUCCESS. You can check what the app_fifo_put() actually returns, but I guess the issue is that you have not emptied the fifo using app_uart_get(), which uses app_fifo_get(), and the fifo buffer is full. 

    To "recover" from this event, you need to not forward the p_event->data.error_code into an APP_ERROR_HANDLER() (you can, but this will reboot the application), but instead start emptying your fifo buffer. However, the byte that caused the APP_UART_FIFO_ERROR is lost, unless you modify the app_uart_fifo.c to store it somewhere else.

    Best regards,

    Edvin

  • Hello,

    The app_uart_get() is used in my code.I get the data and put into a global array as fllow:

    void uart_event_handle(app_uart_evt_t * p_event) uart_evt_t * p_eventuart_evt_t * p_eventuart_evt_t * p_eventuart_evt_t * p_eventuart_evt_t * p_eventuart_evt_t * p_event

    {

      switch(p_event->evt_type) 开关(p_event - > evt_type)开关(p_event - > evt_type)开关(p_event - > evt_type)开关(p_event - > evt_type)开关(p_event - > evt_type)开关(p_event - > evt_type)

      {

     case APP_UART_DATA_READY: 案例APP_UART_DATA_READY:案例APP_UART_DATA_READY:案例APP_UART_DATA_READY:案例APP_UART_DATA_READY:案例APP_UART_DATA_READY:案例APP_UART_DATA_READY:

     uart_flag = true;

     if(buf_is_full()) 如果(buf_is_full ()) 如果(buf_is_full ()) 如果(buf_is_full ()) 如果(buf_is_full ()) 如果(buf_is_full ()) 如果(buf_is_full ())

     {

     return; 返回; 返回; 返回; 返回; 返回; 返回;

     }

     UNUSED_VARIABLE(app_uart_get(&uart_buf_input[p_rail]));

    void uart_event_handle(app_uart_evt_t * p_event)
    {
    	switch(p_event->evt_type)
    	{
    		case APP_UART_DATA_READY:
    			uart_flag = true;
    			if(buf_is_full())
    			{
    				return;
    			}
    			UNUSED_VARIABLE(app_uart_get(&uart_buf_input[p_rail]));
    			p_rail = (p_rail+1)%(BLE_NUS_MAX_DATA_LEN);
    			break;
    		case APP_UART_FIFO_ERROR:
    			NRF_LOG_INFO("FIFO_ERR:%08x",p_event->data.error_code);
    			break;
    		default:
    			NRF_LOG_INFO("UART EVT ID:%d",p_event->evt_type);
    			break;
    	}
    }
    I deal with the global array in main loop.And in order to deal with some specifically data,add delay 

    in it.So maybe the issue caused by delay so that the fifo buffer is full?

  • I don't know what "buf_is_full()" does, but if this returns true, and your application doesn't start emptying using app_uart_get(), then you risk that the FIFO is full, and you will enter the APP_UART_FIFO_ERROR eventually.

    Best regards,

    Edvin

  • The buf_is_full() just used to check if the array used as buffer is full.buf_is_full()只是用来检查用作缓冲区的数组是否已满。

    The interrupt have higher priority,So maybe delay due to too many data not been deal so that the fuction return andapp_uart_get() didn't work.

    But it is still puzzled me that maybe something I can do in APP_UART_FIFO_ERROR so that I can reach to effect that the uart seem to be restart and transfer data normally again by itself.

    I want to know what need to do.

    Just uninit uart and restart init or just clear fifo buffer or both?Or some other operation?

    中断具有更高的优先级,因此可能由于没有处理太多数据而延迟,因此函数return和app_uart_get()没有工作。

  • When APP_UART_FIFO_ERROR occurs, you will loose the byte that it was trying to add to your FIFO. If you want to preserve it, you need to modify the NRF_DRV_UART_EVT_RX_DONE event in app_uart_fifo.c.

    If the FIFO is full, then it will not start the next uart_rx automatically. This needs to be done using app_uart_get() from your application.

    Best regards,

    Edvin

Related