This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

UART Interrput in Zephyr nRF9160

Zephyr version: 2.4.99

OS: Linux

Board : nrf9160dk

I am trying to read data on UART 1 with interrupt. I have below shown portion in my code for enabling UART 1. (I am keeping UART0 for debugging, printk/printf)

    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,
    };
    
    f_uart = device_get_binding(DT_LABEL(DT_ALIAS(fuart)));
    if (f_uart == NULL) {
        printf("NB-IoT UART could not be enabled!\n");
        return;
    }

    ret = uart_configure(f_uart, &uart_cfg);
    if (ret != 0) {
        printf("UART can not be configured!\n");
    }
    uart_irq_rx_disable(f_uart);
    uart_irq_tx_disable(f_uart);
    uart_irq_callback_set(f_uart, uart_callback_fn);
    uart_irq_rx_enable(f_uart);

DTS file has below change:

* These aliases are provided for compatibility with samples */
	aliases {
		led0 = &led0;
		led1 = &led1;
		led2 = &led2;
		led3 = &led3;
		pwm-led0 = &pwm_led0;
		sw0 = &button2;
		sw1 = &button3;
		sw2 = &button0;
		sw3 = &button1;
		fuart = &fuart;
	};
	
.
.
.
fuart: &uart1 {
	status = "okay";
	current-speed = <9600>;
	tx-pin = <1>;
	rx-pin = <0>;
	rts-pin = <14>;
	cts-pin = <15>;
};

Prj.conf file is:

CONFIG_UART_1_ASYNC=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_1_NRF_HW_ASYNC=y
CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2

UART Callback function

void uart_callback_fn(const struct device *dev, void *user_data)
{
	ARG_UNUSED(user_data);		

	uart_irq_update(dev);	
	 	if  (uart_irq_rx_ready(dev)) {
			rx_len = uart_fifo_read(dev, &rx_buf[0], 350);
			//printf("%s", rx_buf[0]);
		}
}

I am sending data of approx 350 bytes from nrf52840dk to nrf9160dk. I do not want to use DMA as we have variable length of receiving data, but we can know the end of the data by a special character . The issue I am facing is My uart_callback_fn() is called for every byte received; uart_fifo_read() is  not reading all the data at once. What I have observed is

  1. Even though I give 350 as 3rd param in uart_fifo_read(), it only reads 1 byte. This is due to read function implementation in uart_nrfx_uarte.c file which gets bounded in device_get_binding. The function only reads 1 byte. How can I not bind uart_nrfx_uarte.c ? How can I bind uart_nrfx_uart.c which has implementation of reading multiple bytes. What are the Kconfigs for this? I tried defining " compatible = "nordic,nrf-uart" "  in DTS file but did not work.
  2. I also observed that only partial data was received. I suspect that might be due to buffer size. How can I increase the buffer size. I can neither find API nor Kconfig for this.
  3. There are some Kconfig like CONFIG_UART_NRFX_UARTE1 which are not given in Zephyr documentation. How can I know all other Kconfigs specific to nrf series Soc?

Thanks in advance!

Parents
  • Hi,

     

    Even though I give 350 as 3rd param in uart_fifo_read(), it only reads 1 byte. This is due to read function implementation in uart_nrfx_uarte.c file which gets bounded in device_get_binding. The function only reads 1 byte. How can I not bind uart_nrfx_uarte.c ? How can I bind uart_nrfx_uart.c which has implementation of reading multiple bytes. What are the Kconfigs for this? I tried defining " compatible = "nordic,nrf-uart" "  in DTS file but did not work.

     If you do not set the buffer length in uart_rx_enable() function, it will read only 1 byte.

    The function which it resolves to is this one, where the DMA buffer is set here:

    https://github.com/nrfconnect/sdk-zephyr/blob/master/drivers/serial/uart_nrfx_uarte.c#L630

     

    The compatible = "nordic,nrf-uart" will not work with nRF53 or nRF9160, as it does not have the legacy NRF_UART peripheral, it has the NRF_UARTE (DMA capable) peripheral.

     

    If you do not want to use the zephyr uart driver, you can use the NRFX_UARTE driver directly instead, by setting CONFIG_NRFX_UARTE=y and manually use the UARTE1 peripheral, similar to how the uart example in the nrf5 sdk is setup.

     

    I also observed that only partial data was received. I suspect that might be due to buffer size. How can I increase the buffer size. I can neither find API nor Kconfig for this.

    This could be a side effect of the 1 byte DMA setup. Have you checked if the rx_len accumulates to the expected bytes to receive? In case there's something that overwrites the buffer (ie: one of your threads taking more time compared to the uart interrupt function)

    There are some Kconfig like CONFIG_UART_NRFX_UARTE1 which are not given in Zephyr documentation. How can I know all other Kconfigs specific to nrf series Soc?

    Kconfig is a descriptive language, and if you do not enable certain modules; it will not expose them in the menuconfig either. If you search in the "menuconfig", you can see all available kconfig entries, but do note that there's quite alot of them.

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    Even though I give 350 as 3rd param in uart_fifo_read(), it only reads 1 byte. This is due to read function implementation in uart_nrfx_uarte.c file which gets bounded in device_get_binding. The function only reads 1 byte. How can I not bind uart_nrfx_uarte.c ? How can I bind uart_nrfx_uart.c which has implementation of reading multiple bytes. What are the Kconfigs for this? I tried defining " compatible = "nordic,nrf-uart" "  in DTS file but did not work.

     If you do not set the buffer length in uart_rx_enable() function, it will read only 1 byte.

    The function which it resolves to is this one, where the DMA buffer is set here:

    https://github.com/nrfconnect/sdk-zephyr/blob/master/drivers/serial/uart_nrfx_uarte.c#L630

     

    The compatible = "nordic,nrf-uart" will not work with nRF53 or nRF9160, as it does not have the legacy NRF_UART peripheral, it has the NRF_UARTE (DMA capable) peripheral.

     

    If you do not want to use the zephyr uart driver, you can use the NRFX_UARTE driver directly instead, by setting CONFIG_NRFX_UARTE=y and manually use the UARTE1 peripheral, similar to how the uart example in the nrf5 sdk is setup.

     

    I also observed that only partial data was received. I suspect that might be due to buffer size. How can I increase the buffer size. I can neither find API nor Kconfig for this.

    This could be a side effect of the 1 byte DMA setup. Have you checked if the rx_len accumulates to the expected bytes to receive? In case there's something that overwrites the buffer (ie: one of your threads taking more time compared to the uart interrupt function)

    There are some Kconfig like CONFIG_UART_NRFX_UARTE1 which are not given in Zephyr documentation. How can I know all other Kconfigs specific to nrf series Soc?

    Kconfig is a descriptive language, and if you do not enable certain modules; it will not expose them in the menuconfig either. If you search in the "menuconfig", you can see all available kconfig entries, but do note that there's quite alot of them.

     

    Kind regards,

    Håkon

Children
  • Hi,

    Thank for replying.

    Now it is understandable why UART is not getting bound to legacy UART driver. I still have a question.

    I am using UART in interrupt mode so I don't think I can use uart_rx_enable(). As well there is no argument for setting buffer size in uart_irq_rx_enable(). Is there any Kconfig for UART DMA buffer size? Or is there any workaround?

  • Hi,

     

    Vishwas Jain said:
    I am using UART in interrupt mode so I don't think I can use uart_rx_enable(). As well there is no argument for setting buffer size in uart_irq_rx_enable(). Is there any Kconfig for UART DMA buffer size? Or is there any workaround?

     Yes, you're right. You have both CONFIG_UART_ASYNC_API and CONFIG_UART_INTERRUPT_DRIVEN set, and the interrupt driven mode will get priority and thus blocks the async library of being used.

    You can disable the uart interrupt driven configuration, and use async uart in a dedicated thread, or you can use the nrfx_uarte driver directly to receive > 1 byte per transaction.

     

    Kind regards,

    Håkon

Related