nrf9160 uart0

Hi:

I tested that uart0 can't be used.

I want to use uart_tx( uart, tx, 10, 0); to print "1234567890".

But UART0 is not output.Shown below:

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

static uint8_t uart_buf[1024];

struct device *uart;

void uart_cb(struct device *x)
{
	uart_irq_update(x);
	int data_length = 0;

	if (uart_irq_rx_ready(x)) {
		data_length = uart_fifo_read(x, uart_buf, sizeof(uart_buf));
		uart_buf[data_length] = 0;
	}
	printk("%s", uart_buf);
}

void uart_init(void)
{
	uart = device_get_binding("UART_0");
	uart_irq_callback_set(uart, uart_cb);
	uart_irq_rx_enable(uart);
}

void uart_example(void)
{
    uint8_t tx[]="1234567890";
	printk("UART loopback start!\n");
    uart_tx( uart, tx, 10, 0);
}

void main(void)
{
    uart_init();
    uart_example();
    while (1) {
    }
}

Parents
  • I was able to make uart_tx work, check out it out here:

    I think the issue is that you have probably set CONFIG_UART_INTERRUPT_DRIVEN=y, and uart_tx will not work when that is the case.


    As mentioned in this reply, uart_tx is supported if you use CONFIG_UART_ASYNC_API.

    I have made an async uart loopback sample here (inspired by ..\zephyr\tests\drivers\uart\uart_async_api): 

    https://github.com/simon-iversen/ncs_samples/tree/master/uart_async

    If you use nrf9160dk_nrf9160, uart1 will be used. Connect together tx and rx of uart1 to make it work.

    Best regards,

    Simon

  • Hi Simon:

    Use nrf9160dk_nrf9160_ns

    After I modify prj.conf.It outputs garbled.


    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/gpio.h>
    #include <logging/log.h>
    #include <logging/log_ctrl.h>
    #include "user_uart.h"
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   1000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    
    #if DT_NODE_HAS_STATUS(LED0_NODE, okay)
    #define LED0	DT_GPIO_LABEL(LED0_NODE, gpios)
    #define PIN	DT_GPIO_PIN(LED0_NODE, gpios)
    #define FLAGS	DT_GPIO_FLAGS(LED0_NODE, gpios)
    #else
    /* A build error here means your board isn't set up to blink an LED. */
    #error "Unsupported board: led0 devicetree alias is not defined"
    #define LED0	""
    #define PIN	0
    #define FLAGS	0
    #endif
    
    void main(void)
    {
    
    	const struct device *dev;
    	bool led_is_on = true;
    	int ret;
    
    	dev = device_get_binding(LED0);
    	if (dev == NULL) {
    		return;
    	}
    
    	ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0) {
    		return;
    	}
    
    	uart_init();
    
    	uart_example();
    	
    	while (1) {
    		gpio_pin_set(dev, PIN, (int)led_is_on);
    		led_is_on = !led_is_on;
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    

    I found that uf the following is deleted,UART can output normally.

    		gpio_pin_set(dev, PIN, (int)led_is_on);
    		led_is_on = !led_is_on;
    		k_msleep(SLEEP_TIME_MS);

    What causes this?

  • If you look at the explanatory text above uart_tx() you can see that the function returns immediately. I think the issue then is that gpio_pin_set and k_msleep is called from the same thread (main), and I think it it will interrupt and corrupt the output. (I will take a closer look at this and get back to you)

    If you set up a callback, you can get notified when uart_tx is completed. Check out how it's done in ppp.c for example, where a semaphore is used to make it wait until it's finished:

    You could also try to put the uart_tx call into an own thread. Check out the DevAcademy to learn how to make your own threads: https://academy.nordicsemi.com/lessons/lesson-7-multithreaded-applications/

    Best regards,

    Simon

  • hi Simon:

    I tried to use thread, but it was still garbled.

    #define STACKSIZE 1024
    
    #define THREAD0_PRIORITY 7
    #define THREAD1_PRIORITY 7
    
    void thread0(void)
    {
    	const struct device *dev;
    	bool led_is_on = true;
    	int ret;
    
    	dev = device_get_binding(LED0);
    	if (dev == NULL) {
    		return;
    	}
    
    	ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0) {
    		return;
    	}
    
    	while (1) {
    		gpio_pin_set(dev, PIN, (int)led_is_on);
    		led_is_on = !led_is_on;
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    
    void thread1(void)
    {
    	uart_init();
    	uart_example();
    	while (1) {
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    
    /* STEP 4 - Define and initialize the two threads */
    K_THREAD_DEFINE(thread0_id, STACKSIZE, thread0, NULL, NULL, NULL,
    		THREAD0_PRIORITY, 0, 0);
    K_THREAD_DEFINE(thread1_id, STACKSIZE, thread1, NULL, NULL, NULL,
    		THREAD1_PRIORITY, 0, 0);

    I tried again semaphore, but it was still garbled.

    static K_SEM_DEFINE(uarte_tx_finished, 0, 1);
    
    static uint8_t uart_rx_buf[1024];
    
    static void uart_callback(const struct device *dev,
    			  struct uart_event *evt,
    			  void *user_data)
    {
    	uint8_t *p;
    	int len;
    	switch (evt->type) 
    	{
    	case UART_TX_DONE:
    		k_sem_give(&uarte_tx_finished);
    		break;
    	case UART_TX_ABORTED:
    		k_sem_give(&uarte_tx_finished);
    		break;	
    	case UART_RX_RDY:
    		len = evt->data.rx.len;
    		p = evt->data.rx.buf + evt->data.rx.offset;
    		break;	
    	case UART_RX_BUF_REQUEST:
    		break;			
    	case UART_RX_BUF_RELEASED:
    		break;
    	case UART_RX_DISABLED:
    		break;	
    	case UART_RX_STOPPED:
    		break;
    	}
    }
    
    static int user_uart_rx_enable(void)
    {
    	int err;
    	err = uart_callback_set(uart, uart_callback, (void *)NULL);
    	if (err) {
    	}
    
    	err = uart_rx_enable(uart, uart_rx_buf, sizeof(uart_rx_buf),
    			     5 * USEC_PER_MSEC);
    	if (err) {
    	} else {
    	}
    	return err;
    }
    
    void uart_init(void)
    {
    	uart = device_get_binding("UART_0");
    	k_sem_give(&uarte_tx_finished);
    	user_uart_rx_enable();
    }
    
    void uart_example(void)
    {
    	int ret;
        uint8_t tx[]="1234567890";
    	printk("UART loopback start!\n");
    	k_sem_take(&uarte_tx_finished, K_FOREVER);
        ret = uart_tx( uart, tx, 10, 0);
    	if (ret) {
    		k_sem_give(&uarte_tx_finished);
    	}	
    }

Reply
  • hi Simon:

    I tried to use thread, but it was still garbled.

    #define STACKSIZE 1024
    
    #define THREAD0_PRIORITY 7
    #define THREAD1_PRIORITY 7
    
    void thread0(void)
    {
    	const struct device *dev;
    	bool led_is_on = true;
    	int ret;
    
    	dev = device_get_binding(LED0);
    	if (dev == NULL) {
    		return;
    	}
    
    	ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0) {
    		return;
    	}
    
    	while (1) {
    		gpio_pin_set(dev, PIN, (int)led_is_on);
    		led_is_on = !led_is_on;
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    
    void thread1(void)
    {
    	uart_init();
    	uart_example();
    	while (1) {
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    
    /* STEP 4 - Define and initialize the two threads */
    K_THREAD_DEFINE(thread0_id, STACKSIZE, thread0, NULL, NULL, NULL,
    		THREAD0_PRIORITY, 0, 0);
    K_THREAD_DEFINE(thread1_id, STACKSIZE, thread1, NULL, NULL, NULL,
    		THREAD1_PRIORITY, 0, 0);

    I tried again semaphore, but it was still garbled.

    static K_SEM_DEFINE(uarte_tx_finished, 0, 1);
    
    static uint8_t uart_rx_buf[1024];
    
    static void uart_callback(const struct device *dev,
    			  struct uart_event *evt,
    			  void *user_data)
    {
    	uint8_t *p;
    	int len;
    	switch (evt->type) 
    	{
    	case UART_TX_DONE:
    		k_sem_give(&uarte_tx_finished);
    		break;
    	case UART_TX_ABORTED:
    		k_sem_give(&uarte_tx_finished);
    		break;	
    	case UART_RX_RDY:
    		len = evt->data.rx.len;
    		p = evt->data.rx.buf + evt->data.rx.offset;
    		break;	
    	case UART_RX_BUF_REQUEST:
    		break;			
    	case UART_RX_BUF_RELEASED:
    		break;
    	case UART_RX_DISABLED:
    		break;	
    	case UART_RX_STOPPED:
    		break;
    	}
    }
    
    static int user_uart_rx_enable(void)
    {
    	int err;
    	err = uart_callback_set(uart, uart_callback, (void *)NULL);
    	if (err) {
    	}
    
    	err = uart_rx_enable(uart, uart_rx_buf, sizeof(uart_rx_buf),
    			     5 * USEC_PER_MSEC);
    	if (err) {
    	} else {
    	}
    	return err;
    }
    
    void uart_init(void)
    {
    	uart = device_get_binding("UART_0");
    	k_sem_give(&uarte_tx_finished);
    	user_uart_rx_enable();
    }
    
    void uart_example(void)
    {
    	int ret;
        uint8_t tx[]="1234567890";
    	printk("UART loopback start!\n");
    	k_sem_take(&uarte_tx_finished, K_FOREVER);
        ret = uart_tx( uart, tx, 10, 0);
    	if (ret) {
    		k_sem_give(&uarte_tx_finished);
    	}	
    }

Children
Related