How to Separate Logging and Serial Communication on Different VCOMs (nRF5340)

I am using the board nRF5340 Soc, which by default exports two VCOM ports via the J-Link OB debugger. Currently:

  • VCOM1 (UART0) is used for both logging and serial communication by default.
  • VCOM2 mainly logs boot information.

Goal:

I want to separate logging and serial communication as follows:

  1. VCOM1 (UART0) → Only for logs (debug messages).
  2. VCOM2 (UART1) → Only for serial read/write communication.

Questions:

  1. Is there an internal J-Link OB forwarding mechanism that could be causing this issue?
  2. Are there any Zephyr configurations or Nordic-specific settings required to properly separate logs and serial communication?
  3. What is the best way to ensure logs stay on VCOM1 and serial communication happens only on VCOM2?

Any guidance or recommendations would be greatly appreciated. Thanks!

Parents
  • Hello,

    The two COM ports on the DK are the two UARTs that the nRF5340 uses for logging by default. One for the application core, and one for the network core. So the one you are saying just logs boot information, that is probably the network core logging. 

    Is there an internal J-Link OB forwarding mechanism that could be causing this issue?

    The debugger is hard wired to specific GPIOs that are used by the app core and network core by default. They are listed on the back of the DK. They are named RTS TXD CTS and RXD.

    What you can do is to disable logging on the network core, stop the pin forwarding to the network core, and control these as a separate UART on the app core. 

    Are there any Zephyr configurations or Nordic-specific settings required to properly separate logs and serial communication?

    Yes. The logging is by default done on the first UART instance, i.e. UARTE0. So if you set up a different UART for serial communication you should be fine. Just make sure that they use the same GPIOs as the network core use by default.

    What is the best way to ensure logs stay on VCOM1 and serial communication happens only on VCOM2?

    These are hard-wired to particular pins, so they will not change. 

    However, if you want to use UART for serial communication and at the same time monitor logs, another, perhaps easier option, is to use RTT Logging. This kind of log doesn't require it's own GPIOs. It uses a RAM buffer to write the log, and the debugger reads this RAM buffer. If you are interested, this is the way it is done in the NCS\nrf\samples\bluetooth\peripheral_uart sample. To monitor the LOG, you can either open the log in VS Code by connecting the RTT viewer there, or you can use a standalone RTT viewer, such as the one provided by JLink. (from segger.com). 

    Best regards,

    Edvin

Reply
  • Hello,

    The two COM ports on the DK are the two UARTs that the nRF5340 uses for logging by default. One for the application core, and one for the network core. So the one you are saying just logs boot information, that is probably the network core logging. 

    Is there an internal J-Link OB forwarding mechanism that could be causing this issue?

    The debugger is hard wired to specific GPIOs that are used by the app core and network core by default. They are listed on the back of the DK. They are named RTS TXD CTS and RXD.

    What you can do is to disable logging on the network core, stop the pin forwarding to the network core, and control these as a separate UART on the app core. 

    Are there any Zephyr configurations or Nordic-specific settings required to properly separate logs and serial communication?

    Yes. The logging is by default done on the first UART instance, i.e. UARTE0. So if you set up a different UART for serial communication you should be fine. Just make sure that they use the same GPIOs as the network core use by default.

    What is the best way to ensure logs stay on VCOM1 and serial communication happens only on VCOM2?

    These are hard-wired to particular pins, so they will not change. 

    However, if you want to use UART for serial communication and at the same time monitor logs, another, perhaps easier option, is to use RTT Logging. This kind of log doesn't require it's own GPIOs. It uses a RAM buffer to write the log, and the debugger reads this RAM buffer. If you are interested, this is the way it is done in the NCS\nrf\samples\bluetooth\peripheral_uart sample. To monitor the LOG, you can either open the log in VS Code by connecting the RTT viewer there, or you can use a standalone RTT viewer, such as the one provided by JLink. (from segger.com). 

    Best regards,

    Edvin

Children
  • Hello Edvin,

    Thank you for your response.  I have made the following configurations to separate logging and serial communication:

    Current Configuration:

    Device Tree Overlay (UART1 Enabled for Serial Communication):
    &uart1 {
        status = "okay";
    };



    Default UART1 Configuration:

    uart1: arduino_serial: uart@9000 {
        compatible = "nordic,nrf-uarte";
        reg = < 0x9000 0x1000 >;
        interrupts = < 0x9 0x1 >;
        status = "okay";
        current-speed = < 0x1c200 >;
        pinctrl-0 = < &uart1_default >;
        pinctrl-1 = < &uart1_sleep >;
        pinctrl-names = "default", "sleep";
    };
    
    uart1_default: uart1_default {
        group1 {
            psels = <NRF_PSEL(UART_TX, 1, 9)>,
                    <NRF_PSEL(UART_RTS, 1, 11)>;
        };
        group2 {
            psels = <NRF_PSEL(UART_RX, 1, 8)>,
                    <NRF_PSEL(UART_CTS, 1, 10)>;
            bias-pull-up;
        };
    };
    


    Issue 1: UART1 Not Receiving Data

    • I have connected an external USB-to-UART bridge to UART1.
    • However, when I send data from the external UART device, nothing is received in Zephyr.
    • My UART1 interrupt-based handler does not trigger on incoming data.

      UART Handling:
    #include <zephyr/kernel.h>
    #include <zephyr/drivers/uart.h>
    #include <zephyr/sys/printk.h>
    
    #define BUFFER_SIZE 526
    #define UART_NODE DT_NODELABEL(uart1)
    
    static const struct device *uart_dev = DEVICE_DT_GET(UART_NODE);
    static char command_buffer[BUFFER_SIZE];
    static int buffer_index = 0;
    static volatile bool command_ready = false;
    
    void uart_callback(const struct device *dev, void *user_data)
    {
        uint8_t c;
        printk("DEBUG: UART Callback\n");
        while (uart_irq_update(dev) && uart_irq_rx_ready(dev)) 
        {
            if (uart_fifo_read(dev, &c, 1) == 1) 
            {
                printk("DEBUG: Received Char: %c (ASCII: %d)\n", c, c); 
                if (c == '\n' || c == '\r') 
                {
                    if (buffer_index > 0) 
                    {
                        command_buffer[buffer_index] = '\0';
                        command_ready = true;
                    }
                }
                else if (buffer_index < BUFFER_SIZE - 1) 
                {
                    command_buffer[buffer_index++] = c;
                }
                else
                {
                    buffer_index = 0; // Reset on overflow
                }
            }
        }
    }
    
    int uart_init()
    {
        if (!device_is_ready(uart_dev))
        {
            printk("ERROR: UART device not ready!\n");
            return -1;
        }
        uart_irq_callback_set(uart_dev, uart_callback);
        uart_irq_rx_enable(uart_dev);
        printk("UART Initialized\n");
        return 0;
    }
    


    Debugging Steps Tried:

    1. Checked with device_is_ready(uart_dev), and UART1 is initialized successfully.
    2. Verified the external USB-to-UART bridge works with other devices.
    3. Confirmed UART1 TX/RX pins are set correctly.

      In this case if i use the UART0(VCOM1) then it work fine . 

    Issue 2: Unexpected Loopback Between VCOM2 and UART1

    • When I send data to VCOM2, it appears on UART1 (external USB-to-UART).
    • When I send data to UART1, it appears on VCOM2

    Questions:

    1. Disabling Network Core Logging & Stopping Pin Forwarding

      • How exactly do I disable logging on the network core and stop pin forwarding?
      • Should I modify the .overlay file, prj.conf, or both?
    2. Configuring UARTE0 for Logs & UART1 for Communication

      • How should I configure the .overlay file and prj.conf to ensure logs stay on UARTE0 while UART1 is used solely for communication?
    3. Preventing GPIO Conflicts with the Network Core

      • If the network core is using the same GPIOs by default, how can I prevent conflicts?
      • Should I modify the zephyr,console or zephyr,shell-uart settings?
      • Is there a way to stop pin forwarding to the network core while keeping the application core logging enabled?
    4. Additional Configuration Considerations

      • What additional configurations (e.g., Kconfig, DTS) are needed to ensure UART1 does not interfere with VCOM2?
      • Are there any nrfjprog or J-Link debugger settings that need to be changed?

    Could you guide me on the correct configurations to fully separate logging and serial communication in both cases—one without an external USB-to-UART adapter and one with it connected?

    Thanks in advance for your help!

Related