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 Reply Children
  • Hi Torbjørn,

    Currently, I'm using UART0 for both devices. Should I switch to using LPUART for both devices? If so, what mode should I use for lpuart driver?

    Best regards

    Youssef

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

    It seems the issue is that you still have the UART console library enabled, even though you have disabled uart0 and removed the uart console chosen definition. 

    Could you try to disable the UART console by adding the following to your project configuration? 

    CONFIG_UART_CONSOLE=n

    Best regards
    Torbjørn

  • Hi Torbjørn,

    I have disabled the UART console, but I am still encountering the same issue.

    Here is my prj.conf file:

    CONFIG_GPIO=y
    CONFIG_SERIAL=y
    #CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_LOG=y
    CONFIG_COREDUMP_DEVICE=y
    CONFIG_DEBUG_COREDUMP=y
    CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y
    CONFIG_FPU=y
    CONFIG_UART_CONSOLE=n

    i tried also to disable CONFIG_SERIAL but the same problem.

    Best regards

    Youssef

  • Now, when i have activated uart0, so status = "okay" there's no error, but when i tried to send data over lpuart, the function uart_irq_handler returns 5 for the first time then it returns 0 bytes.

    here's my callback :

    static void uart_irq_handler(const struct device *dev, void *context)
    {
        uint8_t buf[] = {1, 2, 3, 4, 5};
        printk("uart_irq_handler\n");
        if (uart_irq_tx_ready(dev)) {
            int ret = uart_fifo_fill(dev, buf, sizeof(buf));
            printk("fill %d bytes\n", ret);
            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);
            }else{
                printk("no data %d bytes\n",len);
            }
        }
    }

    it returns : fill 5 bytes , then fill 0 bytes

    Best regards,

    Youssef

Related