Zephyr: USB ACM (Virtual Serial Port) with the ST STM32U083

 Date: January 31, 2025

Integrating a virtual USART interface using USB isn’t complicated (well.. after fixing a warning as nobody seems to have used it before) on STM32U083 with Zephyr. This example is based on the STM32U083C-DK Discovery Kit and the Zephyr version 4.0.0 (master). The .dts file of the “Discovery Kit” can be found in the boards directory of Zephyr.

Clock, Pin and Interface Configuration

I decided to go with the HSI48 for the USB clock generation. First create a clock configuration on STM32CubeIDE with the known configuration from the board .dts (setting M, N, P, Q, R, AHB-Prescaler, AHPB1-Prescaler, etc.). Then it’s easier to fill out the missing data.

#include <st/u0/stm32u083Xc.dtsi>
#include <st/u0/stm32u083mctx-pinctrl.dtsi>
#include <zephyr/dt-bindings/input/input-event-codes.h>

/ {
	model = "SolarLoraBox";
	compatible = "st,stm32u083c-dk";

	#address-cells = <1>;
	#size-cells = <1>;

	chosen {
		zephyr,console = &usb_cdc_acm_uart;
		zephyr,shell-uart = &usb_cdc_acm_uart;
		zephyr,sram = &sram0;
		zephyr,flash = &flash0;
	};

(...)
};

&clk_hsi48 {
	status = "okay";
};

zephyr_udc0: &usb {
	clocks = <&rcc STM32_CLOCK(APB1, 13U)>,
		 <&rcc STM32_SRC_HSI48 CLK48_SEL(3)>;
	pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>;
	pinctrl-names = "default";
	status = "okay";

	usb_cdc_acm_uart: cdc_acm_uart {
		compatible = "zephyr,cdc-acm-uart";
	};
};

<&rcc STM32_SRC_HSI48 CLK48_SEL(3)> means that the device uses the HSI48 source. Explaination of the options can be found in the manual (RM0503, p. 203).

In the STM32 world all devices seem to use pins PA11 and PA12 for USB - so this configuration is rather easy ;-)

Driver Integration

After the clocktree is configured the next step is to add all relevant configuration flags.

# The Shell is extremely helpful with the USBD extensions to debug issues
CONFIG_SHELL=y
CONFIG_USBD_SHELL=y

# I wasn't able to get the legacy stack running. The "NEXT" worked out of the box.
CONFIG_USB_DEVICE_STACK_NEXT=y

# Copied from the kernel defaults
CONFIG_USBD_THREAD_STACK_SIZE=1024
CONFIG_USBD_MAX_UDC_MSG=10
CONFIG_USBD_MSG_SLAB_COUNT=8
CONFIG_USBD_MSG_WORK_DELAY=1

# This is the integration of the virtual port
CONFIG_USBD_CDC_ACM_CLASS=y
CONFIG_USBD_CDC_ACM_STACK_SIZE=1024

CONFIG_UART_LINE_CTRL=y

Now the big problem: PID, Product ID, etc. cannot be set using CONFIG_ flags.

The easiest solution is to copy the common part the official usbd example application from here. It consists of sample_usbd.h, sample_usbd_init.c and the Kconfig.sample_usbd. Do not forget to include the Kconfig.sample_usbd into your Kconfig with rsource. rsource is the relative path to your project where source is the path to the Zephyr main project directory.

For the first test connect your USB<->RS232 adapter to the board without modifying zephyr,console and zephyr,shell-uart, flash and powercycle it.

A successful start looks like this in the Zephyr console

** Booting Zephyr OS build 2594eae6f13e ***
[00:00:00.002,000] <inf> usbd_init: interface 0 alternate 0
[00:00:00.002,000] <inf> usbd_init:     ep 0x81 mps 0x0010 interface ep-bm 0x00020000
[00:00:00.002,000] <inf> usbd_init: interface 1 alternate 0
[00:00:00.002,000] <inf> usbd_init:     ep 0x82 mps 0x0040 interface ep-bm 0x00040000
[00:00:00.002,000] <inf> usbd_init:     ep 0x01 mps 0x0040 interface ep-bm 0x00040002
[00:00:00.002,000] <inf> usbd_init: Instance iface-bm 0x00000003 ep-bm 0x00060002
[00:00:00.002,000] <inf> usbd_init: Init class node 0x20000438, descriptor length 66
[00:00:00.002,000] <inf> usbd_init: bNumInterfaces 2 wTotalLength 75
[00:00:00.002,000] <inf> usbd_init: FS bNumConfigurations 1
[00:00:00.002,000] <inf> main: USB device support enabled
[00:00:00.344,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:00.344,000] <inf> usbd_core: Actual device speed 1
[00:00:00.406,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.441,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:00.441,000] <inf> usbd_core: Actual device speed 1
[00:00:00.494,000] <inf> udc: Sequence 4 not completed
--- 3 messages dropped ---
[00:00:00.494,000] <inf> usbd_ch9: Handle control 0x20005b54 ep 0x00, len 8, s:1 d:0 s:0
--- 5 messages dropped ---
[00:00:00.494,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x80, len 0, s:0 d:0 s:1
[00:00:00.494,000] <inf> usbd_ch9: s-(out)-status finished
[00:00:00.505,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.506,000] <inf> udc: Sequence 4 not completed
[00:00:00.506,000] <inf> usbd_ch9: Handle control 0x20005b54 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.506,000] <inf> usbd_ch9: protocol error:
[00:00:00.506,000] <inf> usbd_ch9: setup:
                                   80 06 00 06 00 00 0a 00                          |........         
[00:00:00.506,000] <inf> usbd_ch9: not supported
[00:00:00.507,000] <inf> udc: Sequence 2 not completed
[00:00:00.507,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.507,000] <inf> usbd_ch9: protocol error:
[00:00:00.507,000] <inf> usbd_ch9: setup:
                                   80 06 00 06 00 00 0a 00                          |........         
[00:00:00.508,000] <inf> usbd_ch9: protocol error:
[00:00:00.508,000] <inf> usbd_ch9: setup:
                                   80 06 00 06 00 00 0a 00                          |........         
[00:00:00.513,000] <inf> udc: Sequence 4 not completed
[00:00:00.513,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.515,000] <inf> udc: Sequence 4 not completed
[00:00:00.515,000] <inf> usbd_ch9: Handle control 0x20005b54 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.517,000] <inf> udc: Sequence 4 not completed
[00:00:00.517,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.519,000] <inf> udc: Sequence 4 not completed
[00:00:00.519,000] <inf> usbd_ch9: Handle control 0x20005b54 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.553,000] <inf> udc: Sequence 4 not completed
[00:00:00.553,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.553,000] <inf> usbd_ch9: Set Configuration Request value 1
[00:00:00.553,000] <inf> usbd_iface: Modify interface 0 ep 0x81 by op 1 ep_bm 20000
[00:00:00.553,000] <inf> usbd_iface: Modify interface 1 ep 0x82 by op 1 ep_bm 60000
[00:00:00.554,000] <inf> usbd_iface: Modify interface 1 ep 0x01 by op 1 ep_bm 60002
[00:00:00.554,000] <inf> usbd_cdc_acm: Configuration enabled
[00:00:00.554,000] <inf> usbd_ch9: Handle control 0x20005b54 ep 0x80, len 0, s:0 d:0 s:1
[00:00:00.554,000] <inf> usbd_ch9: s-(out)-status finished
[00:00:00.554,000] <inf> usbd_ch9: Handle control 0x20005b54 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.556,000] <inf> udc: Sequence 4 not completed
[00:00:00.557,000] <inf> usbd_ch9: Handle control 0x20005b30 ep 0x00, len 8, s:1 d:0 s:0
[00:00:00.557,000] <inf> usbd_ch9: spool 0x20005b54
[00:00:00.558,000] <inf> usbd_ch9: Handle control 0x20005b78 ep 0x80, len 0, s:0 d:0 s:1
[00:00:00.558,000] <inf> usbd_ch9: s-(out)-status finished

Linux then spits out

[13059.392184] [  T35252] usb 3-3.3: new full-speed USB device number 11 using xhci_hcd
[13059.506592] [  T35252] usb 3-3.3: New USB device found, idVendor=2fe3, idProduct=0001, bcdDevice= 4.00
[13059.506598] [  T35252] usb 3-3.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[13059.506599] [  T35252] usb 3-3.3: Product: USBD sample
[13059.506600] [  T35252] usb 3-3.3: Manufacturer: Zephyr Project
[13059.506601] [  T35252] usb 3-3.3: SerialNumber: 12345
[13059.567592] [  T36959] cdc_acm 3-3.3:1.0: ttyACM0: USB ACM device
[13059.567618] [  T36959] usbcore: registered new interface driver cdc_acm
[13059.567619] [  T36959] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

Troubleshooting

*** Booting Zephyr OS build 2594eae6f13e ***
[00:00:00.002,000] <inf> usbd_init: interface 0 alternate 0
[00:00:00.002,000] <inf> usbd_init:     ep 0x81 mps 0x0010 interface ep-bm 0x00020000
[00:00:00.002,000] <inf> usbd_init: interface 1 alternate 0
[00:00:00.002,000] <inf> usbd_init:     ep 0x82 mps 0x0040 interface ep-bm 0x00040000
[00:00:00.002,000] <inf> usbd_init:     ep 0x01 mps 0x0040 interface ep-bm 0x00040002
[00:00:00.002,000] <inf> usbd_init: Instance iface-bm 0x00000003 ep-bm 0x00060002
[00:00:00.002,000] <inf> usbd_init: Init class node 0x20000438, descriptor length 66
[00:00:00.002,000] <inf> usbd_init: bNumInterfaces 2 wTotalLength 75
[00:00:00.002,000] <inf> usbd_init: FS bNumConfigurations 1
[00:00:00.002,000] <inf> main: USB device support enabled
[00:00:00.328,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:00.328,000] <inf> usbd_core: Actual device speed 1
[00:00:00.415,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:00.415,000] <inf> usbd_core: Actual device speed 1
[00:00:00.615,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:00.616,000] <inf> usbd_core: Actual device speed 1
[00:00:00.815,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:00.815,000] <inf> usbd_core: Actual device speed 1
[00:00:00.912,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:00.912,000] <inf> usbd_core: Actual device speed 1
[00:00:01.111,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:01.111,000] <inf> usbd_core: Actual device speed 1
[00:00:01.615,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:01.615,000] <inf> usbd_core: Actual device speed 1
[00:00:01.651,000] <inf> udc: ep 0x80 is not halted|disabled
[00:00:01.651,000] <inf> usbd_core: Actual device speed 1

That’s most likely a clocktree issue.

Check if HSI48/MSI/etc. initalized and correctly configured?


Previous
⏪ Zephyr: State of LoRa(WAN)

Next
Hunting the HT-CT62 Meshtastic deafness syndrome ⏩