drivers: serial: nrfx_uarte: Workaround for spurious RXTO during restart

Some SoCs generates unexpected RXTO event during restart.
Restart happens when ENDRX_STARTRX short is enabled and STOPRX
is triggered (via short or by CPU). STOPRX starts closing
procedure and ENDRX event is generated at some point which
triggers STARTRX and closing procedure is interrupted. RXTO
should not be triggered in that case. Due to internal timings
some SoC on fast UARTE instance will trigger RXTO followed
by RXSTARTED. This RXTO event shall be cleared as receiver is
actually restarted and not stopped.

Affected SoC is not in tree so Kconfig is added which enables
the workaround.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruściński 2025-05-16 09:51:55 +02:00 committed by Benjamin Cabé
commit c58ae7467b
2 changed files with 22 additions and 0 deletions

View file

@ -66,6 +66,11 @@ config UART_ASYNC_TX_CACHE_SIZE
config UART_NRFX_UARTE_DIRECT_ISR
bool "Use direct ISR"
config UART_NRFX_UARTE_SPURIOUS_RXTO_WORKAROUND
bool
help
Apply workaround for spurious RXTO during restart.
if HAS_HW_NRF_UART0 || HAS_HW_NRF_UARTE0
nrfx_uart_num = 0
rsource "Kconfig.nrfx_uart_instance"

View file

@ -266,6 +266,9 @@ struct uarte_nrfx_data {
/* If enabled then UARTE peripheral is using memory which is cacheable. */
#define UARTE_CFG_FLAG_CACHEABLE BIT(3)
/* Indicates that workaround for spurious RXTO during restart shall be applied. */
#define UARTE_CFG_FLAG_SPURIOUS_RXTO BIT(3)
/* Formula for getting the baudrate settings is following:
* 2^12 * (2^20 / (f_PCLK / desired_baudrate)) where f_PCLK is a frequency that
* drives the UARTE.
@ -1546,6 +1549,17 @@ static void endrx_isr(const struct device *dev)
unsigned int key = irq_lock();
if (async_rx->buf) {
#if CONFIG_UART_NRFX_UARTE_SPURIOUS_RXTO_WORKAROUND
/* Check for spurious RXTO event. */
const struct uarte_nrfx_config *config = dev->config;
if ((config->flags & UARTE_CFG_FLAG_SPURIOUS_RXTO) &&
nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXTO)) {
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXTO);
}
#endif
/* Check is based on assumption that ISR handler handles
* ENDRX before RXSTARTED so if short was set on time, RXSTARTED
* event will be set.
@ -2586,6 +2600,9 @@ static int uarte_instance_init(const struct device *dev,
(!IS_ENABLED(CONFIG_HAS_NORDIC_DMM) ? 0 : \
(UARTE_IS_CACHEABLE(idx) ? \
UARTE_CFG_FLAG_CACHEABLE : 0)) | \
(IS_ENABLED(CONFIG_UART_NRFX_UARTE_SPURIOUS_RXTO_WORKAROUND) && \
INSTANCE_IS_HIGH_SPEED(_, /*empty*/, idx, _) ? \
UARTE_CFG_FLAG_SPURIOUS_RXTO : 0) | \
USE_LOW_POWER(idx), \
UARTE_DISABLE_RX_INIT(UARTE(idx)), \
.poll_out_byte = &uarte##idx##_poll_out_byte, \