This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

UART isue

Hi,

I experience a very strange issue with UART.

When I try to send data via /dev/ttyACM0 device it looks like the characters sent are buffered and sent only upon the following transmission,

and in some circumstances the first character gets overwritten.

For instance, using minicom, when I type-in: 1234,
The following output is printed: 

in uart_irq_handler!                                                            
RX is ready!                                                                    
value: ~                                                                        
in uart_irq_handler!                                                            
RX is ready!                                                                    
value: 1                                                                          
in uart_irq_handler!                                                            
RX is ready!                                                                    
value: 2                                                                          
in uart_irq_handler!                                                            
RX is ready!                                                                    
value: 3      

trying afterwards: echo -en "1,abc" > /dev/ttyACM0

I get:

in uart_irq_handler!                                                            
RX is ready!                                                                    
value: 4                                                                        
value: ,                                                                        
value: a                                                                        
value: b                                                                        
value: c                                                                        
in uart_irq_handler!                                                            
RX is not ready! 

Details about my environment:

  • nrf52833DK
  • nRF Connect SDK 1.7.1
  • minicom is configured with 115200, 8N1, Hardware & Software flow control Np
  • I have modified the nrf25833,dtsi file to contain the following uart&lpuart sections:
  • uart1: uart@40028000 {
    	        compatible = "nordic,nrf-uarte";
    	        current-speed = <115200>;
    	        reg = <0x40028000 0x1000>;
    	        interrupts = <40 5>;
    	        label = "UART_1";
    	        status = "okay";
    	        /delete-property/ rts-pin;
    	        /delete-property/ cts-pin;
    	        /delete-property/ hw-flow-control;
    
    	        lpuart: nrf-sw-lpuart {
    	                compatible = "nordic,nrf-sw-lpuart";
    	                status = "okay";
    	                label = "LPUART";
    	                req-pin = <46>;
    	                rdy-pin = <47>;
    	        };
    		};

Source code:

#include <zephyr.h>
#include <zephyr/types.h>
#include <sys/printk.h>
#include <drivers/uart.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

static void uart_irq_handler(const struct device *lpuart_device, void *context)
{
    int result;

    printk("in uart_irq_handler!\n");
    result = uart_irq_update(lpuart_device);
    if (result != 1) {
        printk("uart_irq_update failed, with error: %d\n", result);
        return ;
    }

	if (uart_irq_rx_ready(lpuart_device)) {
		uint8_t buffer[100];
        char command[100];
		int length;
        printk("RX is ready!\n", result);
		do {
            length = uart_fifo_read(lpuart_device, buffer, sizeof(buffer));
            if (length > 0) {
                sprintf(command, "%c", buffer[0]);
                printk("value: %s\n",command);
                buffer[0] = '-1';
            }
		} while (length > 0) ;
	} else {
         printk("RX is not ready!\n", result);
         uart_irq_update(lpuart_device);
    }
}


void start_uart(void) {

    const struct device *lpuart_device;
    uint8_t buffer[1];

    printk("in start_uart\n");
	lpuart_device = device_get_binding("UART_0");
	if (lpuart_device == NULL) {
        printk("Error! CANNOT get low power UART device!\n");
        return ;
    }
	uart_irq_callback_set(lpuart_device, uart_irq_handler);
	uart_irq_rx_enable(lpuart_device);
    printk("in start_uart, successfully set UART IRQ\n");
}

Parents Reply Children
  • Sure!

    Here's the source code:
    .

    #include <zephyr.h>
    #include <device.h>
    #include <drivers/uart.h>
    
    #include <string.h>
    
    /* change this to any other UART peripheral if desired */
    #define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)
    
    #define MSG_SIZE 32
    
    /* queue to store up to 10 messages (aligned to 4-byte boundary) */
    K_MSGQ_DEFINE(uart_msgq, MSG_SIZE, 10, 4);
    
    static const struct device *uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);
    
    /* receive buffer used in UART ISR callback */
    static char rx_buf[MSG_SIZE];
    static int rx_buf_pos;
    
    /*
     * Read characters from UART until line end is detected. Afterwards push the
     * data to the message queue.
     */
    void serial_cb(const struct device *dev, void *user_data)
    {
    	uint8_t c;
    
    	if (!uart_irq_update(uart_dev)) {
    		return;
    	}
    
    	while (uart_irq_rx_ready(uart_dev)) {
    
    		uart_fifo_read(uart_dev, &c, 1);
    
    		if ((c == '\n' || c == '\r') && rx_buf_pos > 0) {
    			/* terminate string */
    			rx_buf[rx_buf_pos] = '\0';
    
    			/* if queue is full, message is silently dropped */
    			k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);
    
    			/* reset the buffer (it was copied to the msgq) */
    			rx_buf_pos = 0;
    		} else if (rx_buf_pos < (sizeof(rx_buf) - 1)) {
    			rx_buf[rx_buf_pos++] = c;
    		}
    		/* else: characters beyond buffer size are dropped */
    	}
    }
    
    /*
     * Print a null-terminated string character by character to the UART interface
     */
    void print_uart(char *buf)
    {
    	int msg_len = strlen(buf);
    
    	for (int i = 0; i < msg_len; i++) {
    		uart_poll_out(uart_dev, buf[i]);
    	}
    }
    
    void main(void)
    {
    	char tx_buf[MSG_SIZE];
    
    	if (!device_is_ready(uart_dev)) {
    		printk("UART device not found!");
    		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);
    
    	print_uart("Hello! I'm your echo bot.\r\n");
    	print_uart("Tell me something and press enter:\r\n");
    
    	/* indefinitely wait for input from the user */
    	while (k_msgq_get(&uart_msgq, &tx_buf, K_FOREVER) == 0) {
    		print_uart("Echo: ");
    		print_uart(tx_buf);
    		print_uart("\r\n");
    	}
    }

    prj.conf:

    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096
    
    # BT configuration 
    CONFIG_BT=y
    CONFIG_BT_DEBUG_LOG=y
    CONFIG_BT_SMP=y
    CONFIG_BT_SIGNING=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DIS=n
    CONFIG_BT_ATT_PREPARE_COUNT=5
    CONFIG_BT_BAS=n
    CONFIG_BT_HRS=n
    CONFIG_BT_PRIVACY=y
    CONFIG_BT_DEVICE_NAME="AAA"
    CONFIG_BT_DEVICE_APPEARANCE=833
    CONFIG_BT_DEVICE_NAME_DYNAMIC=y
    CONFIG_BT_DEVICE_NAME_MAX=128
    CONFIG_BT_KEYS_OVERWRITE_OLDEST=y
    CONFIG_BT_SETTINGS=y
    CONFIG_BT_L2CAP_TX_MTU=252
    CONFIG_BT_BUF_ACL_RX_SIZE=256
    
    CONFIG_FLASH=y
    CONFIG_FLASH_PAGE_LAYOUT=y
    CONFIG_FLASH_MAP=y
    CONFIG_NVS=y
    CONFIG_SETTINGS=y
    
    CONFIG_PRINTK=y
    CONFIG_LOG_PRINTK=y
    CONFIG_LOG=y
    CONFIG_LOG_MODE_IMMEDIATE=y
    CONFIG_LOG_MAX_LEVEL=4
    CONFIG_USE_SEGGER_RTT=y
    CONFIG_RTT_CONSOLE=y
    CONFIG_UART_CONSOLE=y
    
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_SECURE_BOOT=y
    CONFIG_MCUMGR=y
    CONFIG_MCUMGR_CMD_OS_MGMT=y
    CONFIG_MCUMGR_CMD_IMG_MGMT=y
    CONFIG_MCUMGR_SMP_BT=y
    CONFIG_MCUMGR_SMP_BT_AUTHEN=n
    
    CONFIG_IMG_MANAGER=y
    
    CONFIG_NRFX_TEMP=y
    
    CONFIG_SERIAL=y
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_UART_USE_RUNTIME_CONFIGURE=y
    CONFIG_USB_CDC_ACM=n

    rv32m1_vega_ri5cy.overlay:

    /*
     * Copyright 2019 NXP
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    &lptmr1 {
    	interrupt-parent = <&intmux0_ch2>;
    };
    
    &intmux0_ch2 {
    	status = "okay";
    };
    
    &intmux0_ch3 {
    	status = "okay";
    };
    
    &generic_fsk {
    	interrupt-parent = <&intmux0_ch3>;
    	status = "okay";
    };
    

    Please let me know how it behaves for you and what you see.

    Thanks!

  • Vitaliy Freidovich said:
    rv32m1_vega_ri5cy.overlay:

    Is this the correct file? It's not for the nrf52833 board, and you don't include the uart configurations here.

  • Yes, it's the only overlay file that I have, and you're right, I think it's not even used by the IDE (Visual Studio Code).

  • But as you said earlier

    I have modified the nrf25833,dtsi file to contain the following uart&lpuart sections:

    Did you modify the dts file directly, instead of writing the changes to an overlay file? The dts file is not supposed to be modified directly. It might not matter at all, but I just want to make sure I have your exact setup before I proceed.

Related