Hello, I am relatively new to the Zephyr project and I have made a custom board nrf52840dk
based 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.