uart_callback_set() returns ENOSYS on nRF52840dk

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

Parents
  • fwiw, I've had this problem after upgrading ncs from v1.9.1 to v2.1.2, and none of the measures suggested here fixed it for me.

    The config that finally worked was this:

    CONFIG_UART_ASYNC_API=y
    CONFIG_UART_0_ASYNC=y
    CONFIG_UART_0_INTERRUPT_DRIVEN=n
    CONFIG_NRFX_UARTE0=y
    

    Note that I had to explicitly set CONFIG_UART_0_INTERRUPT_DRIVEN=n, otherwise CONFIG_UART_0_ASYNC=y would be ignored.

Reply
  • fwiw, I've had this problem after upgrading ncs from v1.9.1 to v2.1.2, and none of the measures suggested here fixed it for me.

    The config that finally worked was this:

    CONFIG_UART_ASYNC_API=y
    CONFIG_UART_0_ASYNC=y
    CONFIG_UART_0_INTERRUPT_DRIVEN=n
    CONFIG_NRFX_UARTE0=y
    

    Note that I had to explicitly set CONFIG_UART_0_INTERRUPT_DRIVEN=n, otherwise CONFIG_UART_0_ASYNC=y would be ignored.

Children
Related