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
  • Can't edit my original comment so I'm going to put a few extra thoughts/ideas here...

    • I still don't 100% know what I'm doing with the device tree.  The compatibility field has uarte instead of uart, but changing it to uart has a linking failure
    • Generally, I feel like I'm configuring everything twice, once in the device tree, then again in my source coded.  I'm referring specifically to the UART config (baud rate, parity, etc).  Is that right?  Do I need it in my source code?
    • I am confusing the drivers/uart.h and the nrf_uart.h / nrf_uarte.h headers.  When do i use which?
  • @kenneth - Noridc's website seems buggy and I'm not getting the reply option to your message, so I have to reply inline with my own (or maybe I don't understand how it works).

    Thanks for the response and clarification regarding what header file to include.  I assume that the library under the hood selects between the uart and uarte implementation based on what the board supports.

    Also, yes, the uart_callback is of the correct form, so it's not clear why that's failing.  I had also looked at the function.

    What I have stumbled upon is this:

    It seems that CONFIG_UART_INTERRUPT_DRIVEN is being set to y somewhere else, it says "In build".  Where would that be?  The config file for the board does not set it, how can I find where it is being set?

  • This really seems to be my problem.  I haven't seen anything that suggests that CONFIG_UART_INTERRUPT_DRIVEN=y would break the uart_callback_set() function in that way, however, it does make sense.


    Right now it seems there is some unknown chain of implied config values that I cannot chase down.  I get this warning at build time:

    warning: UART_INTERRUPT_DRIVEN (defined at boards/shields\sparkfun_sara_r4\Kconfig.defconfig:24,
    boards/shields\wnc_m14a2a\Kconfig.defconfig:17, soc/arm\quicklogic_eos_s3\Kconfig.defconfig:17,
    drivers/serial/Kconfig:72) was assigned the value 'n' but got the value 'y'. See
    http://docs.zephyrproject.org/latest/kconfig.html#CONFIG_UART_INTERRUPT_DRIVEN and/or look up
    UART_INTERRUPT_DRIVEN in the menuconfig/guiconfig interface. The Application Development Primer,
    Setting Configuration Values, and Kconfig - Tips and Best Practices sections of the manual might be
    helpful too.

    However the warning doesn't provide a lot of guidance regarding what config value implied it.  My guess is 

    CONFIG_CONSOLE_HANDLER, but when setting 
    CONFIG_CONSOLE_HANDLER=n the warning then changes that 
    CONFIG_CONSOLE_HANDLER is being set to y.  Following it further seems like a bit of a rabbit hole.
  • The problem did turn out to be configuration, although I was not able to determine what specifically.

    I tried using the peripheral_uart sample as a starting point per Kenneth's suggestion but even that failed.  I actually started completely from scratch so all my config and overlay files were empty and added everything one by one.  The code worked exactly as I have it above.

Reply Children
No Data
Related