Hello, I am relatively new to the Zephyr project and I have made a custom board nrf52840dkbased on the nRF52840 Development Kit (nrf52840dk_nrf52840). It is the nRF52840 Development Kit I am flashing to.

My goal is to define three UARTs or UARTEs that I can use in my application. Below is the relevant device tree files for the custom board nrf52840dk with two UARTEs (uart0 and uart1). This works like a charm on the demonstration program app\src\main.c.

boards\arm\nrf52840dk\nrf52840dk-pinctrl.dtsi

&pinctrl {
	uart0_default: uart0_default {
		group1 {
			psels =	<NRF_PSEL(UART_TX, 0, 6)>,
					<NRF_PSEL(UART_RTS, 0, 5)>;
		};
		group2 {
			psels =	<NRF_PSEL(UART_RX, 0, 8)>,
					<NRF_PSEL(UART_CTS, 0, 7)>;
			bias-pull-up;
		};
	};
	uart0_sleep: uart0_sleep {
		group1 {
			psels =	<NRF_PSEL(UART_TX, 0, 6)>,
					<NRF_PSEL(UART_RX, 0, 8)>,
					<NRF_PSEL(UART_RTS, 0, 5)>,
					<NRF_PSEL(UART_CTS, 0, 7)>;
			low-power-enable;
		};
	};
	uart1_default: uart1_default {
		group1 {
			psels =	<NRF_PSEL(UART_RX, 0, 14)>;
			bias-pull-up;
		};
		group2 {
			psels =	<NRF_PSEL(UART_TX, 0, 16)>;
		};
	};
	uart1_sleep: uart1_sleep {
	   group1 {
			psels =	<NRF_PSEL(UART_RX, 0, 14)>,
		  			<NRF_PSEL(UART_TX, 0, 16)>;
		  low-power-enable;
		};
	};
};

boards\arm\nrf52840dk\nrf52840dk.dts

/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>
#include "nrf52840dk-pinctrl.dtsi"

/ {
	model = "nRF52840 DK Board";
	compatible = "nordic,nrf52840dk";

	chosen {
		zephyr,console = &uart0;
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
	};
};

&uart0 {
	compatible = "nordic,nrf-uarte";
	status = "okay";
	current-speed = <115200>;
	pinctrl-0 = <&uart0_default>;
	pinctrl-1 = <&uart0_sleep>;
	pinctrl-names = "default", "sleep";
};

&uart1 {
	compatible = "nordic,nrf-uarte";
	current-speed = <115200>;
	status = "okay";
	pinctrl-0 = <&uart1_default>;
	pinctrl-1 = <&uart1_sleep>;
	pinctrl-names = "default", "sleep";
};

app\src\main.c

#include <app_version.h>
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL);

#define UART0_DEVICE_NODE DT_NODELABEL(uart0)
#define UART1_DEVICE_NODE DT_NODELABEL(uart1)

static const struct device *const uart0_dev = DEVICE_DT_GET(UART0_DEVICE_NODE);
static const struct device *const uart1_dev = DEVICE_DT_GET(UART1_DEVICE_NODE);

/**
 * @brief Print a null-terminated string, character by character, to the UART
 * interface.
 *
 * @param dev the UART device to print from.
 * @param str the null-terminated string to print.
 */
void print_uart(const struct device *dev, const char *str) {
    const size_t str_len = strlen(str);
    for (size_t i = 0; i < str_len; i++) {
        uart_poll_out(dev, str[i]);
    }
}

/**
 * @brief This is where the magic happens.
 */
int main(void) {
    LOG_INF("Application version %s initialized on board %s!", APP_VERSION_STRING, CONFIG_BOARD);

	// Print on uart0.
    print_uart(uart0_dev, "uart0: ");
    print_uart(uart0_dev, uart0_dev->name);
    print_uart(uart0_dev, "\r\n");

	// Print on uart1.
    print_uart(uart1_dev, "uart1: ");
    print_uart(uart1_dev, uart1_dev->name);
    print_uart(uart1_dev, "\r\n");

    LOG_INF("Application version %s shutting down on board %s!", APP_VERSION_STRING, CONFIG_BOARD);
    return 0;
}

The problems arise when I try to implement another UART: uart2. To begin with, I don’t know if a third UART or UARTE is supported in the first place. In stripped down form, the changes to the respective files are:

boards\arm\nrf52840dk\nrf52840dk-pinctrl.dtsi

// Stripped down version.
&pinctrl {
	uart2_default: uart2_default {
		group1 {
			psels =	<NRF_PSEL(UART_RX, 0, 1)>;
			bias-pull-up;
		};
		group2 {
			psels =	<NRF_PSEL(UART_TX, 0, 2)>;
		};
	};
	uart2_sleep: uart2_sleep {
	   group1 {
			psels =	<NRF_PSEL(UART_RX, 0, 1)>,
		  			<NRF_PSEL(UART_TX, 0, 2)>;
		  low-power-enable;
		};
	};
};

boards\arm\nrf52840dk\nrf52840dk.dtsi

// Stripped down version.
&uart2 {
	compatible = "nordic,nrf-uart";
	current-speed = <115200>;
	status = "okay";
	pinctrl-0 = <&uart2_default>;
	pinctrl-1 = <&uart2_sleep>;
	pinctrl-names = "default", "sleep";
};

app\src\main.c

// Stripped down version.
#define UART2_DEVICE_NODE DT_NODELABEL(uart2)

static const struct device *const uart2_dev = DEVICE_DT_GET(UART2_DEVICE_NODE);

int main(void) {
    // Print on uart2.
    print_uart(uart2_dev, "uart2: ");
    print_uart(uart2_dev, uart2_dev->name);
    print_uart(uart2_dev, "\r\n");
}

When I build the application with the command west build -p always -b nrf52840dk app, the operation fails. The error given is:
devicetree error: path/to/zephyr-uarts-project/zephyr-application/boards/arm/nrf52840dk/nrf52840dk.dts:42 (column 1): parse error: undefined node label 'uart2'

Given that the node label is undefined. Is it possible to define it on my own? For example in a way like this?

boards\arm\nrf52840dk\nrf52840dk.dtsi

// Stripped down version.
/ {
	model = "nRF52840 DK Board";
	compatible = "nordic,nrf52840dk";

	chosen {
		zephyr,console = &uart0;
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
	};

	soc {
		uart2: uart@some_address_here {
			compatible = "nordic,nrf-uart";  // or "nordic,nrf-uarte"?
			reg = <some_address_here 0x1000>;
			interrupts = <interrupt_number_here NRF_DEFAULT_IRQ_PRIORITY>;
		};
	};
};

Any input on this matter is greatly appreciated. Thank you in advance.

If there is no uart2 (i.e. third UART) in the nRF52 .dts file your editing from there’s likely not a 3rd UART supported by the hardware. From what I remember about the nRF52840 there’s only two. (search for UART on that page)

Terms and Conditions | Privacy Policy