Enabling an USB serial (CDC-ACM) on Zephyr (and other stuff)
Enabling the Serial communication on USB, for example for logging or for the shell subsystem is very easy, you just need to add some line in the device tree and enable the configuration on the config file. But for a bug or whatever, you also need to add a configuration line that is not documented, otherwise autostart will not work.
But let’s start from the beginning.
The USB CDC/ACM support can be enabled on the configuration only if it is enabled in the device tree. You need a node in your kconfig overlay:
...
&zephyr_udc0 {
cdc_acm_uart0: cdc_acm_uart0 {
compatible = "zephyr,cdc-acm-uart";
};
};
without this, the USB_CDC_ACM
entry will not be enabled (and indeed, west will complain during the merging of the config files).
Then you need to add a few lines in your config file:
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_CDC_ACM=y
CONFIG_USB_DEVICE_PID=0x0110
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y
CONFIG_UART_INTERRUPT_DRIVEN=y
The first line enables the USB device stack, the second the CDC_ACM service, so that when connected the device will emulate a MODEM or serial port (on linux it will appear as /dev/ttyACM*
node).
The third line will define the PID of the USB device; also a VID can be specified in the same way, but you need to register the proper VID code. Without it, the compiler will use a code reserved for testing, not suitable for production.
The fourth line (CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT
) avoids you the need to initialize and setting up of the USB stack, but Zephyr will initialize it for you. Check the documentation when it is ok and how to configure it eventually.
The last line is needed if you want to use the USB uart with the logger of with the shell. It is not clear why, but indeed without it the logger will not work.
Last thing, if you want to use the Logger or the shell, you must to define a chosen
node on the overlay again:
/ {
chosen {
zephyr,console = &cdc_acm_uart0;
zephyr,shell-uart = &cdc_acm_uart0;
};
...
};
With it the Logger source should work without any modification.
Compiling for multiple boards
If you want to compiler for different hardware, the best way is to put configuration files and device tree overlay in a proper file that will be merged at compile time.
This is especially useful because different boards may have different hardware configuration: for example, you may want to support a USB UART on one board and TTL UART on another.
For example, suppose you have, like me, two boards: an adafruit feather nrf52840 and an adafruit kb2040.
Create a boards
subdirectory in your main project directory and put there those files:
adafruit_kb2040.overlay
for the kb2040 overlayfileadafruit_kb2040.conf
the kconfig file for the kb2040adafruit_feather_nrf52840.overlay
is the dt overlay for the featheradafruit_feather_nrf52840
is the kconfig for the feather
There must be no app.overlay
files, because it would be override all the other device tree overlay. On the other hand, the can be a main prj.conf
that will be merged with the board specific files.
Adding an ESP32 (Adafruit Huzzah32)
The Adafruit Huzzah32 board is a development board / Module based on the Espressif SoM ESP32.
Porting our experiment to it is simple, but requires some additional comment.
First you need to setup the environment. Zephyr requires some BLOB to be installed. Go in the zephyr folder and install it:
$ cd zephyrproject
$ west update
$ west blobs fetch hal_espressif
Now, back to our project. Let’s add a devicetree overlay in the boards
directory, because the board doesn’t require any additional configuration even if we want to use the USB as a serial port. Indeed the board has a small bootloader that sets up the USB as a CDC port and we can use it to program the board and output the logs.
Huzzah provides a red LED connected to the GPIO13.
let’s add our Device tree overlay:
/ {
aliases {
led0 = &led_blue;
};
leds {
compatible = "gpio-leds";
led_blue: led_0 {
gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
};
};
};
This is almost identicaly to the nrf52840 version, except for the GPIO number.
To compile, we use the esp32
board specifications, because there is no specific support for the Huzzah.
$ west build -b esp32 -d build-esp32
To flash the board, simply use west:
$ west flash -d build-esp32
Note that you don’t have to specify the board but just the building directory.