I'm working on implementing asynchronous UART on a nRF52840dk but uart_callback_set() is returning -88 (ENOSYS), which according to the tutorial here means it's not supported by the device. According to the Product Specification the UART is asynchronous (via EasyDMA), so I must be doing something wrong.
My overlay:
&pinctrl { uart1_default: uart1_default { group1 { psels = <NRF_PSEL(UART_TX, 1, 2)>, <NRF_PSEL(UART_RX, 1, 1)>; }; }; /* required if CONFIG_PM_DEVICE=y */ uart1_sleep: uart1_sleep { group1 { psels = <NRF_PSEL(UART_TX, 1, 2)>, <NRF_PSEL(UART_RX, 1, 2)>; low-power-enable; }; }; }; &uart1 { compatible = "nordic,nrf-uarte"; current-speed = <38400>; status = "okay"; pinctrl-0 = <&uart1_default>; pinctrl-1 = <&uart1_sleep>; pinctrl-names = "default", "sleep"; };
My config:
# From prj.conf CONFIG_NCS_SAMPLES_DEFAULTS=y CONFIG_CONSOLE=y CONFIG_CONSOLE_SUBSYS=y CONFIG_CONSOLE_HANDLER=y CONFIG_CONSOLE_GETCHAR=y CONFIG_BT_CTLR_SDC_LLPM=y CONFIG_BT_DEVICE_NAME="Nordic_LLPM" CONFIG_BT=y CONFIG_BT_DEBUG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y CONFIG_BT_MAX_CONN=2 CONFIG_BT_SCAN=y CONFIG_BT_SCAN_FILTER_ENABLE=y CONFIG_BT_SCAN_UUID_CNT=1 CONFIG_BT_LATENCY=y CONFIG_BT_LATENCY_CLIENT=y CONFIG_BT_LL_SOFTDEVICE=y CONFIG_BT_HCI_VS_EVT_USER=y CONFIG_HEAP_MEM_POOL_SIZE=2048 CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n CONFIG_GPIO=y CONFIG_UART_ASYNC_API=y # From nrf52840dk_nrf52840.conf CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_REMOTE_WAKEUP=n CONFIG_USB_DEVICE_PRODUCT="LLPM sample console" CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y CONFIG_UART_CONSOLE=y #Tried commenting out CONFIG_UART_INTERRUPT_DRIVEN=y #Tried commenting out CONFIG_UART_LINE_CTRL=y #Tried commenting out # Since the default LOG_MODE_MINIMAL is synchronous, it will mess with the USB # driver/subsys. Use the deferred mode instead. CONFIG_LOG_MODE_DEFERRED=y
Relevant code:
printk("Starting Uart1\r\n"); struct device *uart uart = DEVICE_DT_GET(DT_NODELABEL(uart1)); if (!device_is_ready(uart)) { printk("Uart1 not ready!\r\n"); return; } const struct uart_config uart_cfg = { .baudrate = 38400, .parity = UART_CFG_PARITY_NONE, .stop_bits = UART_CFG_STOP_BITS_1, .data_bits = UART_CFG_DATA_BITS_7, .flow_ctrl = UART_CFG_FLOW_CTRL_NONE }; err = uart_configure(uart, &uart_cfg); if (err == -ENOSYS) { printk("Uart1 configure failure: %d\r\n", err); return; } err = uart_callback_set(uart, uart_cb, NULL); if (err) { printk("Uart1 callback set failure: %d\r\n", err); return; } err = uart_rx_enable(uart, rx_buf, RX_BUFF_SIZE, 50); // 50ms timeout if (err) { printk("Uart1 rx buffer enable failure: %d\r\n", err); return; }
I used the llpm application as a starting point while following the nordic academy lesson above, I'm wondering if there's maybe a conflict with the config values that were there initially? Or I've noticed that the .dts file for the nrf52840dk is quite busy, possibly something conflicts there? Fwiw I initially implemented polling and had it working well before I tried the asynchronous approach. For that reason I have some confidence in my device tree.
Other than above issue, a few questions also have come to mind:
- Should I be using drivers/uarte.h instead of drivers/uart.h because of the EasyDMA support of the chipset? Would that be a problem if I didn't? I only favored uart.h because most of the examples follow it
- Does it matter if I enable CONFIG_UART_INTERRUPT_DRIVEN with the asynchronous approach? I've tried it both ways
Thanks