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
  • Hi Youssef,

    Can you share more about your implementation, what you are doing?

    Generally, async UART is the best option in most cases. You should enable HW counting though, which uses a TIMER and PPI (NRF_HW_ASYNC). There are also some examples using LPUART, like Low Power UART and the Connectivity bridge.

    Einar

  • 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

Reply
  • 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

Children
Related