CherryUSB: an embedded USB host and device stack designed around IP-level porting
CherryUSB is a tiny and beautiful, high performance and portable USB host and device stack for embedded system with USB IP
At a glance
- What is it?
- CherryUSB is a C library with USB host and device stacks for microcontrollers, covering seventeen device-side USB classes with zero heap allocation for most components. USB3.0 super speed is still marked as a TODO on the device side.
- Who is it for?
- CherryUSB suits embedded engineers who need a USB stack they can port to a microcontroller by writing two porting files for the USB IP, particularly where memory is tight and zero heap allocation matters. Skip it if you need USB3.0 super speed on the device side, since that is listed as TODO.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.
Editorial analysis
USB IP porting as the core design constraint: DCD and HCD interfaces
CherryUSB offers separate host and device stacks for embedded systems where the USB hardware is a USB IP block built into a microcontroller. Its architecture centres on a porting interface: device-side code adapts through a DCD (device controller driver) interface, and host-side code adapts through an HCD (host controller driver) interface. Engineers write those two adapter files once for their USB IP and then use the rest of the stack unchanged.
Repository topics name the USB IP controllers covered: dwc2, ehci, xhci, musb, ohci, cdns2, and cdns3. Each has a corresponding file or directory under port/. A microcontroller that uses one of those IPs can reuse an existing port file rather than writing a new one, which reduces the initial integration cost.
Documentation lives at https://cherryusb.readthedocs.io. A Chinese README is at README_zh.md in the repository root. The project also maintains a Discord server, linked from the badge row at the top of the README. A README section titled Why choose CherryUSB breaks the design rationale into three areas: learning the USB standard, interacting with the USB interface in application code, and achieving hardware-level USB performance.
Device stack: USB 2.0 full and high speed, zero heap for seventeen classes
On the device side, CherryUSB covers USB 2.0 full speed and high speed. The class list includes CDC_ACM, CDC_ECM, HID, MSC, UVC 1.0 and 1.5, UAC 1.0 and 2.0, RNDIS, DFU, MIDI, MTP, TMC, WINUSB 1.0 and 2.0, WEBUSB, BOS, UF2, Android Debug Bridge (shell only), a vendor display class, a vendor class, and multi-device USB IP. Composite device operation lets several classes run on one physical device simultaneously.
Resource consumption is documented in a table for GCC 10.2 at -O2 with logging disabled. usbd_core.c uses approximately 4,000 bytes of FLASH and 8 bytes of RAM. usbd_hid.c uses approximately 200 bytes of FLASH and 0 bytes of RAM. usbd_msc.c uses approximately 3,200 bytes of FLASH and 16 bytes of RAM per bus. usbd_audio.c uses approximately 1,300 bytes of FLASH. The heap column is zero for every component except usbd_mtp.c, where it scales with the number of MTP objects tracked.
Endpoint IRQ callbacks can be registered by users, letting application code run directly inside a USB interrupt handler for each endpoint. That capability is listed separately in the device stack feature set as an explicit design decision, not as a debugging convenience or an afterthought.
Memory zero copy, direct register access, and DMA packetization in interrupt context
CherryUSB's data transfer design rests on two principles: memory zero copy and no length restrictions on transmission or reception. The README describes the transfer interface as equivalent to UART TX DMA and UART RX DMA, which are familiar to most embedded engineers. Packetization into USB-sized packets happens inside the porting driver rather than in application code.
When the USB IP supports DMA, CherryUSB uses it. DMA also handles hardware packetization, and the no-length-restriction design makes it easier to wire up DMA channels that want a contiguous buffer. Porting drivers communicate directly with hardware registers rather than going through an intermediate abstraction layer, which keeps the path from buffer to wire short.
Packetization happens in interrupt context. That is a deliberate choice that has a real cost: any work placed in an endpoint callback shares the interrupt budget with the packetization logic, and long callbacks affect transfer throughput.
cherryusb_config_template.h and the demo/ directory as integration starting points
CherryUSB does not distribute a compiled binary. Integration starts by cloning or downloading the repository from https://github.com/cherry-embedded/CherryUSB and adding its directories to an existing project build. Several build systems are supported: CMake via cherryusb.cmake and CMakeLists.txt, Scons via SConscript, ESP-IDF via idf_component.yml, and Kconfig for RT-Thread via Kconfig and Kconfig.rtt.
The configuration entry point is cherryusb_config_template.h at the repository root. It controls buffer sizes, bus count and feature toggles. That file must be copied and edited before the first build because the stack reads configuration from it at compile time.
Demo files in the demo/ directory cover common class combinations. demo/cdc_acm_template.c shows a CDC ACM device. demo/cdc_acm_hid_msc_template.c shows a composite device with three classes active at once. demo/audio_v2_mic_speaker_multichan_template.c covers UAC 2.0 with both microphone and speaker channels. demo/dfu_template.c handles Device Firmware Upgrade. Each template follows the same pattern: register a class driver and implement its callbacks, with no boilerplate for USB enumeration, which the core handles.
Host stack: multi-level hub support limited to dwc2, ehci, xhci and rp2040
The host stack handles enumeration on root hubs and external hubs, loads class drivers automatically after enumeration, and supports both blocking and asynchronous transfers. Hub chaining is documented as expandable up to 7 levels, and a hub with 10 ports has been tested. That multi-level capability is limited to four specific port driver families: dwc2, ehci, xhci, and rp2040. Other USB IP families do not carry the same claim in the documentation.
Host-side class support covers CDC (ACM, ECM, NCM), HID, MSC, UVC 1.0 and 1.5, UAC 1.0, RNDIS, and DFU. Low speed, full speed, high speed and super speed devices can be connected on the host side. An OS is required for host stack management, and an osal abstraction layer must be ported for the target operating system. Kconfig.rtt at the repository root names RT-Thread as one target; a Zephyr directory is present at the top level as well.
Super speed device detection on the host side is listed in the feature set without any TODO marker, unlike the device-side super speed which is explicitly deferred.
USB3.0 super speed is marked TODO on device side; ADB covers shell only
Two capabilities carry explicit constraints. Device-side USB 3.0 super speed appears in the feature list with a TODO marker. An engineer who needs super speed on the device side cannot use the current stack for that use case.
Android Debug Bridge support on the device side covers shell only, as documented in the feature list. File transfer (adb push, adb pull) and other ADB services are not listed as supported features. demo/adb_template.c in the demo directory gives the starting point for an ADB shell implementation, and the README does not describe any broader ADB roadmap.
The hub limitation to dwc2, ehci, xhci and rp2040 also applies in practice: deep hub trees on other IP families have no documented support. The host stack feature list documents this boundary without explaining the reason behind it.
v1.6.1 on 2026-04-27, Apache-2.0 license, and a VERSION file at the root
Three recent releases appear in the repository: v1.6.1 on 2026-04-27, v1.6.0 on 2026-01-27, and v1.5.3.99 on 2026-01-22. The last push to master was on 2026-10-06, and the repository is not archived. A VERSION file sits at the repository root. A CHANGELOG-style document would be found at the readthedocs site rather than in the top-level file list, which does not contain a CHANGELOG.md.
Apache-2.0 is the declared license, matching the README badge and the LICENSE file at the repository root. idf_component.yml at the root means CherryUSB can be referenced as an ESP-IDF managed component rather than copied manually into a project tree. The Zephyr integration directory at the top level indicates that a Zephyr port exists, though its setup is not described in the README.
Engineers on platforms outside ESP-IDF and Zephyr write the porting layer directly from the DCD and HCD interfaces. The docs/ directory and the readthedocs site are the starting points for understanding what each interface requires.
Editorial conclusion
CherryUSB suits embedded engineers who need a USB stack they can port to a microcontroller by writing two porting files for the USB IP, particularly where memory is tight and zero heap allocation matters. Skip it if you need USB3.0 super speed on the device side, since that is listed as TODO. Before starting a port, check whether your USB IP controller appears in the port/ directory under one of the supported topics (dwc2, ehci, xhci, musb, ohci, cdns2, cdns3), and copy cherryusb_config_template.h from the repository root to understand which configuration values must be set before the first build.
Frequently asked questions
What is CherryUSB?
CherryUSB is an Apache-2.0 USB host and device stack written in C for embedded systems. It covers class drivers for CDC, HID, MSC, UVC, UAC, DFU, MIDI, MTP and more, with a porting interface for hardware USB IP controllers such as dwc2, ehci, xhci and musb.
How do I add CherryUSB to my embedded project?
Clone the repository and integrate it via CMake (cherryusb.cmake), Scons (SConscript), ESP-IDF (idf_component.yml), or Kconfig for RT-Thread. Copy cherryusb_config_template.h from the repository root and adjust buffer sizes and feature flags before building.
Does CherryUSB support USB3.0 super speed?
USB3.0 super speed on the device side is listed in the feature list but is marked as TODO. The device stack currently covers USB 2.0 full speed and high speed.
Which USB IP controllers does CherryUSB support?
Repository topics and the port/ directory cover dwc2, ehci, xhci, musb, ohci, cdns2, and cdns3. Multi-level hub support (up to 7 levels) on the host side is documented for dwc2, ehci, xhci, and rp2040.
Does CherryUSB require dynamic memory allocation?
The resource table in the README shows zero heap allocation for all listed device-side components except usbd_mtp.c, where heap usage scales with the number of MTP objects. The design avoids heap for the core and most class drivers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cherry-embedded-cherryusb)