UART async API with fifo / workqueue

Hi

I'm using the UART async API and want to pass the received data to a fifo or workqueue to them process this received data.

There does not seem to be any examples of doing this with the async API, so where can i find something ?

KR

  

Parents Reply Children
  • i found this, much easier example, might be of interest to others.

  • Just remember is based on an old version of NCS so it will not work out of the box 

    Regards

    Runar

  • From the top of my head, the include paths is wrong. I would recommend comparing them to one of the examples I have linked you. In NCS 2.0 Zephyr 3.0 was introduced and with it:  

    "All Zephyr public headers have been moved to include/zephyr, meaning they must be prefixed with <zephyr/...> when included. Because this change can potentially break many applications or libraries, CONFIG_LEGACY_INCLUDE_PATH is provided to allow using the old include path."

    You might be lucky and that is the only thing you have to care about. 

    Regards

    Runar

  • this is my code, it seems to work, can you check to see if you think i'm missing anything ?

    #include <stdio.h>
    #include <string.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/uart.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/ring_buffer.h>
    
    #include <zephyr/usb/usb_device.h>
    #include <zephyr/logging/log.h>
    
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/sys/util.h>
    
    //https://github.com/too1/ncs-uart-async-count-rx/blob/master/src/main.c
    
    #define UART_BUF_SIZE			500
    //#define UART_TX_TIMEOUT_MS		100
    #define UART_RX_TIMEOUT_MS		100*1000
    #define UART_RX_MSG_QUEUE_SIZE	8
    
    #define GNSS_THREAD_PRIORITY 	2
    #define GNSS_THREAD_STACK_SIZE 	1024
    
    LOG_MODULE_REGISTER(gnss, LOG_LEVEL_DBG);
    
    static const struct device *uart = 
    	DEVICE_DT_GET(DT_NODELABEL(uart0));
    
    static uint8_t uart_double_buffer[2][UART_BUF_SIZE];
    static uint8_t *uart_buf_next = uart_double_buffer[0];
    static uint8_t *uart_buf_prev = uart_double_buffer[1];
    
    struct uart_msg_queue_item {
    	uint8_t bytes[UART_BUF_SIZE];
    	uint32_t length;
    };
    
    const struct uart_config uart_cfg = {
    	.baudrate = 9600,
    	.parity = UART_CFG_PARITY_NONE,
    	.stop_bits = UART_CFG_STOP_BITS_1,
    	.data_bits = UART_CFG_DATA_BITS_8,
    	.flow_ctrl = UART_CFG_FLOW_CTRL_NONE
    };
    
    static void gnss_thread(void *unused1, void *unused2, void *unused3);
    static void uart_callback_handler(const struct device *dev, struct uart_event *evt, void *user_data);
    
    //K_SEM_DEFINE(rx_disabled, 0, 1);
    K_MSGQ_DEFINE(uart_rx_msgq, sizeof(struct uart_msg_queue_item), UART_RX_MSG_QUEUE_SIZE, 4);
    K_THREAD_DEFINE(gnss_thread_id, GNSS_THREAD_STACK_SIZE, gnss_thread, NULL, NULL, NULL, GNSS_THREAD_PRIORITY, 0, 0);
    
    void gns_init(void)
    {
    int result;
    
    
    	if (!device_is_ready(uart)) 
    	{
    		LOG_DBG("UART device not ready");
    
    		return;
    	}
    
    	result = uart_configure(uart, &uart_cfg);
    
    	if (result != 0) 
    	{
    		LOG_DBG("UART configuration error %i", result);
    
    		return;
    	}
    
    	uart_callback_set(uart, uart_callback_handler, NULL);
    	uart_rx_enable(uart, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
    }
    
    static void uart_callback_handler(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    int result;	
    static int toggle = 0;
    static struct uart_msg_queue_item new_message;
    
    
    	ARG_UNUSED(dev);
    
    	switch (evt->type) 
    	{
    		case UART_TX_DONE:
    			LOG_DBG("tx done");
    			break;
    
    		case UART_TX_ABORTED:
    			LOG_DBG("tx aborted");
    			break;
    
    		case UART_RX_STOPPED:
    			LOG_DBG("rx stopped");
    			break;
    			
    		case UART_RX_DISABLED:
    //			k_sem_give(&rx_disabled);
    
    			LOG_DBG("rx disabled");
    			break;
    
    		default:
    			LOG_ERR("unhandled case!");
    			break;
    
    		case UART_RX_BUF_RELEASED:
    			uart_buf_prev = evt->data.rx_buf.buf;
    
    			LOG_DBG("rx buffer release @ 0x%p size %i", 
    				   (void *)&uart_buf_prev, UART_BUF_SIZE);
    			break;			
    
    		case UART_RX_BUF_REQUEST:
    			toggle = (toggle ^ 1);
    
    			uart_buf_next = uart_double_buffer[toggle];
    
    			LOG_DBG("rx buffer request @ 0x%p size %i", 
    				   (void *)&uart_buf_next, UART_BUF_SIZE);
    
    			uart_rx_buf_rsp(uart, uart_buf_next, UART_BUF_SIZE);
    			break;
    
    		case UART_RX_RDY:
    			new_message.length = evt->data.rx.len;
    
    			memcpy(new_message.bytes, 
    				  (evt->data.rx.buf + evt->data.rx.offset), 
    				   evt->data.rx.len);
    
    			LOG_DBG("rx ready %i byte(s) offset %i",
                        evt->data.rx.len, evt->data.rx.offset);
    
    			result = k_msgq_put(&uart_rx_msgq, &new_message, K_NO_WAIT);
    
    			if(result != 0)
    			{
    				LOG_ERR("rx message queue full!");
    			}
    			break;
    	}
    }
    
    void gnss_thread(void *unused1, void *unused2, void *unused3)
    {
    int result;
    struct uart_msg_queue_item rx_message;
    
    
        ARG_UNUSED(unused1);
        ARG_UNUSED(unused2);
        ARG_UNUSED(unused3);
    
    	//k_sem_take(&ble_init_ok, K_FOREVER);
    
    	while(1)
    	{
    //		k_sleep(K_MSEC(2000));
    //		LOG_DBG("this is gnss_thread!");
    
    		result = k_msgq_get(&uart_rx_msgq, &rx_message, K_FOREVER);
    
    		if(result == 0)
    		{
    			
    			LOG_DBG("reading %i byte(s) from buffer", rx_message.length);
    
    			LOG_HEXDUMP_DBG(&rx_message.bytes[0], rx_message.length, "");
    		}
    	}
    }

Related