drivers: serial: nrfx_uarte: Add workaround for bytes dropping

Add workaround for development kits on which interface chip (segger chip)
is dropping bytes when they are sent in bursts. Issue has been seen on
DK which have multiple virtual com ports on the USB.

A workaround is adding periodic busy waits to introduce gaps in the
transmission.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruscinski 2022-07-25 15:43:28 +02:00 committed by Carles Cufí
parent 1c70522734
commit 0f9f18843f
2 changed files with 52 additions and 0 deletions

View file

@ -27,6 +27,32 @@ config UART_ASYNC_TX_CACHE_SIZE
in RAM, because EasyDMA in UARTE peripherals can only transfer data
from RAM.
config UART_NRF_DK_SERIAL_WORKAROUND
bool
help
On some development kits there are characters being dropped by the
controller chip (Segger interface) if there are burst of bytes being
printed. It can lead to test failures since test out is corrupted.
A workaround is to enforce gaps (by adding busy waits) in the transmission.
It is recommended to enable the workaround only in the test since
busy waits can impact application flow.
if UART_NRF_DK_SERIAL_WORKAROUND
config UART_NRF_DK_SERIAL_WORKAROUND_COUNT
int
default 32
help
Number of bytes transferred after which a busy wait is added.
config UART_NRF_DK_SERIAL_WORKAROUND_WAIT_MS
int
default 10
help
Busy wait time (in milliseconds).
endif
# ----------------- port 0 -----------------
config UART_0_NRF_UART
def_bool HAS_HW_NRF_UART0

View file

@ -1539,6 +1539,32 @@ static void uarte_nrfx_poll_out(const struct device *dev, unsigned char c)
bool isr_mode = k_is_in_isr() || k_is_pre_kernel();
unsigned int key;
#if CONFIG_UART_NRF_DK_SERIAL_WORKAROUND
/* On some boards (usually those which have multiple virtual coms) it can
* be seen that bytes are dropped on the console serial (serial that goes
* through Segger interface chip) when working in virtual environment.
* It's the Segger chip that drops those bytes. A workaround is to enforce
* periodic gaps which allows to handle the traffic correctly.
*/
if (dev == DEVICE_DT_GET(DT_CHOSEN(zephyr_console))) {
static int cnt;
static uint32_t t;
uint32_t now = k_uptime_get_32();
if ((now - t) >= CONFIG_UART_NRF_DK_SERIAL_WORKAROUND_WAIT_MS) {
cnt = 0;
} else {
cnt++;
if (cnt >= CONFIG_UART_NRF_DK_SERIAL_WORKAROUND_COUNT) {
k_busy_wait(1000 * CONFIG_UART_NRF_DK_SERIAL_WORKAROUND_WAIT_MS);
cnt = 0;
}
}
t = now;
}
#endif
if (isr_mode) {
while (1) {
key = irq_lock();