Problem with Async UART Example from peripheral_uart

Trying to integrate the serial part of the example code for use with a custom nRF52840 board. The problem is that I'm getting an error in uart_callback_set(uart, uart_cb, NULL) that is causing "Cannot initialize UART callback" to be displayed. I'm using UART1 which works with a different interrupt version of this code. Not sure what I'm missing here to get the callback initialized.

int initUart() {
int err;
int pos;
struct uart_data_t *rx;
struct uart_data_t *tx;

   //fifoInit();
   uart = device_get_binding("UART_1");
	__ASSERT(uart, "Failed to get UART device");
	//interrupt_driven(uart);

	if (!uart) {
		return -ENXIO;
	}

	rx = k_malloc(sizeof(*rx));
	if (rx) {
		rx->len = 0;
	} else {
		return -ENOMEM;
	}

	k_work_init_delayable(&uart_work, uart_work_handler);

	err = uart_callback_set(uart, uart_cb, NULL);
	if (err) {
		LOG_ERR("Cannot initialize UART callback");
		return err;
	}

CONFIG_STDOUT_CONSOLE=n
CONFIG_UART_CONSOLE=n
CONFIG_NRF_SW_LPUART=n
CONFIG_NRF_SW_LPUART_INT_DRIVEN=y

# UART
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_LINE_CTRL=n
CONFIG_UART_ASYNC_API=y
CONFIG_UART_0_ASYNC=y
CONFIG_UART_1_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC=y
CONFIG_UART_1_NRF_HW_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC_TIMER=1
CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2
CONFIG_NRFX_UARTE=y
CONFIG_NRFX_UARTE0=y
CONFIG_NRFX_UARTE1=y
CONFIG_NRFX_TIMER=y
CONFIG_NRFX_TIMER1=y
CONFIG_NRFX_TIMER2=y
CONFIG_NRFX_PPI=y
CONFIG_NRFX_TIMER2=y

  • Hello Paul, 

    The problem is that I'm getting an error in uart_callback_set(uart, uart_cb, NULL) that is causing "Cannot initialize UART callback" to be displayed. I'm using UART1 which works with a different interrupt version of this code. Not sure what I'm missing here to get the callback initialized.

    In your code snippet, I’m not able to find the definition of the call-back handler itself. That is probably the reason you get ‘Cannot initialise UART call-back’ displayed.  

    Cheers, 

    Markus 

  • Here is the callback code.

    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	ARG_UNUSED(dev);
    
    	static uint8_t *current_buf;
    	static size_t aborted_len;
    	static bool buf_release;
    	struct uart_data_t *buf;
    	static uint8_t *aborted_buf;
    
    	switch (evt->type) {
    	case UART_TX_DONE:
    		LOG_DBG("tx_done");
    		if ((evt->data.tx.len == 0) ||
    		    (!evt->data.tx.buf)) {
    			return;
    		}
    
    		if (aborted_buf) {
    			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    					   data);
    			aborted_buf = NULL;
    			aborted_len = 0;
    		} else {
    			buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t,
    					   data);
    		}
    
    		k_free(buf);
    
    		buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
    		if (!buf) {
    			return;
    		}
    
    		if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
    			LOG_WRN("Failed to send data over UART");
    		}
    
    		break;
    
    	case UART_RX_RDY:
    		LOG_DBG("rx_rdy");
    		buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data);
    		buf->len += evt->data.rx.len;
    		buf_release = false;
    
    		if (buf->len == UART_BUF_SIZE) {
    			k_fifo_put(&fifo_uart_rx_data, buf);
    		} else if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
    			  (evt->data.rx.buf[buf->len - 1] == '\r')) {
    			k_fifo_put(&fifo_uart_rx_data, buf);
    			current_buf = evt->data.rx.buf;
    			buf_release = true;
    			uart_rx_disable(uart);
    		}
    
    		break;
    
    	case UART_RX_DISABLED:
    		LOG_DBG("rx_disabled");
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    			k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    			return;
    		}
    
    		uart_rx_enable(uart, buf->data, sizeof(buf->data),
    			       UART_WAIT_FOR_RX);
    
    		break;
    
    	case UART_RX_BUF_REQUEST:
    		LOG_DBG("rx_buf_request");
    		buf = k_malloc(sizeof(*buf));
    		if (buf) {
    			buf->len = 0;
    			uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
    		} else {
    			LOG_WRN("Not able to allocate UART receive buffer");
    		}
    
    		break;
    
    	case UART_RX_BUF_RELEASED:
    		LOG_DBG("rx_buf_released");
    		buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
    				   data);
    		if (buf_release && (current_buf != evt->data.rx_buf.buf)) {
    			k_free(buf);
    			buf_release = false;
    			current_buf = NULL;
    		}
    
    		break;
    
    	case UART_TX_ABORTED:
    			LOG_DBG("tx_aborted");
    			if (!aborted_buf) {
    				aborted_buf = (uint8_t *)evt->data.tx.buf;
    			}
    
    			aborted_len += evt->data.tx.len;
    			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    					   data);
    
    			uart_tx(uart, &buf->data[aborted_len],
    				buf->len - aborted_len, SYS_FOREVER_MS);
    
    		break;
    
    	default:
    		break;
    	}
    }

  • NautDesigner said:
    Here is the callback code.

    Thanks, Paul! Looks ok to me, I would say. 

    What is the exact error code that is returned by uart_callback_set()? 

    Cheers, 

    Markus 

  • The problem is that api->callback_set is NULL. Where am I not setting this?

  • Hello Paul, 

    NautDesigner said:
    The problem is that api->callback_set is NULL. Where am I not setting this?

    I’m not quite sure why that happens. I took the Hello World sample as a starting point and added parts of the code you provided to it. 

    /*
     * Copyright (c) 2012-2014 Wind River Systems, Inc.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <zephyr/device.h>
    #include <drivers/uart.h>
    #include <zephyr/logging/log.h>
    
    LOG_MODULE_REGISTER(application_module, CONFIG_APPLICATION_MODULE_LOG_LEVEL);
    
    
    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    	// ARG_UNUSED(dev);
    
    	// static uint8_t *current_buf;
    	// static size_t aborted_len;
    	// static bool buf_release;
    	// struct uart_data_t *buf;
    	// static uint8_t *aborted_buf;
    
    	switch (evt->type) {
    	case UART_TX_DONE:
    		LOG_DBG("tx_done");
    		// if ((evt->data.tx.len == 0) ||
    		//     (!evt->data.tx.buf)) {
    		// 	return;
    		// }
    
    	// 	if (aborted_buf) {
    	// 		buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    	// 				   data);
    	// 		aborted_buf = NULL;
    	// 		aborted_len = 0;
    	// 	} else {
    	// 		buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t,
    	// 				   data);
    	// 	}
    
    	// 	k_free(buf);
    
    	// 	buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
    	// 	if (!buf) {
    	// 		return;
    	// 	}
    
    	// 	if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
    	// 		LOG_WRN("Failed to send data over UART");
    	// 	}
    
    	// 	break;
    
    	case UART_RX_RDY:
    		LOG_DBG("rx_rdy");
    		// buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data);
    		// buf->len += evt->data.rx.len;
    		// buf_release = false;
    
    		// if (buf->len == UART_BUF_SIZE) {
    		// 	k_fifo_put(&fifo_uart_rx_data, buf);
    		// } else if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
    		// 	  (evt->data.rx.buf[buf->len - 1] == '\r')) {
    		// 	k_fifo_put(&fifo_uart_rx_data, buf);
    		// 	current_buf = evt->data.rx.buf;
    		// 	buf_release = true;
    		// 	uart_rx_disable(uart);
    		// }
    
    		break;
    
    	// case UART_RX_DISABLED:
    	// 	LOG_DBG("rx_disabled");
    	// 	buf = k_malloc(sizeof(*buf));
    	// 	if (buf) {
    	// 		buf->len = 0;
    	// 	} else {
    	// 		LOG_WRN("Not able to allocate UART receive buffer");
    	// 		k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
    	// 		return;
    	// 	}
    
    	// 	uart_rx_enable(uart, buf->data, sizeof(buf->data),
    	// 		       UART_WAIT_FOR_RX);
    
    	// 	break;
    
    	// case UART_RX_BUF_REQUEST:
    	// 	LOG_DBG("rx_buf_request");
    	// 	buf = k_malloc(sizeof(*buf));
    	// 	if (buf) {
    	// 		buf->len = 0;
    	// 		uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
    	// 	} else {
    	// 		LOG_WRN("Not able to allocate UART receive buffer");
    	// 	}
    
    	// 	break;
    
    	// case UART_RX_BUF_RELEASED:
    	// 	LOG_DBG("rx_buf_released");
    	// 	buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
    	// 			   data);
    	// 	if (buf_release && (current_buf != evt->data.rx_buf.buf)) {
    	// 		k_free(buf);
    	// 		buf_release = false;
    	// 		current_buf = NULL;
    	// 	}
    
    	// 	break;
    
    	// case UART_TX_ABORTED:
    	// 		LOG_DBG("tx_aborted");
    	// 		if (!aborted_buf) {
    	// 			aborted_buf = (uint8_t *)evt->data.tx.buf;
    	// 		}
    
    	// 		aborted_len += evt->data.tx.len;
    	// 		buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
    	// 				   data);
    
    	// 		uart_tx(uart, &buf->data[aborted_len],
    	// 			buf->len - aborted_len, SYS_FOREVER_MS);
    
    	// 	break;
    
    	default:
    		break;
    	}
    }
    
    void main(void)
    {
    	LOG_INF("Hello World! %s", CONFIG_BOARD);
    
    	int err;
    	//int pos;
    	//struct uart_data_t *rx;
    	//struct uart_data_t *tx;
    
       	//fifoInit();
    	const struct device *uart;
       	uart = device_get_binding("UART_1");
    	__ASSERT(uart, "Failed to get UART device");
    	//interrupt_driven(uart);
    
    	if (!uart) {
    		return /*-ENXIO*/;
    	}
    
    	// rx = k_malloc(sizeof(*rx));
    	// if (rx) {
    	// 	rx->len = 0;
    	// } else {
    	// 	return /*-ENOMEM*/;
    	// }
    
    	//k_work_init_delayable(&uart_work, uart_work_handler);
    
    	err = uart_callback_set(uart, uart_cb, NULL);
    	if (err) {
    		LOG_ERR("Cannot initialize UART callback");
    		return /*err*/;
    	}
    	else LOG_INF("UART callback handler successfully initialised!");
    }

    # nothing here
    CONFIG_UART_ASYNC_API=y
    CONFIG_LOG=y

    I’m not able to reproduce the error, see log below. 

    *** Booting Zephyr OS build v3.0.99-ncs1  ***
    [00:00:00.366,516] <inf> application_module: Hello World! nrf52840dk_nrf52840
    [00:00:00.366,516] <inf> application_module: UART callback handler successfully initialised!

    Could this maybe be a devicetree issue with your custom board? 

    Cheers, 

    Markus 

Related