UART configuration and pin-definition on nRF54L15-DK

Hi,

I would like to create a UART on the nRF54L15 DK, but currently it seems that only the pins bound to CONFIG_UART_CONSOLE (P1.04 / P1.05) are working as below Output. 
I am unable to assign other TXD/RXD pins, for example (P2.00 / P2.01) or (P2.02 / P2.00) .

Could you please advise on how to properly configure alternative UART pins on this platform?

nrf54l15dk_nrf54l15_cpuapp.overlay

&pinctrl {
    uart20_default: uart20_default {
        group1 {
            psels = <NRF_PSEL(UART_TX, 2, 0)>,
                    <NRF_PSEL(UART_RX, 2, 1)>;
        };
    };
};

&uart20 {
    status = "okay";
    current-speed = <115200>;
};


prj.conf

CONFIG_SERIAL=y
CONFIG_UART_NRFX=y
CONFIG_UART_ASYNC_API=y
CONFIG_GPIO=y

CONFIG_MAIN_STACK_SIZE=2048

CONFIG_LOG=n
CONFIG_USE_SEGGER_RTT=n
CONFIG_UART_CONSOLE=y
CONFIG_SHELL=n


main.c

#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/device.h>
#include <string.h>
#include <stdio.h>

#define RX_TIMEOUT_US 20000
#define LINE_MAX      128

static const struct device *uart;
static char line[LINE_MAX];
static size_t linelen;

static uint8_t rxbuf1[64];
static uint8_t rxbuf2[64];
static bool buf2_in_use;

static void on_evt(const struct device *dev, struct uart_event *evt, void *ud)
{
    ARG_UNUSED(dev); ARG_UNUSED(ud);

    switch (evt->type) {
    case UART_RX_RDY: {
        const struct uart_event_rx *rx = &evt->data.rx;
        
        for (size_t i = rx->offset; i < rx->offset + rx->len; ++i) {
            char c = rx->buf[i];
            if (c == '\r' || c == '\n') {
                if (linelen > 0) {
                    line[linelen] = 0;
                    printk("Received: %s\n", line);
                    linelen = 0;
                }
            } else if (linelen + 1 < sizeof(line)) {
                line[linelen++] = c;
            } else {
                linelen = 0;
            }
        }
        break;
    }
    case UART_RX_BUF_REQUEST:
        if (!buf2_in_use) {
            uart_rx_buf_rsp(uart, rxbuf2, sizeof(rxbuf2));
            buf2_in_use = true;
        }
        break;
    case UART_RX_BUF_RELEASED:
        if (evt->data.rx_buf.buf == rxbuf2) buf2_in_use = false;
        break;
    case UART_RX_DISABLED:
        uart_rx_enable(uart, rxbuf1, sizeof(rxbuf1), RX_TIMEOUT_US);
        break;
    default:
        break;
    }
}

int main(void)
{
    uart = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    if (!device_is_ready(uart)) {
        return 0;
    }

    printk("Hello World!\n"); 

    /* Async */
    uart_callback_set(uart, on_evt, NULL); //uart20
    uart_rx_enable(uart, rxbuf1, sizeof(rxbuf1), RX_TIMEOUT_US);

    while (1) {
        k_sleep(K_SECONDS(1));
    }
}


Output:

*** Booting nRF Connect SDK v3.1.0-6c6e5b32496e ***
*** Using Zephyr OS v4.1.99-1612683d4010 ***
Hello World!
Received: 123456

thanks.

Parents
  • Hi,

    I think I understand the problem, and it's related to what you can find here:
    https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/uarte.html#d1754e919 
    https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/chapters/pin.html#ariaid-title2 
    https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/chapters/pin.html#d379e188 
    https://docs.nordicsemi.com/bundle/ps_nrf54L15/page/chapters/pin.html#ariaid-title3 

    Make sure to carefully read all 4 of those chapters. So I believe you need to explicit request and release constlat when using Port 2, e.g.

    (#include <nrfx_power.h>) nrfx_power_constlat_mode_request(); // right before you transmit/receive something, release afterwards to reduce current when not using UART.

    Edit: If you are using the DK, also see my next reply.

    Kenneth

  • Hi,

    Thank you for your reply. I have followed your suggestion and added the nrfx_power_constlat_mode_request() function. For testing purposes, I have not released it yet. Unfortunately, the UART is still not working. Could you please advise if there might be any other configuration conflicts or errors that I should check?

    nrf54l15dk_nrf54l15_cpuapp.overlay

    &uart20 {
        status = "okay";
        current-speed = <115200>;
    
        /delete-property/ pinctrl-1;
        /delete-property/ pinctrl-names;
    
        pinctrl-0 = <&uart20_p2>;
        pinctrl-names = "default";
    };
    
    &pinctrl {
        uart20_p2: uart20_p2 {
            group1 {
                psels = <NRF_PSEL(UART_TX, 2, 2)>,
                        <NRF_PSEL(UART_RX, 2, 0)>;
            };
        };
    
        /delete-node/ uart20_sleep_p2;
    };


    prj.conf
    CONFIG_SERIAL=y
    CONFIG_UART_NRFX=y
    CONFIG_UART_ASYNC_API=y
    CONFIG_GPIO=y
    CONFIG_UART_NRFX=y
    CONFIG_NRFX_POWER=y
    
    CONFIG_MAIN_STACK_SIZE=2048
    
    CONFIG_LOG=n
    CONFIG_USE_SEGGER_RTT=n
    CONFIG_UART_CONSOLE=y
    CONFIG_SHELL=n


    main.c
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/uart.h>
    #include <zephyr/device.h>
    #include <string.h>
    #include <stdio.h>
    #include <nrfx_power.h> //added
    
    #define RX_TIMEOUT_US 20000
    #define LINE_MAX      128
    
    static const struct device *uart;
    static char line[LINE_MAX];
    static size_t linelen;
    
    static uint8_t rxbuf1[64];
    static uint8_t rxbuf2[64];
    static bool buf2_in_use;
    
    static void on_evt(const struct device *dev, struct uart_event *evt, void *ud)
    {
        ARG_UNUSED(dev); ARG_UNUSED(ud);
    
        switch (evt->type) {
        case UART_RX_RDY: {
            const struct uart_event_rx *rx = &evt->data.rx;
            for (size_t i = rx->offset; i < rx->offset + rx->len; ++i) {
                char c = rx->buf[i];
                if (c == '\r' || c == '\n') {
                    if (linelen > 0) {
                        line[linelen] = 0;
                        printk("Received: %s\n", line);
                        linelen = 0;
                    }
                } else if (linelen + 1 < sizeof(line)) {
                    line[linelen++] = c;
                } else {
                    linelen = 0;  // overflow reset
                }
            }
            break;
        }
        case UART_RX_BUF_REQUEST:
            if (!buf2_in_use) {
                uart_rx_buf_rsp(uart, rxbuf2, sizeof(rxbuf2));
                buf2_in_use = true;
            }
            break;
        case UART_RX_BUF_RELEASED:
            if (evt->data.rx_buf.buf == rxbuf2) buf2_in_use = false;
            break;
        case UART_RX_DISABLED:
            /* continuous */
            uart_rx_enable(uart, rxbuf1, sizeof(rxbuf1), RX_TIMEOUT_US);
            break;
        default:
            break;
        }
    }
    
    int main(void)
    {
        //uart = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
        uart = DEVICE_DT_GET(DT_NODELABEL(uart20));
        if (!device_is_ready(uart)) {
            return 0;
        }
        nrfx_power_constlat_mode_request(); //added
    
        printk("Hello World! uart20 on P2.02/P2.00 (CONSTLAT ON)\n");
    
        /* Async */
        uart_callback_set(uart, on_evt, NULL);
        uart_rx_enable(uart, rxbuf1, sizeof(rxbuf1), RX_TIMEOUT_US);
    
        while (1) {
            k_sleep(K_SECONDS(1));
        }
    }

    Best regards,
    Webb

Reply
  • Hi,

    Thank you for your reply. I have followed your suggestion and added the nrfx_power_constlat_mode_request() function. For testing purposes, I have not released it yet. Unfortunately, the UART is still not working. Could you please advise if there might be any other configuration conflicts or errors that I should check?

    nrf54l15dk_nrf54l15_cpuapp.overlay

    &uart20 {
        status = "okay";
        current-speed = <115200>;
    
        /delete-property/ pinctrl-1;
        /delete-property/ pinctrl-names;
    
        pinctrl-0 = <&uart20_p2>;
        pinctrl-names = "default";
    };
    
    &pinctrl {
        uart20_p2: uart20_p2 {
            group1 {
                psels = <NRF_PSEL(UART_TX, 2, 2)>,
                        <NRF_PSEL(UART_RX, 2, 0)>;
            };
        };
    
        /delete-node/ uart20_sleep_p2;
    };


    prj.conf
    CONFIG_SERIAL=y
    CONFIG_UART_NRFX=y
    CONFIG_UART_ASYNC_API=y
    CONFIG_GPIO=y
    CONFIG_UART_NRFX=y
    CONFIG_NRFX_POWER=y
    
    CONFIG_MAIN_STACK_SIZE=2048
    
    CONFIG_LOG=n
    CONFIG_USE_SEGGER_RTT=n
    CONFIG_UART_CONSOLE=y
    CONFIG_SHELL=n


    main.c
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/uart.h>
    #include <zephyr/device.h>
    #include <string.h>
    #include <stdio.h>
    #include <nrfx_power.h> //added
    
    #define RX_TIMEOUT_US 20000
    #define LINE_MAX      128
    
    static const struct device *uart;
    static char line[LINE_MAX];
    static size_t linelen;
    
    static uint8_t rxbuf1[64];
    static uint8_t rxbuf2[64];
    static bool buf2_in_use;
    
    static void on_evt(const struct device *dev, struct uart_event *evt, void *ud)
    {
        ARG_UNUSED(dev); ARG_UNUSED(ud);
    
        switch (evt->type) {
        case UART_RX_RDY: {
            const struct uart_event_rx *rx = &evt->data.rx;
            for (size_t i = rx->offset; i < rx->offset + rx->len; ++i) {
                char c = rx->buf[i];
                if (c == '\r' || c == '\n') {
                    if (linelen > 0) {
                        line[linelen] = 0;
                        printk("Received: %s\n", line);
                        linelen = 0;
                    }
                } else if (linelen + 1 < sizeof(line)) {
                    line[linelen++] = c;
                } else {
                    linelen = 0;  // overflow reset
                }
            }
            break;
        }
        case UART_RX_BUF_REQUEST:
            if (!buf2_in_use) {
                uart_rx_buf_rsp(uart, rxbuf2, sizeof(rxbuf2));
                buf2_in_use = true;
            }
            break;
        case UART_RX_BUF_RELEASED:
            if (evt->data.rx_buf.buf == rxbuf2) buf2_in_use = false;
            break;
        case UART_RX_DISABLED:
            /* continuous */
            uart_rx_enable(uart, rxbuf1, sizeof(rxbuf1), RX_TIMEOUT_US);
            break;
        default:
            break;
        }
    }
    
    int main(void)
    {
        //uart = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
        uart = DEVICE_DT_GET(DT_NODELABEL(uart20));
        if (!device_is_ready(uart)) {
            return 0;
        }
        nrfx_power_constlat_mode_request(); //added
    
        printk("Hello World! uart20 on P2.02/P2.00 (CONSTLAT ON)\n");
    
        /* Async */
        uart_callback_set(uart, on_evt, NULL);
        uart_rx_enable(uart, rxbuf1, sizeof(rxbuf1), RX_TIMEOUT_US);
    
        while (1) {
            k_sleep(K_SECONDS(1));
        }
    }

    Best regards,
    Webb

Children
Related