Using UART different methods

I'm using nRF Connect SDK with nRF52840dk and going through the UART samples and currently have both the Polling and Async methods working to some extent. But questions for each.

With Polling I'm able to read/write seeming indefinitely but messages received from my modem through UART are truncated to about 6 characters.

// prj.conf
CONFIG_SERIAL=y

// main.c

....

void main(void)
{

	if (!device_is_ready(uart0_dev) || !device_is_ready(uart1_dev)) {
		printk("UART device not found!");
		return;
	}

	char c;
	while (1) {
		if (uart_poll_in(uart0_dev, &c) == 0) {
			uart_poll_out(uart1_dev, c);
		}

		if (uart_poll_in(uart1_dev, &c) == 0) {
			uart_poll_out(uart0_dev, c);
		}
		k_usleep(100);
	}
}

Then with Async I'm able to read the full responses, but I can't figure out how to clear the rx buffer without dynamic allocation. I'd just like to set all buffer entries to 0 and reset offset, or use a ring buffer and allow it to wrap, whichever is easier. Currently the serial comm becomes unresponsive once offset increases beyond the array size, as one would expect.

// prj.conf
CONFIG_UART_ASYNC_API=y

// main.c

...

static uint8_t rx_buf[100] = { 0 };
static uint8_t tx_buf[100] = { 0 };
static void uart_cb(const struct device* dev, struct uart_event* evt, void* user_data)
{
	switch (evt->type) {
	case UART_RX_RDY: {
		bool pressedEnter = evt->data.rx.buf[evt->data.rx.offset] == '\r';
		if (pressedEnter) {
			rx_buf[evt->data.rx.offset] = '\0';
			printk("Pressed enter and buffer is %s\n", rx_buf);
		} else {
			printk("buf %s, len: %d, offset: %d\n", evt->data.rx.buf, evt->data.rx.len, evt->data.rx.offset);
		}
		break;
	}
	default:
		break;
	}
}

void main(void)
{
	// Persistent data
	const struct device* uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
	if (!device_is_ready(uart)) {
		printk("UART device not ready\n\r");
		return;
	}
	uart_callback_set(uart, uart_cb, NULL);
	uart_rx_enable(uart, rx_buf, sizeof(rx_buf), 100);

	strcpy(tx_buf, "Type a string, press enter, and it will be stored\n\r");
	uart_tx(uart, tx_buf, sizeof(tx_buf), SYS_FOREVER_US);

	while (1) {
		k_msleep(1000);
	}
}

Can you see what I'm doing wrong with the polling method and how I can clear the buffer with the async method? I haven't seen anything in the documentation yet that covers these cases, nor the DevAcademy series. My goal is to be able to read and write to uart outside of a callback, could a message queue allow that?

Parents
  • Hi 

    It is possible to copy the received data into a message queue or buffer. You just need to keep in mind that the offset value is for the source buffer in the UART driver, not for your own buffer. 

    There is an unofficial sample available here showing how you can handle UART async with non dynamic memory management. In particular take a look at the handling of the RX callback here.

    Best regards
    Torbjørn 

  • Thanks for the direction! I ended up using async RX with a message queue, very similar to the implementation in the echo_bot example which fit my needs perfectly

    // serial.c
    void serial_cb(const struct device* dev, void* user_data)
    {
        uint8_t c;
        while (uart_irq_rx_ready(uart1_dev)) {
            uart_fifo_read(uart1_dev, &c, 1);
            bool is_break = c == '\n' || c == '\r';
    
            if (is_break && rx_buf_pos > 0) {
                rx_buf[rx_buf_pos] = '\0';
                k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);
                rx_buf_pos = 0;
            } else if (!is_break && rx_buf_pos < (sizeof(rx_buf) - 1)) {
                rx_buf[rx_buf_pos++] = c;
            }
        }
    }
    
    // main.c
    while (1) {
    	// will be a full line received from the message queue
    	while (k_msgq_get(&uart_msgq, &tx_buf, K_NO_WAIT) == 0) {
    		print_uart("Echo: ");
    		print_uart(tx_buf); 
    		print_uart("\r\n");
    	}
    	// will be a single character from user to send to modem
    	while (uart_poll_in(uart0_dev, &c) == 0) { 
    		printk("%c", c);
    		uart_poll_out(uart1_dev, c);
    	}
    
    }

  • Hi 

    Good to hear that you found a good solution. The best of luck with your project Slight smile

    Best regards
    Torbjørn

Reply Children
No Data
Related