Recover from APP_UART_COMMUNICATION_ERROR

Hi, We are using SDK17 and are implementing the UART y APP_UART_FIFO_INIT. Every now and then we encounter APP_UART_COMMUNICATION_ERROR. I know this is related to buffer overrun during reception. How do we gracefully recover from this? If the data in the buffer is lost, we can handle this in an other way. But for now, the error is not cleared and the only way to get it working again is reset the device.

Parents
  • Hi,

    Without further information, my best guess is that your code run a APP_ERROR_CHECK or APP_ERROR_HANDLER when you receive a callback with APP_UART_COMMUNICATION_ERROR? That and you are building with the Debug option and default nRF5 SDK app_error implementation.

    If my above guesses are correct, APP_ERROR_CHECK and APP_ERROR_HANDLER are calling functions in the Error Module.
    In Debug build, those function stop the firmware anytime they detect an error, and also produce logs on the error.
    In Release build, the functions reset the firmware instead.

    To gracefully recover from an APP_UART_COMMUNICATION_ERROR, you should handle the app_uart_evt_t. You can find implementation hint in the documentation of the app_uart_evt_t.data.error_communication field, quote below.

    Field used if evt_type is: APP_UART_COMMUNICATION_ERROR. This field contains the value in the ERRORSRC register for the UART peripheral. The UART_ERRORSRC_x defines from nrf5x_bitfields.h can be used to parse the error code. See also the nRF5 Series Reference Manual for specification.

    I can't find nrf5x_bitfields.h anywhere, but the ERRORSRC register documentations are available in the nRF52840 Product Specification.

    To further refine the handling of error, please also look into the behavior of the Error Module and the possibility having your own custom app_error_fault_handler() implementation.

    By the way, please also note that the error name in the log provided by the Error Module would be incorrected for this case. Just note the number and look up the Product Specification. See RE: NRF_ERROR_SVC_HANDLER_MISSING of uart  

    Best regards,

    Hieu.

  • Hi Hieu,

    Thanks for your reply.

    However this does not answer my question yet. My question is how to recover from such an error event.

    In case I just print some info (NRF_LOG_ERR) the error condition/flag is not cleared. The quote in the link is talking about the origin of the error (UART_ERRORSRC_x defines from nrf5x_bitfields.h). Is a simple clear those bits sufficient? Is there a nice call to do that or should I dig into the register itself? 

  • Hi Hieu,

    I am unable to answer on your last reply about using the Advanced UARTE Driver library, so I try this message instead.

    I tried to implement the Advanced UARTE Driver library in the existing application, but failed on setting the NRF_CLOCK to enable nrf_drv_clock_lfclk_request. Adding the (relevant??) defines like NRF_CLOCK_ENABLED 1 in the app_config.h, I get errors in apply_old_config.h. expected declaration specifiers or '...' before numeric constant. 

  • Hi,

    You are probably talking about adding "#define NRF_CLOCK_ENABLE 1" in sdk_config.h?

    Aside from that, did you make sure all of these configurations are setup as well?

    // <e> NRF_CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer
    //==========================================================
    #ifndef NRF_CLOCK_ENABLED
    #define NRF_CLOCK_ENABLED 1
    #endif
    // <o> CLOCK_CONFIG_LF_SRC  - LF Clock Source
     
    // <0=> RC 
    // <1=> XTAL 
    // <2=> Synth 
    // <131073=> External Low Swing 
    // <196609=> External Full Swing 
    
    #ifndef CLOCK_CONFIG_LF_SRC
    #define CLOCK_CONFIG_LF_SRC 1
    #endif
    
    // <q> CLOCK_CONFIG_LF_CAL_ENABLED  - Calibration enable for LF Clock Source
     
    
    #ifndef CLOCK_CONFIG_LF_CAL_ENABLED
    #define CLOCK_CONFIG_LF_CAL_ENABLED 0
    #endif
    
    // <o> CLOCK_CONFIG_IRQ_PRIORITY  - Interrupt priority
     
    
    // <i> Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice
    // <0=> 0 (highest) 
    // <1=> 1 
    // <2=> 2 
    // <3=> 3 
    // <4=> 4 
    // <5=> 5 
    // <6=> 6 
    // <7=> 7 
    
    #ifndef CLOCK_CONFIG_IRQ_PRIORITY
    #define CLOCK_CONFIG_IRQ_PRIORITY 6
    #endif
    
    // </e>

    If you did and still got that error, could you please give more details? For example:
    - Which line in apply_old_config.h is giving you the error?
    - Are there any other hints in the error? Such as where or what the related numeric constant is?

    Hieu

  • Hi,

    As soon as I add one of the below line, the error is generated

    #define NRF_CLOCK_ENABLED 1
    #define CLOCK_CONFIG_LF_SRC 1

    #define UART_DEFAULT_CONFIG_HWFC 0
    #define UART_DEFAULT_CONFIG_PARITY 0
    #define UART_DEFAULT_CONFIG_BAUDRATE 30801920
    #define UART_DEFAULT_CONFIG_IRQ_PRIORITY 7

  • Hi,

    I apologize for the late follow-up. I tried some simple solutions I thought of, but they didn't work. My direction right now is to get libuarte to work without relying on NRF_CLOCK. I will need to go deeper into the documents some more.

    By the way, are you using any other NRFX drivers in the project?

    The error comes from apply_old_config.h, as you said. It is included in nrf_glue.h and subsequently by nrfx.h, which is used in most if not all NRFX drivers.

    Best regards,

    Hieu

  • Hi,

    BvdP4Celsius said:

    Hi,

    As soon as I add one of the below line, the error is generated

    I inspected further and does not find apply_old_config.h looks like that in both nRF5 SDK v17.1.0, v17.0.2, and v15.0.0. Where did you pull this file from? What SDK version are you on?


    Anyway, if your apply_old_config.h looks like that, then the SDK you are on probably does not want NRF_DRV_CLOCK to be enabled while NRFX is being used.

    Meanwhile, libUARTE, as setup in the example, use App Timer (under the hood). The App Timer in turns relies on the LFCLK. Finally, the example uses NRF_DRV_CLOCK to enable LFCLK.

    Therefore, to avoid using NRF_DRV_CLOCK, we can just use NRFX_CLOCK to enable LFCLK instead. I cannot find an example which uses NRFX_CLOCK, so here is my code, tested and work:

    void MY_nrfx_clock_event_handler(nrfx_clock_evt_type_t event)
    {
        // Do nothing?
        // Alternatively handle these event types as you see fit
        // typedef enum
        // {
        //     NRFX_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started.
        //     NRFX_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started.
        //     NRFX_CLOCK_EVT_CTTO,          ///< Calibration timeout.
        //     NRFX_CLOCK_EVT_CAL_DONE       ///< Calibration has been done.
        // } nrfx_clock_evt_type_t;
        NRF_LOG_INFO("MY_nrfx_clock_event_handler %d", event);
    }
    
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
        
        //ret_code_t ret = nrf_drv_clock_init();
        //APP_ERROR_CHECK(ret);
      
        //nrf_drv_clock_lfclk_request(NULL);
        
        ret_code_t ret = nrfx_clock_init(MY_nrfx_clock_event_handler);
        APP_ERROR_CHECK(ret);
        nrfx_clock_lfclk_start();
        
        ...
        
    }


    I apologize once again for the long wait. Please come again if you need help; and if it is urgent for certain reasons, please just note so.

    Best regards,

    Hieu

Reply
  • Hi,

    BvdP4Celsius said:

    Hi,

    As soon as I add one of the below line, the error is generated

    I inspected further and does not find apply_old_config.h looks like that in both nRF5 SDK v17.1.0, v17.0.2, and v15.0.0. Where did you pull this file from? What SDK version are you on?


    Anyway, if your apply_old_config.h looks like that, then the SDK you are on probably does not want NRF_DRV_CLOCK to be enabled while NRFX is being used.

    Meanwhile, libUARTE, as setup in the example, use App Timer (under the hood). The App Timer in turns relies on the LFCLK. Finally, the example uses NRF_DRV_CLOCK to enable LFCLK.

    Therefore, to avoid using NRF_DRV_CLOCK, we can just use NRFX_CLOCK to enable LFCLK instead. I cannot find an example which uses NRFX_CLOCK, so here is my code, tested and work:

    void MY_nrfx_clock_event_handler(nrfx_clock_evt_type_t event)
    {
        // Do nothing?
        // Alternatively handle these event types as you see fit
        // typedef enum
        // {
        //     NRFX_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started.
        //     NRFX_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started.
        //     NRFX_CLOCK_EVT_CTTO,          ///< Calibration timeout.
        //     NRFX_CLOCK_EVT_CAL_DONE       ///< Calibration has been done.
        // } nrfx_clock_evt_type_t;
        NRF_LOG_INFO("MY_nrfx_clock_event_handler %d", event);
    }
    
    
    /**
     * @brief Function for main application entry.
     */
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
        
        //ret_code_t ret = nrf_drv_clock_init();
        //APP_ERROR_CHECK(ret);
      
        //nrf_drv_clock_lfclk_request(NULL);
        
        ret_code_t ret = nrfx_clock_init(MY_nrfx_clock_event_handler);
        APP_ERROR_CHECK(ret);
        nrfx_clock_lfclk_start();
        
        ...
        
    }


    I apologize once again for the long wait. Please come again if you need help; and if it is urgent for certain reasons, please just note so.

    Best regards,

    Hieu

Children
No Data
Related