UART tx using thingy91

Hello,

I am using uart with thingy:91 to communicate between nrf52 SoC and nrf91 SiP, i am able to receive data from nrf52 but when i try to send data to nrf52 SoC the function uart_irq_tx_ready always returns 0 "UART TX is not ready", btw I am using uart0 for both nrf52 and nrf91 and for nrf91 I am using interrupt driven mode and for nrf52 I am using async api mode.

Here is my init code for nrf91 SiP and how i try to send data:

void uart_init(void)
{
    int ret;
  if (!uart_dev) {
    LOG_ERR("UART_0 failed");
    return;
  }
  ret = uart_irq_callback_user_data_set(uart_dev, uart_cb, NULL);
  if (ret < 0)
  {
    if (ret == -ENOTSUP)
    {
      LOG_ERR("Interrupt-driven UART API support not enabled\n");
    }
    else if (ret == -ENOSYS)
    {
      LOG_ERR("UART device does not support interrupt-driven API\n");
    }
    else
    {
      LOG_ERR("Error setting UART callback: %d\n", ret);
    }
    return 0;
  }
  uart_irq_rx_enable(uart_dev);
  LOG_INF("UART initialized");
}
void send_data_to_nrf52(int64_t timestamp_unix)
{
    int ret;
    uint8_t data[8];
    int64_to_uint8_array(data, timestamp_unix);
    LOG_DBG("Sending : %x | %x | %x | %x | %x | %x | %x | %x ", data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7]);
    uart_irq_tx_enable(uart_dev);
    if (!uart_irq_update(uart_dev)) {
    LOG_DBG("uart_irq_update failed");
    return;
    }
    if(uart_irq_tx_ready(uart_dev) == 0) // the issue is here always 0
    {
        LOG_ERR("UART TX not ready");
        uart_irq_tx_enable(uart_dev);
    }
    // Enable TX interrupt
   
    ret = uart_fifo_fill(uart_dev, data, sizeof(data));
    if(ret == ENOSYS || ret == ENOTSUP)
    {
        LOG_ERR("UART device does not support interrupt-driven API , error code : %d",ret);
    }
    else
    {
        LOG_INF("Data sent to nrf52 , number of bytes sent : %d",ret);
    }
    uart_irq_tx_disable(uart_dev); // disable the tx interrupt
}
Parents
  • Hi Youssef

    Have you considered using the LPUART driver instead, since you are establishing communication between two Nordic devices? 

    This driver is optimized for lower power consumption, and should be easier to interface than accessing the serial drivers directly. 

    Best regards
    Torbjørn 

  • Hi Torbjørn,

    When I tried using LPUART with the Thingy91_nrf9160ns, I encountered a build error. The error message is as follows:

    C:/ncs/v2.5.0/deps/zephyr/include/zephyr/device.h:85:41: error: '__device_dts_ord_96' undeclared here (not in a function); did you mean '__device_dts_ord_16'?
       85 | #define DEVICE_NAME_GET(dev_id) _CONCAT(__device_, dev_id)
          |                                         ^~~~~~~~~
    C:/ncs/v2.5.0/deps/zephyr/include/zephyr/toolchain/common.h:132:26: note: in definition of macro '_DO_CONCAT'
      132 | #define _DO_CONCAT(x, y) x ## y
          |                          ^
    C:/ncs/v2.5.0/deps/zephyr/include/zephyr/device.h:85:33: note: in expansion of macro '_CONCAT'
       85 | #define DEVICE_NAME_GET(dev_id) _CONCAT(__device_, dev_id)
          |                                 ^~~~~~~
    C:/ncs/v2.5.0/deps/zephyr/include/zephyr/device.h:211:37: note: in expansion of macro 'DEVICE_NAME_GET'
      211 | #define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_ID(node_id))
          |                                     ^~~~~~~~~~~~~~~
    C:/ncs/v2.5.0/deps/zephyr/include/zephyr/device.h:228:34: note: in expansion of macro 'DEVICE_DT_NAME_GET'
      228 | #define DEVICE_DT_GET(node_id) (&DEVICE_DT_NAME_GET(node_id))
          |                                  ^~~~~~~~~~~~~~~~~~
    C:/ncs/v2.5.0/deps/zephyr/drivers/console/uart_console.c:40:9: note: in expansion of macro 'DEVICE_DT_GET'
       40 |         DEVICE_DT_GET(DT_CHOSEN(zephyr_console))

    here is my thingy91_nrf9160ns.overlay file : 

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

    &uart1 {

        status = "okay";

        current-speed = <115200>;

        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";

            label = "LPUART";

            req-pin = <24>;

            rdy-pin = <25>;

        };

    };



    &uart0 {

        status = "disabled";

    };



    &gpio0 {

        status = "okay";

    };



    &gpiote {

        interrupts = <49 NRF_DEFAULT_IRQ_PRIORITY>;

    };



    &pinctrl {

        uart1_default_alt: uart1_default_alt {

            group1 {

                psels = <NRF_PSEL(UART_RX, 0, 23)>,

                    <NRF_PSEL(UART_TX, 0, 22)>,

                    <NRF_PSEL(UART_CTS, 0, 13)>,

                    <NRF_PSEL(UART_RTS, 0, 14)>;

            };

        };



        uart1_sleep_alt: uart1_sleep_alt {

            group1 {
                psels = <NRF_PSEL(UART_RX, 0, 23)>,
                    <NRF_PSEL(UART_TX, 0, 22)>,
                    <NRF_PSEL(UART_CTS, 0, 13)>,
                    <NRF_PSEL(UART_RTS, 0, 14)>;
                low-power-enable;

            };

        };

    };

    main.c file (which is based on lpuart sample):


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

    LOG_MODULE_REGISTER(app);

    #define BUF_SIZE 64
    static K_MEM_SLAB_DEFINE(uart_slab, BUF_SIZE, 3, 4);

    static void uart_irq_handler(const struct device *dev, void *context)
    {
        uint8_t buf[] = {1, 2, 3, 4, 5};

        if (uart_irq_tx_ready(dev)) {
            (void)uart_fifo_fill(dev, buf, sizeof(buf));
            uart_irq_tx_disable(dev);
        }

        if (uart_irq_rx_ready(dev)) {
            uint8_t buf[10];
            int len = uart_fifo_read(dev, buf, sizeof(buf));

            if (len) {
                printk("read %d bytes\n", len);
            }
        }
    }

    static void interrupt_driven(const struct device *dev)
    {
        uint8_t c = 0xff;

        uart_irq_callback_set(dev, uart_irq_handler);
        uart_irq_rx_enable(dev);
        while (1) {
            uart_irq_tx_enable(dev);
            k_sleep(K_MSEC(500));

            uart_poll_out(dev, c);
            k_sleep(K_MSEC(100));
        }
    }

    static void uart_callback(const struct device *dev,
                  struct uart_event *evt,
                  void *user_data)
    {
        struct device *uart = user_data;
        int err;

        switch (evt->type) {
        case UART_TX_DONE:
            LOG_INF("Tx sent %d bytes", evt->data.tx.len);
            break;

        case UART_TX_ABORTED:
            LOG_ERR("Tx aborted");
            break;

        case UART_RX_RDY:
            LOG_INF("Received data %d bytes", evt->data.rx.len);
            break;

        case UART_RX_BUF_REQUEST:
        {
            uint8_t *buf;

            err = k_mem_slab_alloc(&uart_slab, (void **)&buf, K_NO_WAIT);
            __ASSERT(err == 0, "Failed to allocate slab");

            err = uart_rx_buf_rsp(uart, buf, BUF_SIZE);
            __ASSERT(err == 0, "Failed to provide new buffer");
            break;
        }

        case UART_RX_BUF_RELEASED:
            k_mem_slab_free(&uart_slab, (void *)evt->data.rx_buf.buf);
            break;

        case UART_RX_DISABLED:
            break;

        case UART_RX_STOPPED:
            break;
        }
    }

    static void async(const struct device *lpuart)
    {
        uint8_t txbuf[5] = {1, 2, 3, 4, 5};
        int err;
        uint8_t *buf;

        err = k_mem_slab_alloc(&uart_slab, (void **)&buf, K_NO_WAIT);
        __ASSERT(err == 0, "Failed to alloc slab");

        err = uart_callback_set(lpuart, uart_callback, (void *)lpuart);
        __ASSERT(err == 0, "Failed to set callback");

        err = uart_rx_enable(lpuart, buf, BUF_SIZE, 10000);
        __ASSERT(err == 0, "Failed to enable RX");

        while (1) {
            err = uart_tx(lpuart, txbuf, sizeof(txbuf), 10000);
            __ASSERT(err == 0, "Failed to initiate transmission");

            k_sleep(K_MSEC(500));

            uart_poll_out(lpuart, txbuf[0]);
            k_sleep(K_MSEC(100));
        }
    }

    int main(void)
    {
        const struct device *lpuart = DEVICE_DT_GET(DT_NODELABEL(lpuart));

        __ASSERT(device_is_ready(lpuart), "LPUART device not ready");

        if (IS_ENABLED(CONFIG_NRF_SW_LPUART_INT_DRIVEN)) {
            interrupt_driven(lpuart);
        } else {
            async(lpuart);
        }

        return 0;
    }

    and my thingy91_nrf9160ns.conf file :

    CONFIG_NRF_SW_LPUART=y
    CONFIG_NRF_SW_LPUART_INT_DRIVEN=y

    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

     

    Best Regards

    Youssef

  • Hi Torbjørn,

    I have already set CONFIG_UART_INTERRUPT_DRIVEN  and CONFIG_NRF_SW_LPUART_INT_DRIVEN but the same issue,

    the first image shows that the lpuart sends 8 bytes as expected for the first try, but then it sends only 0 as shown in the second image

    Send 8 bytes for the first time

    Send 0 bytes

    I have tried to use uart1 and uart 0 with async but it doesn't work, does lpuart supports async mode ?

    Best regards

    Youssef

  • Hi Torbjørn,

    Following your suggestion, I tried using UART1 in async mode for communication between the nRF52 and nRF91. However, I encountered some issues:

    1. On the nRF52 side, whenever I send data, the callback jumps to the UART_TX_ABORT case instead of UART_TX_DONE.
    2. On the nRF91 side, when I send data over UART1, the callback correctly calls UART_TX_DONE, but nothing is received on the nRF52.

    Best regards

    Youssef

  • Hi Youssef

    Could you test this with MCUboot disabled? 

    CONFIG_BOOTLOADER_MCUBOOT=n

    Having MCUboot enabled can some times cause issues for UART applications, and it would be good to know if this is the case here. 

    Best regards
    Torbjørn

  • Hello Torbjørn,

    I wanted to let you know that I have switched to async mode with UART1. Based on the sample provided in this GitHub repository, I managed to fix the issue.

    Best regards,

    Youssef

  • Hi Youssef

    Great to hear you were able to get it working!

    I will close the case then, unless you have more questions. 

    Best regards
    Torbjørn

Reply Children
No Data
Related