nRF9151 UART: DMA vs FIFO – Seeking Fast TX with FIFO Setup

I’m working with nRF9151 + Toolchain 2.9.0 and wanted to share my experience & issue while sending ~7kB data over UART. I’ve tried both DMA & FIFO-based approaches — here’s what I learned, and where I need help.

DMA-Based UART (Async API)
To achieve high-speed transfer, I first used the async UART API with DMA:

prj.conf:

CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_0_INTERRUPT_DRIVEN=y
CONFIG_UART_0_ASYNC=y
CONFIG_NRFX_UARTE0=y

Init:

uart_callback_set(dev, siwg917y_uart_response_handler, &siwg917y_Udata);
uart_rx_enable(dev, siwg917y_Udata.user_rx_buf, siwg917y_Udata.user_rx_len, siwg917y_Udata.user_rx_timeout);



Handler:

static void siwg917y_uart_response_handler(const struct device *dev, struct uart_event *evt, void *user_data)
{
    switch (evt->type) {
        case UART_RX_RDY:
            // buffer handling logic
            break;

        case UART_RX_DISABLED:
            uart_rx_enable(dev, data->user_rx_buf, data->user_rx_len, data->user_rx_timeout);
            break;
    }
}



Transmit:

uart_tx(dev, cmd, strlen(cmd), SYS_FOREVER_US); // Works perfectly!


With this setup, I can send 7kB in ~1 second.

2) FIFO-Based UART (Interrupt-Driven)
To improve stability and explore classic UART FIFO, I switched to interrupt-driven mode:

prj.conf:

CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y


init:
uart_irq_callback_user_data_set(dev, siwg917y_uart_response_handler, &siwg917y_Udata);
uart_irq_rx_enable(dev);


FIFO Handler:

while (uart_fifo_read(dev, &c, 1) == 1) {
    if ((c == '\n' || c == '\r') && rx_buf_pos > 0) {
        // Copy into user buffer & queue
        k_msgq_put(&siwg917y_rx_queue, data, K_NO_WAIT);
        rx_buf_pos = 0;
    } else {
        rx_buf[rx_buf_pos++] = c;
    }
}


Transmit:

for (int i = 0; i < strlen(cmd); i++) {
    uart_poll_out(dev, cmd[i]);
}

This method takes 5–6 seconds for the same 7kB.

Issue:
When using FIFO mode, uart_tx() does not work — but it's fast and DMA-friendly in async mode.

Goal:
Use a fast transmit method (like uart_tx) with FIFO / interrupt mode — is this possible?


Question to the community:

Is there a way to use uart_tx() or any DMA-based high-speed send method with FIFO config?

Any ideas, configs, or driver-level tricks to enable uart_tx or DMA in interrupt mode?

Let me know what worked for you!

Related