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

How to recover from nrf_serial driver errors?

Hi,

I'm using the nRF52840 on a custom board along with an ESP8266 (ESP-12S) Wi-Fi module.

The ESP module prints out a bunch of information at a weird nonstandard baud rate when it powers up, and then it switches to 115200.  I've found that the stuff coming in at the wrong baud rate at startup is crashing the nrf_serial driver such that I never get receive interrupts even after the module starts sending proper 115200 data, I just get just NRF_SERIAL_EVENT_DRV_ERR. It does not seem to recover on its own.

I am getting around this issue for now by waiting for several seconds after powering up the ESP before I call nrf_serial_init, but I don't think this is a great long-term solution.

Is there some way to prevent this crash from happening, or to recover from it when it happens? Can I just call nrf_serial_init again from my interrupt handler when I get NRF_SERIAL_EVENT_DRV_ERR?

Thanks!

Glen

Parents
  • The easiest way is to add a listener for the error event and use it to reinitialize the Serial Driver.

    Depending on how you have setup the driver it can be as easy as:

    // If you already have an event callback you just need to add another case.
    // I have omiited the lines where I setup the queue and buffer because it
    // doesn't seem applicable to your question.
    NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_DMA,
                          &serial_queues, &serial_buffs, &uart_event_handle, NULL);
    
    // Skip a few lines...
    
    void uart_event_handle(struct nrf_serial_s const* p_serial, nrf_serial_event_t event){
        switch (event){
            case NRF_SERIAL_EVENT_DRV_ERR:
                NRF_LOG_INFO("Serial driver error handler");
                uint32_t error;
                if(NRF_UART0->EVENTS_ERROR !=0)
                {
                    error = NRF_UART0->ERRORSRC;
                    NRF_LOG_INFO("Serial driver err: %d", error);
                    NRF_UART0->EVENTS_ERROR = 0;
                }
    
                nrf_serial_uninit(p_serial);
                
                uart_init(); // <-- The function you use to configure the uart driver.
                break;
        }
    }

Reply
  • The easiest way is to add a listener for the error event and use it to reinitialize the Serial Driver.

    Depending on how you have setup the driver it can be as easy as:

    // If you already have an event callback you just need to add another case.
    // I have omiited the lines where I setup the queue and buffer because it
    // doesn't seem applicable to your question.
    NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_DMA,
                          &serial_queues, &serial_buffs, &uart_event_handle, NULL);
    
    // Skip a few lines...
    
    void uart_event_handle(struct nrf_serial_s const* p_serial, nrf_serial_event_t event){
        switch (event){
            case NRF_SERIAL_EVENT_DRV_ERR:
                NRF_LOG_INFO("Serial driver error handler");
                uint32_t error;
                if(NRF_UART0->EVENTS_ERROR !=0)
                {
                    error = NRF_UART0->ERRORSRC;
                    NRF_LOG_INFO("Serial driver err: %d", error);
                    NRF_UART0->EVENTS_ERROR = 0;
                }
    
                nrf_serial_uninit(p_serial);
                
                uart_init(); // <-- The function you use to configure the uart driver.
                break;
        }
    }

Children
Related