Communication between nrf52840 and nrf9160 on nrf9160DK over lpuart

Hello,

I'm attempting to establish communication between an nRF52840 and an nRF9160 on the nRF9160DK using LPUART. Initially, I tried using the interrupt-driven mode, but the uart_fifo_fill function only sends the packet once and then sends 0 bytes on both sides.

Next, I switched to the async mode API for LPUART by disabling the interrupt-driven mode. However, when I attempt to use uart_tx, it returns EBUSY.

Best Regards

Youssef

Parents Reply Children
  • i have tried to use samples lpuart and connectivity bridge but the same problem.

    My .overlay of nrf52 and nrf91 are based on hci_lpuart sample and lte_ble_getway sample :

    nrf9160dk_nrf52840.overlay :

    /* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */

    #include <nrf9160dk_nrf52840_reset_on_if5.dtsi>
    #include <nrf9160dk_uart1_on_if0_3.dtsi>

    &pinctrl {
        uart0_default_alt: uart0_default_alt {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 5)>;
            };
        };

        uart0_sleep_alt: uart0_sleep_alt {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 5)>;
                low-power-enable;
            };
        };

        uart1_default_alt: uart1_default_alt {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 17)>,
                    <NRF_PSEL(UART_RX, 0, 20)>;
            };
        };

        uart1_sleep_alt: uart1_sleep_alt {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 17)>,
                    <NRF_PSEL(UART_RX, 0, 20)>;
                low-power-enable;
            };
        };

    };

    &uart1 {
        current-speed = <1000000>;
        pinctrl-0 = <&uart1_default_alt>;
        pinctrl-1 = <&uart1_sleep_alt>;
        pinctrl-names = "default", "sleep";

        lpuart: nrf-sw-lpuart {
            compatible = "nordic,nrf-sw-lpuart";
            status = "okay";
            req-pin = <15>; /* <&interface_to_nrf9160 2 0>; */
            rdy-pin = <22>; /* <&interface_to_nrf9160 3 0>; */
        };
    };

    / {
        chosen {
            zephyr,bt-c2h-uart=&lpuart;
        };
    };

    &gpiote {
        interrupts = <6 NRF_DEFAULT_IRQ_PRIORITY>;
    };

    /* Disabling uart rx pin to get low power */
    &uart0 {
        pinctrl-0 = <&uart0_default_alt>;
        pinctrl-1 = <&uart0_sleep_alt>;
        pinctrl-names = "default", "sleep";
        disable-rx;
    };

    nrf9160dk_nrf9160_ns.overlay :

    #include <nrf9160dk_nrf52840_reset_on_if5.dtsi>

    / {
        chosen {
            zephyr,bt-uart=&lpuart;
        };
    };

    &gpiote {
        interrupts = <49 NRF_DEFAULT_IRQ_PRIORITY>;
    };

    &uart2 {
        current-speed = <1000000>;
        status = "okay";
        /delete-property/ hw-flow-control;

        pinctrl-0 = <&uart2_default_alt>;
        pinctrl-1 = <&uart2_sleep_alt>;
        pinctrl-names = "default", "sleep";
        lpuart: nrf-sw-lpuart {
            compatible = "nordic,nrf-sw-lpuart";
            status = "okay";
            req-pin = <21>; /* <&interface_to_nrf52840 3 0>; */
            rdy-pin = <19>; /* <&interface_to_nrf52840 2 0>; */
        };
    };

    &pinctrl {
        uart2_default_alt: uart2_default_alt {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 18)>,
                    <NRF_PSEL(UART_RX, 0, 17)>;
            };
        };

        uart2_sleep_alt: uart2_sleep_alt {
            group1 {
                psels = <NRF_PSEL(UART_TX, 0, 18)>,
                    <NRF_PSEL(UART_RX, 0, 17)>;
                low-power-enable;
            };
        };

    };

    nrf9160dk_nrf9160_ns.conf :

    CONFIG_NRF_SW_LPUART=y
    CONFIG_NRF_SW_LPUART_INT_DRIVEN=n # to use async mode but when i use interrupt it is
    activated

    CONFIG_UART_2_ASYNC=y
    CONFIG_UART_2_INTERRUPT_DRIVEN=n
    CONFIG_UART_2_NRF_HW_ASYNC=y
    CONFIG_UART_2_NRF_HW_ASYNC_TIMER=2
    CONFIG_UART_2_NRF_TX_BUFFER_SIZE=256

    nrf9160dk_nrf52840.conf :

    # Override prj.conf defaults

    CONFIG_GPIO=y
    CONFIG_MAIN_STACK_SIZE=1024
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512
    CONFIG_BT_MAX_CONN=16
    CONFIG_BT_TINYCRYPT_ECC=n
    CONFIG_BT_CTLR_DTM_HCI=y
    CONFIG_BT_CTLR_ASSERT_HANDLER=n

    CONFIG_UART_1_ASYNC=y
    CONFIG_UART_1_INTERRUPT_DRIVEN=n
    CONFIG_UART_1_NRF_HW_ASYNC=y
    CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2
    CONFIG_NRF_SW_LPUART=y
    CONFIG_NRF_SW_LPUART_INT_DRIVEN=n

     main.c of nrf9160dk_nrf52840 :

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/uart.h>


    uint8_t tx_buffer[12] = "Hello World!";
    uint8_t rx_buffer[12];

    static void uart_callback(const struct device *dev,void *user_data)
    {
        // Gérer les événements UART ici
        if(uart_irq_update(dev) && uart_irq_is_pending(dev))
        {
            if(uart_irq_rx_ready(dev))
            {
                uint8_t buffer[1];
                uart_fifo_read(dev, buffer, 1);
                printk("Caractère reçu: %c\n", buffer[0]);
            }
            if(uart_irq_tx_ready(dev))
            {
                // Gérer les événements de transmission ici
                int ret = uart_fifo_fill(dev, "Hello World!", 12);
                if(ret <= 0)
                {
                    printk("Erreur de transmission : err : %d \n",ret);
                }else{
                    printk("%d octets transmis \n",ret);
                }

                while (uart_irq_tx_complete(dev) == 0);
                printk("Transmission terminée\n");
                uart_irq_tx_disable(dev);
            }
        }
    }

    void uart_cb(const struct device *uart_dev,
                                 struct uart_event *evt, void *user_data)
    {

        switch (evt->type) {
            case UART_TX_DONE:
                printk("Transmission terminée\n");
                break;
           
            case UART_TX_ABORTED:
                printk("Transmission annulée\n");
            case UART_RX_RDY:
                printk("Caractère reçu: %c\n", evt->data.rx.buf[0]);
                break;
           
            case UART_RX_BUF_REQUEST:
                break;

            case UART_RX_BUF_RELEASED:
                break;

            case UART_RX_DISABLED:
                break;
           
            default:
                break;
        }
    }
    int main(void)
    {
        const struct device *uart_dev = DEVICE_DT_GET(DT_NODELABEL(lpuart));

        if (!uart_dev) {
            printk("Impossible de trouver le périphérique UART\n");
            return;
        }
        if(device_is_ready(uart_dev) == false)
        {
            printk("Périphérique UART non prêt\n");
            return -1;
        }
        // to use interrupt mode
        /*uart_irq_callback_set(uart_dev, &uart_callback);
        uart_irq_rx_enable(uart_dev);

        while (1) {
            // Votre code principal ici
            uart_irq_tx_enable(uart_dev);
            k_sleep(K_MSEC(5000));
        }*/
        int ret = uart_callback_set(uart_dev,&uart_cb,NULL);
        if(ret < 0)
        {
            printk("Erreur de configuration de la callback , ret : %d\n",ret);
            return -1;
        }
        ret = uart_rx_enable(uart_dev,rx_buffer,sizeof(rx_buffer),SYS_FOREVER_US);
        if(ret < 0)
        {
            printk("Erreur de configuration de la réception , ret : %d\n",ret);
            return -1;
        }
        while (true)
        {
            ret = uart_tx(uart_dev,tx_buffer,sizeof(tx_buffer),SYS_FOREVER_US);
            if(ret < 0)
            {
                printk("Erreur de transmission , ret : %d\n",ret);
            }
            k_sleep(K_MSEC(5000));
        }
       
        return 0;
    }

    Best regards

    Youssef

  • Update !

    Now it works with uart1 for nrf52 and uart2 for nrf91 in async mode, but there is an issue, the issue is when i receive something the rx is automaticaly disabled, there is any reason or explanation for this.

    main.c :

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/uart.h>
    #include <zephyr/logging/log.h>

    LOG_MODULE_REGISTER(NRF52_LOG,4);

    uint8_t tx_buffer[] = "Hi From nrf52840 SoC";
    uint8_t rx_buffer[100];

    static void uart_callback(const struct device *dev,void *user_data)
    {
        // Gérer les événements UART ici
        if(uart_irq_update(dev) && uart_irq_is_pending(dev))
        {
            if(uart_irq_rx_ready(dev))
            {
                uint8_t buffer[1];
                uart_fifo_read(dev, buffer, 1);
                printk("Caractère reçu: %c\n", buffer[0]);
            }
            if(uart_irq_tx_ready(dev))
            {
                // Gérer les événements de transmission ici
                int ret = uart_fifo_fill(dev, "Hello World!", 12);
                if(ret <= 0)
                {
                    printk("Erreur de transmission : err : %d \n",ret);
                }else{
                    printk("%d octets transmis \n",ret);
                }

                while (uart_irq_tx_complete(dev) == 0);
                printk("Transmission terminée\n");
                uart_irq_tx_disable(dev);
            }
        }
    }

    void uart_cb(const struct device *uart_dev,
                                 struct uart_event *evt, void *user_data)
    {

        switch (evt->type) {
            case UART_TX_DONE:
                LOG_DBG("Transmission terminée\n");
                break;
           
            case UART_TX_ABORTED:
                LOG_ERR("Transmission annulée\n");
            case UART_RX_RDY:
                for(int i = 0 ; i < evt->data.rx.len ; i++){
                    rx_buffer[i] = evt->data.rx.buf[i];
                }
                LOG_DBG("rx_buffer : %s \n",rx_buffer);
                break;
           
            case UART_RX_BUF_REQUEST:
                //printk("rx buffer is requested \n");
                break;

            case UART_RX_BUF_RELEASED:
                break;

            case UART_RX_DISABLED:
                LOG_ERR("rx is disabled \n");
                uart_rx_enable(uart_dev,rx_buffer,sizeof(rx_buffer),SYS_FOREVER_US);
                break;
           
            default:
                break;
        }
    }
    int main(void)
    {
        const struct device *uart_dev = DEVICE_DT_GET(DT_NODELABEL(uart1));

        if (!uart_dev) {
            LOG_ERR("Impossible de trouver le périphérique UART\n");
            return;
        }
        if(device_is_ready(uart_dev) == false)
        {
            LOG_ERR("Périphérique UART non prêt\n");
            return -1;
        }
        // to use interrupt mode
        /*uart_irq_callback_set(uart_dev, &uart_callback);
        uart_irq_rx_enable(uart_dev);

        while (1) {
            // Votre code principal ici
            uart_irq_tx_enable(uart_dev);
            k_sleep(K_MSEC(6000));
        }*/
        int ret = uart_callback_set(uart_dev,&uart_cb,NULL);
        if(ret < 0)
        {
            LOG_ERR("Erreur de configuration de la callback , ret : %d\n",ret);
            return -1;
        }
        ret = uart_rx_enable(uart_dev,rx_buffer,sizeof(rx_buffer),SYS_FOREVER_US);
        if(ret < 0)
        {
            LOG_ERR("Erreur de configuration de la réception , ret : %d\n",ret);
            return -1;
        }
        while (true)
        {
            ret = uart_tx(uart_dev,tx_buffer,sizeof(tx_buffer),SYS_FOREVER_US);
            if(ret < 0)
            {
                LOG_ERR("Erreur de transmission , ret : %d\n",ret);
            }
            k_sleep(K_MSEC(5000));
        }
       
        return 0;
    }

    the output :

    Best regards

    Youssef

  • Hi Youssef,

    It good to see you got something working. Regardign not receving more, I see that you do not handle the UART_RX_BUF_REQUEST event. You should handlethat and provide a new buffer (a sensible approach here could be to have two separate buffers that you alternate between). If you do not, receiving will be stopped once the current buffer is filled.

    Br,

    Einar

  • Hi Einar,

    Thank you for your response. My buffer is a 100-byte array. How can it be filled after receiving a packet of just 20 bytes?

    Based on your response, should I add uart_rx_enable with another buffer?

    Best regards,

    Youssef

  • Hi,

    That is a good point. There are a couple of other reasons you might get this as well. The simplest in that case is to check with a debugger and backtrack why you got the UART_RX_DISABLED event. If you use UARTE, the relevant implementation is in zephyr/drivers/serial/uart_nrfx_uarte.c. And you can set a breakpoint in notify_rx_disable() first to verify that it originates there. Then backtrack and see where notify_rx_disable() is called from, and so on.

Related