Console output over USB

I'm a bit confused on the USB pins of the nRF5340 and how to use them. I have the USB D+/D- pins from my nRF5340 connected to the associated pins on a microUSB connector. I would like to get the console output from my application over the USB to a terminal on my Windows computer.

What's confusing about this is that various references to USB on this forum and others refers to UART over USB, but nothing about just straight USB.

If I only have the nRF5340 D+/D- pins connected, and don't have any of the UART pins connected, is there any way to get console output over the USB connection? If so, are there any examples of how to achieve this?

Parents
  • Hi,

     

    Logging over USB uses CDC, which enumerates as a COM-port in the OS even though all communication is USB.

    To route a CDC ACM to the console, you can have a look at the zephyr/samples/subsys/usb/console sample, specifically in the app.overlay file:

    https://github.com/nrfconnect/sdk-zephyr/blob/main/samples/subsys/usb/console/app.overlay

     

    Kind regards,

    Håkon

  • Thanks for the great information.  Using the example in the link, I was able to use the USB for console output by making the following changes:

    prj.conf

    CONFIG_LOG=y
    CONFIG_LOG_BACKEND_SHOW_COLOR=y
    CONFIG_LOG_MODE_DEFERRED=y
    CONFIG_USB_DEVICE_STACK_NEXT=y
    CONFIG_STDOUT_CONSOLE=y
    CONFIG_UART_LINE_CTRL=y
    CONFIG_USBD_CDC_ACM_CLASS=y
    CONFIG_USBD_LOG_LEVEL_WRN=y
    CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y
    CONFIG_UART_CONSOLE=y

    Added to my dts for my custom board, but could be added to an overlay for a DK:

    	chosen {
    		...
    		zephyr,console = &cdc_acm_uart0;
    	};
    	
    	&usbd {
    	status = "okay";
    	cdc_acm_uart0: cdc_acm_uart0 {
    		compatible = "zephyr,cdc-acm-uart";
    	};
    };

    And in my main.c file:

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/usb/usb_device.h>
    #include <zephyr/usb/usbd.h>
    #include <zephyr/drivers/uart.h>
    
    ...
    
    
    BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart), "Console device is not ACM CDC UART device");
    
    USBD_CONFIGURATION_DEFINE(usbd_config_1, USB_SCD_SELF_POWERED, 200);
    
    USBD_DESC_LANG_DEFINE(usb_lang);
    USBD_DESC_MANUFACTURER_DEFINE(usb_mfr, "CompanyName");
    USBD_DESC_PRODUCT_DEFINE(usb_product, "ProjectName");
    USBD_DESC_SERIAL_NUMBER_DEFINE(usb_sn, "1234SERIALNUMBER");
    
    USBD_DEVICE_DEFINE(my_usbd, DEVICE_DT_GET(DT_NODELABEL(usbd)), 0x2fe3, 0x0001);
    
    static int enable_usb_device_next(void)
    {
    	int err;
    
    	err = usbd_add_descriptor(&my_usbd, &usb_lang);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_descriptor(&my_usbd, &usb_mfr);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_descriptor(&my_usbd, &usb_product);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_descriptor(&my_usbd, &usb_sn);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_configuration(&my_usbd, &usbd_config_1);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_register_class(&my_usbd, "cdc_acm_0", 1);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_init(&my_usbd);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_enable(&my_usbd);
    	if (err) {
    		return err;
    	}
    
    	return 0;
    }
    //End Logging Setup
    
    
    int main(void)
    {
    
        ...
        
         //Init USB Console
        enable_usb_device_next();
        const struct device *const usbDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    	uint32_t dtr = 0;
    
        ...
        
        while(1) {
            //obviously change this to work for your needs
            if(!dtr) {
                uart_line_ctrl_get(usbDevice, UART_LINE_CTRL_DTR, &dtr);
            }
    
    		k_msleep(SLEEP_TIME_MS);
        }

Reply
  • Thanks for the great information.  Using the example in the link, I was able to use the USB for console output by making the following changes:

    prj.conf

    CONFIG_LOG=y
    CONFIG_LOG_BACKEND_SHOW_COLOR=y
    CONFIG_LOG_MODE_DEFERRED=y
    CONFIG_USB_DEVICE_STACK_NEXT=y
    CONFIG_STDOUT_CONSOLE=y
    CONFIG_UART_LINE_CTRL=y
    CONFIG_USBD_CDC_ACM_CLASS=y
    CONFIG_USBD_LOG_LEVEL_WRN=y
    CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y
    CONFIG_UART_CONSOLE=y

    Added to my dts for my custom board, but could be added to an overlay for a DK:

    	chosen {
    		...
    		zephyr,console = &cdc_acm_uart0;
    	};
    	
    	&usbd {
    	status = "okay";
    	cdc_acm_uart0: cdc_acm_uart0 {
    		compatible = "zephyr,cdc-acm-uart";
    	};
    };

    And in my main.c file:

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/logging/log.h>
    #include <zephyr/usb/usb_device.h>
    #include <zephyr/usb/usbd.h>
    #include <zephyr/drivers/uart.h>
    
    ...
    
    
    BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart), "Console device is not ACM CDC UART device");
    
    USBD_CONFIGURATION_DEFINE(usbd_config_1, USB_SCD_SELF_POWERED, 200);
    
    USBD_DESC_LANG_DEFINE(usb_lang);
    USBD_DESC_MANUFACTURER_DEFINE(usb_mfr, "CompanyName");
    USBD_DESC_PRODUCT_DEFINE(usb_product, "ProjectName");
    USBD_DESC_SERIAL_NUMBER_DEFINE(usb_sn, "1234SERIALNUMBER");
    
    USBD_DEVICE_DEFINE(my_usbd, DEVICE_DT_GET(DT_NODELABEL(usbd)), 0x2fe3, 0x0001);
    
    static int enable_usb_device_next(void)
    {
    	int err;
    
    	err = usbd_add_descriptor(&my_usbd, &usb_lang);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_descriptor(&my_usbd, &usb_mfr);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_descriptor(&my_usbd, &usb_product);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_descriptor(&my_usbd, &usb_sn);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_add_configuration(&my_usbd, &usbd_config_1);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_register_class(&my_usbd, "cdc_acm_0", 1);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_init(&my_usbd);
    	if (err) {
    		return err;
    	}
    
    	err = usbd_enable(&my_usbd);
    	if (err) {
    		return err;
    	}
    
    	return 0;
    }
    //End Logging Setup
    
    
    int main(void)
    {
    
        ...
        
         //Init USB Console
        enable_usb_device_next();
        const struct device *const usbDevice = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    	uint32_t dtr = 0;
    
        ...
        
        while(1) {
            //obviously change this to work for your needs
            if(!dtr) {
                uart_line_ctrl_get(usbDevice, UART_LINE_CTRL_DTR, &dtr);
            }
    
    		k_msleep(SLEEP_TIME_MS);
        }

Children
No Data
Related