When we try to test the stability of the UARTE peripheral, we find that when inserting and removing the RX pin, the uarte_handler callback function is very likely to goes to NRFX_UARTE_EVT_ERROR state with error_code = 4. We try to reinitialize the UARTE by uninit and re-init it, but then the uarte_handler only goes to NRFX_UARTE_EVT_RX_DOWN state, and cannot receive any data.
In our test case, we send 11 uint8_t data at 1000000 baud rate every 10ms to the nrf52840dk. UARTE instance 1, TX on P0.27, RX on P0.26. with nrfx_uarte.h library. Also we have enable the interal pull up on the RX pin.
The code shows the uarte_handler function, and init/de-init function
// uarte_handler static void uarte_handler(nrfx_uarte_event_t const *p_event, void *p_context) { nrfx_err_t status; (void)status; uint8_t index; nrfx_uarte_t *p_inst = p_context; switch (p_event->type) { case NRFX_UARTE_EVT_RX_DONE: // NRFX_LOG_INFO("--> RX done"); index = (++m_rx_buffers.w_pos % RINGBUFF_SIZE); status = nrfx_uarte_rx(p_inst, (uint8_t *)(m_rx_buffers.buff + index), sizeof(struct split_msgq_trans)); NRFX_ASSERT(status == NRFX_SUCCESS); m_rx_buffers.w_pos = index; if (!bad_crc) { k_work_schedule(&uarte_work, K_NO_WAIT); } else { struct k_work_sync sync; k_work_cancel_delayable_sync(&uarte_work, &sync); split_uarte_deinit(p_inst); split_uart_init(p_inst); NRFX_LOG_ERROR("delayable work stopped"); bad_crc = 0; } break; case NRFX_UARTE_EVT_TX_DONE: NRFX_LOG_INFO("--> TX done"); NRFX_LOG_INFO("--> Bytes transfered: %u", p_event->data.tx.bytes); break; case NRFX_UARTE_EVT_ERROR: NRFX_LOG_ERROR("--> UARTE Error: %d", p_event->data.error.error_mask); NRFX_LOG_ERROR("--> Rx bytes: %d", p_event->data.error.rx.bytes); struct k_work_sync sync; k_work_cancel_delayable_sync(&uarte_work, &sync); LOG_DBG("NRFX_UARTE_EVT_ERROR: delayable work stopped"); split_uarte_deinit(p_inst); split_uart_init(p_inst); break; default: break; } } // Initialize function static void split_uart_init(nrfx_uarte_t *p_inst) { nrfx_err_t status; uint32_t key; if (false == uart_status) { nrfx_uarte_config_t uarte_config = NRFX_UARTE_DEFAULT_CONFIG(UARTE_TX_PIN, UARTE_RX_PIN); uarte_config.baudrate = NRF_UARTE_BAUDRATE_1000000; uarte_config.p_context = p_inst; status = nrfx_uarte_init(p_inst, &uarte_config, uarte_handler); NRFX_ASSERT(status == NRFX_SUCCESS); // nrfy_gpio_cfg_input(UARTE_RX_PIN, NRF_GPIO_PIN_PULLUP); nrfy_gpio_cfg(UARTE_RX_PIN, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); nrfy_gpio_cfg(UARTE_TX_PIN, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_DISCONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_H0H1, NRF_GPIO_PIN_NOSENSE); #if defined(__ZEPHYR__) IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_UARTE_INST_GET(UARTE_INST_IDX)), IRQ_PRIO_LOWEST, NRFX_UARTE_INST_HANDLER_GET(UARTE_INST_IDX), 0); #endif status = nrfx_uarte_rx(&uarte_inst, (uint8_t *)m_rx_buffers.buff, sizeof(split_msgq_trans_t)); NRFX_ASSERT(status == NRFX_SUCCESS); key = irq_lock(); uart_status = true; irq_unlock(key); } } // de-initialize function static void split_uarte_deinit(nrfx_uarte_t *p_inst) { if (uart_status) { uint32_t key = irq_lock(); uart_status = false; nrfx_uarte_uninit(p_inst); m_rx_buffers.r_pos = 0; m_rx_buffers.w_pos = 0; memset(m_rx_buffers.buff, 0, sizeof(m_rx_buffers.buff)); irq_unlock(key); } }