can't seem to see Rx for either UART0 or UART2

Hello,

I'm trying to see serial data (polling async method) coming from a single-wire signal.  I have verified via an oscilloscope that there is indeed data on that wire.  However I when I plug the wire into the GPIO Rx (for both UART0 and UART2), I see nothing triggering the callback that RX is ready.  There is no flow control

Here are the specifics:

From Uart.C:

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:
            //printk("Tx sent %d bytes\n", evt->data.tx.len);
            break;

        case UART_TX_ABORTED:
            printk("Error: Tx aborted\n\r");
            break;

        case UART_RX_RDY: {
            struct uart_event_rx *pRX = &evt->data.rx;
            size_t length = 0;
            size_t offset = 0;

            struct event_item event = { 0 };
            event.data = NULL;
            event.uart = uart;
            offset =  pRX->offset;
            length = pRX->len;
            printk("Received %d bytes (%s)\n\r", pRX->len, (const char *)&pRX->buf[offset]);
#if 0
            event.data = k_calloc(length, 1);
            memcpy(event.data, (char *)&pRX->buf[offset],  length - 1);
            //printk("Received data %d bytes  (%s)\n", length - 1, (char *)event.data);
            err = k_msgq_put(&event_msgq, &event, K_NO_WAIT);
            if (err) {
                /* Failed to put event into queue */
                k_free(event.data);
            }
#endif
            break;
        }
        case UART_RX_BUF_REQUEST:
        {
            uint8_t *buf;
            //printk("allocating memory\n");
            err = k_mem_slab_alloc(&uart_slab, (void **)&buf, K_NO_WAIT);
            __ASSERT(err == 0, "Failed to allocate slab");

            //printk("setting up buffer response.\n");
            err = uart_rx_buf_rsp(uart, buf, BUF_SIZE);
            __ASSERT(err == 0, "Failed to provide new buffer");
            break;
        }

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

        case UART_RX_DISABLED:
            printk("Rx Disabled.\n");
            break;

        case UART_RX_STOPPED:
            printk("Rx Stopped.\n");
            break;
    }
}

From prj.conf:

CONFIG_THREAD_MONITOR=y
CONFIG_NRF_MODEM_LIB=y                # implies CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NRF_MODEM_LIB_SYS_INIT=n       # The application will take care of initializing Modem in main.c

CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y                  # Will provide BSD name support. e.g. setsockopt() instead of nrf_setsockopt()
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_NATIVE=n                   # We are using socket offload, so set this to no

CONFIG_BUILD_WITH_TFM=y

# Memory size for k_malloc()
CONFIG_HEAP_MEM_POOL_SIZE=4096
# 4096 is the default
CONFIG_MAIN_STACK_SIZE=8192           

CONFIG_MODEM_KEY_MGMT=y               # Application wants to make calls to store keys
CONFIG_LTE_LINK_CONTROL=y             # Enable the API's to setup and configure the LTE link
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n    # The application will take care of initializing the LTE stuff in main.c

CONFIG_NEWLIB_LIBC=y                  # Use the "new" libc
CONFIG_SAMPLE_TFM_MBEDTLS=y

CONFIG_CJSON_LIB=y
CONFIG_HTTP_CLIENT=y

# MbedTLS and security
CONFIG_NORDIC_SECURITY_BACKEND=y            # Required when commenting out BUILD_WITH_TFM
CONFIG_MBEDTLS_VANILLA_BACKEND=y
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
CONFIG_NET_SOCKETS_OFFLOAD_TLS=n
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=8192
CONFIG_MBEDTLS_HEAP_SIZE=44000
CONFIG_MBEDTLS_TLS_LIBRARY=y
CONFIG_MBEDTLS_PKCS1_V15=y
CONFIG_MBEDTLS_RSA_C=y
CONFIG_MBEDTLS=y                              # Required when commenting out CONFIG_NORDIC_SECURITY_BACKEND

CONFIG_LOG=n
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_UART_CONSOLE=n

# Event management which handles network-related events (like ip address change, or net iface up/down for examples)
# CONFIG_NET_MGMT=y
# CONFIG_NET_MGMT_EVENT=y
# CONFIG_NET_SOCKETS_NET_MGMT=y

From the conf and overlay files:

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

&uart2 {
compatible = "nordic,nrf-uarte";
	reg = < 0xa000 0x1000 >;
	interrupts = < 0xa 0x1 >;
	status = "okay";
	label = "UART_2";
	current-speed = < 0x1C200 >;
	tx-pin = < 0x00 >;
	rx-pin = < 0x01 >;
	/delete-property/ rts-pin;
	/delete-property/ cts-pin;
	/delete-property/ hw-flow-control;
};

&uart1 {
	status = "disabled";
};

// &gpiote {
//	interrupts = <13 NRF_DEFAULT_IRQ_PRIORITY>;
// };

CONFIG_TFM_SECURE_UART1=n
CONFIG_UART_ASYNC_API=y
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_NRFX_TIMER2=y
CONFIG_RESET_ON_FATAL_ERROR=n
CONFIG_TRUSTED_EXECUTION_NONSECURE=y

And for UART2 What is the GPIO config?  In one part it reads Rx is PIN 0.  In another part it reads Tx is PIN 1.

Please help.

Thanks

/Loren

Parents Reply Children
  • Hi Oivind,

    Still no success.

    My interpretations for things are as follows:

    nrf9160 has 2 uarts: UART1 and UART2.  It seems that UART1 by default is mapped to VCOM0, and UART2 by default is mapped to VCOM2.  Is this correct?

    What I did was built for the nrf9160_nrf52840 and in the overlay:

    /*
    &vcom2_pins_routing {
            status = "disabled";
    };
    */
    
    &vcom0_pins_routing {
            status = "disabled";
    };

    So to (hopefully) disable the VCOM0 and give control back to UART1.  Is this correct?

    Then on the 9160 side, I have the following in the 9160_9160_ns overlay:

    /* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */
    
    &uart0 {
    compatible = "nordic,nrf-uarte";
        status = "okay";
        label = "UART_0";
    	current-speed = < 115200 >;
    	tx-pin = < 10 >;
    	rx-pin = < 11 >;
    };
    
    /*
    &uart2 {
    compatible = "nordic,nrf-uarte";
        status = "okay";
        label = "UART_2";
    	current-speed = < 115200 >;
    	tx-pin = < 24 >;
    	rx-pin = < 23 >;
    };
    */
    
    &uart1 {
    compatible = "nordic,nrf-uarte";
        status = "okay";
        label = "UART_1";
    	current-speed = < 115200 >;
    	tx-pin = < 29 >;
    	rx-pin = < 28 >;
    };
    

    Is this overlay correct?

    Inside the nrf9160_9160_ns.conf I have:

    CONFIG_TFM_SECURE_UART1=n
    CONFIG_UART_ASYNC_API=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
    CONFIG_NRFX_TIMER2=y
    CONFIG_RESET_ON_FATAL_ERROR=n
    CONFIG_TRUSTED_EXECUTION_NONSECURE=y

    Is this conf correct?

    Lastly, my uart.c:

    #include <string.h>
    #include <zephyr.h>
    #include <drivers/uart.h>
    
    #define BUF_SIZE 4096
    static K_MEM_SLAB_DEFINE(uart_slab, BUF_SIZE, 3, 4);
    
    struct event_item {
        uint8_t id;
        void* data;
        void* uart;
    };
    
    K_MSGQ_DEFINE(event_msgq, sizeof(struct event_item), 10, 4);
    
    #define WORKQ_THREAD_STACK_SIZE 2048
    #define WORKQ_THREAD_PRIORITY   5
    
    static void data_handler_thread_fn(void)
    {
    	struct event_item event;
        int err = 0;
    
    	while (true) {
    		k_msgq_get(&event_msgq, &event, K_FOREVER);
    
    		switch (event.id) {
            case 0: {
                //printk("Thread data %d bytes  (%s)\n", strlen((char *)event.data), (char *)event.data);
                struct device *uart = event.uart;
                err = uart_tx(uart, (char *)event.data, strlen((char *)event.data), 10);
                __ASSERT(err == 0, "Failed to initiate transmission");
                break;
            }
    		default:
    			break;
    		}
    
    		k_free(event.data);
    	}
    }
    
    K_THREAD_DEFINE(data_handler, WORKQ_THREAD_STACK_SIZE,
        data_handler_thread_fn, NULL, NULL, NULL,
        K_PRIO_PREEMPT(WORKQ_THREAD_PRIORITY), 0, 0);
    
    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:
                //printk("Tx sent %d bytes\n", evt->data.tx.len);
                break;
    
            case UART_TX_ABORTED:
                printk("Error: Tx aborted\n\r");
                break;
    
            case UART_RX_RDY: {
                struct uart_event_rx *pRX = &evt->data.rx;
                size_t length = 0;
                size_t offset = 0;
                struct event_item event = { 0 };
                event.data = NULL;
                event.uart = uart;
                offset =  pRX->offset;
                length = pRX->len;
                char *buffer = k_calloc(length, 1);
                strncpy(buffer, (const char *)&pRX->buf[offset], length - 1);
                printk("Received %d bytes (%s)\n\r", pRX->len, buffer);
                k_free(buffer);
    #if 0
                event.data = k_calloc(length, 1);
                memcpy(event.data, (char *)&pRX->buf[offset],  length - 1);
                //printk("Received data %d bytes  (%s)\n", length - 1, (char *)event.data);
                err = k_msgq_put(&event_msgq, &event, K_NO_WAIT);
                if (err) {
                    /* Failed to put event into queue */
                    k_free(event.data);
                }
    #endif
                break;
            }
            case UART_RX_BUF_REQUEST:
            {
                uint8_t *buf;
                //printk("allocating memory\n");
                err = k_mem_slab_alloc(&uart_slab, (void **)&buf, K_NO_WAIT);
                __ASSERT(err == 0, "Failed to allocate slab");
    
                //printk("setting up buffer response.\n");
                err = uart_rx_buf_rsp(uart, buf, BUF_SIZE);
                __ASSERT(err == 0, "Failed to provide new buffer");
                break;
            }
    
            case UART_RX_BUF_RELEASED:
                //printk("Releasing memory");
                k_mem_slab_free(&uart_slab, (void **)&evt->data.rx_buf.buf);
                break;
    
            case UART_RX_DISABLED:
                printk("Rx Disabled.\n");
                break;
    
            case UART_RX_STOPPED:
                printk("Rx Stopped.\n");
                break;
        }
    }
    
    void async(const struct device *lpuart)
    {
        int err = 0;
        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, 10);
        __ASSERT(err == 0, "Failed to enable RX");
    
        struct uart_config cfg = {0};
        err = uart_config_get(lpuart, &cfg);
        __ASSERT(err == 0, "Failed to get config");
    
        printk("Completed async() setup.\n");
    //    unsigned char ch;
    //    while(1) {
    //        //int result = uart_poll_in(lpuart, &ch);
    //    }
    }
    
    void run_loopback(void)
    {
        const struct device *lpuart;
    
        k_msleep(1000);
    
        lpuart = device_get_binding("UART_1");
        __ASSERT(lpuart, "Failed to get the device");
    
        async(lpuart);
    }

    Is everything in this C file correct?

    The problem, Oivind is that my callback is NOT seeing any data received.  Please help!

    /Loren

  • Loren Rogers said:
    nrf9160 has 2 uarts: UART1 and UART2.  It seems that UART1 by default is mapped to VCOM0, and UART2 by default is mapped to VCOM2.  Is this correct?

    No, not exactly. The same numbers are not used together in software and hardware description. The uart0 instance (in the code) is by default connected to VCOM0 through the NRF91_UART1/NRF91_APP1 interface. And the uart1 instance (in the code) is by default connected to VCOM2 through the NRF91_UART2/NRF91_APP2 interface.

    Loren Rogers said:
    What I did was built for the nrf9160_nrf52840 and in the overlay:

    Disabling vcom0_pins_routing will stop the default uart0 pins (P0.26, P0.27, P0.28, P0.29) from being routed to vcom0. If you use other pins for uart0, then this is not necessary. The same goes for vcom2 and uart1. If you want to disable the default routing for those pins, make sure that they are added to a working nrf9160dk_nrf52840 sample, which is then flashed to the nrf52840. You may also have to cut the appropriate solder bridges. In that case, make sure that your board revision matches the documentation.

    Loren Rogers said:
    Then on the 9160 side, I have the following in the 9160_9160_ns overlay:

    You should probably take another look at this after reading what I've written above.

    The config and code seem fine at first glance.

Related