UART missing bytes and the data is also not read in correct order.

I ma supposed to read FA0A03048100020000F , BUT I END UP READING FA0A030482000202020202.  This is also common with the peripheral i am trying to interact, It sends a packet every 1second and i always read only first 5 byes but that too in incorrect order

/*
 * Copyright (c) 2022 Libre Solar Technologies GmbH
 *
 * SPDX-License-Identifier: Apache-2.0
 */

 #include <zephyr.h>
 #include <device.h>
 #include <drivers/uart.h>
 #include <string.h>
 #include <sys/printk.h>
 
 /* Change this to any other UART peripheral if desired */
 #define UART_DEVICE_NODE DT_NODELABEL(uart1)
 
 #define RX_BUF_SIZE 10  // Expecting 10-byte packets
 #define MSG_Q_SIZE 10    // Queue to store 10 messages
 
 /* Queue to store received messages */
 K_MSGQ_DEFINE(uart_msgq, RX_BUF_SIZE, MSG_Q_SIZE, 4);
 
 static const struct device *uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);
 
 /* Receive buffer */
 static uint8_t rx_buf[RX_BUF_SIZE];
 static int rx_buf_pos = 0;
 
 /*
  * UART interrupt callback for receiving hex data
  */
 void serial_cb(const struct device *dev, void *user_data)
 {
	 uint8_t c,d;
 
	 if (!uart_irq_update(uart_dev)) {
		 return;
	 }
 
	 while (uart_irq_rx_ready(uart_dev)) {
		 uart_fifo_read(uart_dev, &d, 1);
		 if(d==0xFA)
		 {
			for(int i=0;i<=10;i++)
			{
			uart_poll_in(uart_dev,&c);
			rx_buf[i]=c;
			rx_buf_pos=i;
			k_msleep(1);
			}
			// while(rx_buf_pos<=RX_BUF_SIZE)
			// uart_fifo_read(uart_dev, &c, 1);
			// rx_buf[rx_buf_pos++] = c;
		 }
		 
 
		 /* If we've received the expected number of bytes, process the packet */
		 if (rx_buf_pos >= RX_BUF_SIZE) {
			 k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);
			 rx_buf_pos = 0;  // Reset buffer position for the next packet
			 d=0;
		 }
	 }
 }
 
 /*
  * Print received data in hex format
  */
 void print_hex(uint8_t *buf, int len)
 {
	 printk("Received: ");
	 for (int i = 0; i < len; i++) {
		 printk("%02X ", buf[i]);  // Print each byte as hex
	 }
	 printk("\r\n");
 }
 
 void main(void)
 {
	 uint8_t tx_buf[RX_BUF_SIZE];
 
	 if (!device_is_ready(uart_dev)) {
		 printk("UART device not found!\r\n");
		 return;
	 }
 
	 /* Configure interrupt and callback to receive data */
	 uart_irq_callback_user_data_set(uart_dev, serial_cb, NULL);
	 uart_irq_rx_enable(uart_dev);
 
	 printk("UART Hex Receiver Ready.\r\n");
 
	 /* Wait for input and print received hex data */
	 while (k_msgq_get(&uart_msgq, &tx_buf, K_FOREVER) == 0) {
		 print_hex(tx_buf, RX_BUF_SIZE);
	 }
 }
 

Parents
  • Hi,

     

    The logic you have in the uart callback is not ideal:

    		 uart_fifo_read(uart_dev, &d, 1);
    		 if(d==0xFA)
    		 {
    			for(int i=0;i<=10;i++)
    			{
    			uart_poll_in(uart_dev,&c);
    			rx_buf[i]=c;
    			rx_buf_pos=i;
    			k_msleep(1);
    			}
    			// while(rx_buf_pos<=RX_BUF_SIZE)
    			// uart_fifo_read(uart_dev, &c, 1);
    			// rx_buf[rx_buf_pos++] = c;
    		 }

     

    This will overflow your buffer, as it will read 11 bytes (From 0...10) into a 10 byte buffer.

    You are using a byte-for-byte poll function, with a k_sleep in interrupt context. I would recommend that you use "uart_fifo_read" and stop when it returns '0'.

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    The logic you have in the uart callback is not ideal:

    		 uart_fifo_read(uart_dev, &d, 1);
    		 if(d==0xFA)
    		 {
    			for(int i=0;i<=10;i++)
    			{
    			uart_poll_in(uart_dev,&c);
    			rx_buf[i]=c;
    			rx_buf_pos=i;
    			k_msleep(1);
    			}
    			// while(rx_buf_pos<=RX_BUF_SIZE)
    			// uart_fifo_read(uart_dev, &c, 1);
    			// rx_buf[rx_buf_pos++] = c;
    		 }

     

    This will overflow your buffer, as it will read 11 bytes (From 0...10) into a 10 byte buffer.

    You are using a byte-for-byte poll function, with a k_sleep in interrupt context. I would recommend that you use "uart_fifo_read" and stop when it returns '0'.

     

    Kind regards,

    Håkon

Children
No Data
Related