$ show cherry-embedded/CherryDAP
CherryDAP is an embedded firmware project that implements a CMSIS-DAP v2.1 debug probe (DAPLink) based on the CherryUSB stack and ARMmbed DAPLink reference code. It supports SWD and JTAG debugging protocols, a USB-to-UART bridge (CDC ACM), and optional features like SWO trace, custom HID commands, and a UF2 bootloader for firmware updates. The repository contains multiple hardware-specific projects targeting different microcontrollers (HPMicro HPM5301, Bouffalo Lab BL616, Espressif ESP32-S3) and two commercial probe variants (HSLink-Lite and HSLink-Pro). The HSLink-Pro variant adds advanced capabilities: programmable target voltage, NeoPixel LED, multi-function button, settings persistence via FlashDB, and a two-slot bootloader for fail-safe upgrades. The core DAP protocol handling is shared across all projects, while each platform provides its own pin configuration, I/O drivers (GPIO bit-bang or SPI-based protocol emulation), and USB descriptors. The architecture follows a monolithic firmware pattern per project, with a main loop that processes USB requests and handles UART data forwarding. The codebase demonstrates solid embedded engineering practices, including SPI-based protocol emulation for high-speed SWD/JTAG, a clean separation of protocol logic from hardware abstraction, and a feature-rich bootloader. However, there is notable code duplication across projects (e.g., SWD/JTAG I/O files, USB2UART implementations) which increases maintenance burden. The repository is actively maintained with recent commits, CI workflows, and documentation.
The LLM identified 6 files worth highlighting for reuse:
Core CMSIS-DAP protocol implementation. Handles all standard DAP commands (Info, Connect, Disconnect, Transfer, TransferBlock, SWJ_Pins, etc.) via DAP_ProcessCommand and DAP_ExecuteCommand. Platform-independent; relies on DAP_config.h for I/O macros. Reusable in any CMSIS-DAP firmware project.
SWD (Serial Wire Debug) transfer implementation. Provides SWD_Transfer() which handles line reset, ID code read, and data transfers using configurable I/O functions (GPIO or SPI). The same file is used across all projects, demonstrating clean abstraction.
SPI-based SWD I/O implementation. Uses the MCU's SPI peripheral in bidirectional mode (MOSI only) to emulate the SWD protocol at high speed (up to 20 MHz). This is a non-obvious, clever pattern that offloads timing from GPIO bit-bang to hardware SPI, achieving reliable high-speed debug access. Reusable for any MCU with SPI support.
UF2 bootloader implementation. Emulates a FAT16 filesystem over USB Mass Storage to accept firmware updates via drag-and-drop of .uf2 files. Includes flash write caching, block processing, and DBR (DOS Boot Record) definitions. Reusable as a standalone bootloader component for any MCU with USB MSC support.
Custom HID command handler for probe configuration. Parses JSON requests over a vendor-defined HID interface to get/set settings (nickname, reset mode, LED brightness), trigger firmware upgrades, and enter bootloader modes. Uses RapidJSON for parsing. Reusable pattern for adding a configuration interface to embedded devices.
SWD host layer providing high-level functions to access target debug registers (DP/AP) and memory (read/write word, block). Implements JTAG-to-SWD sequence, DP/AP selection, and error handling. Used by the DAP command processor to perform debug operations. Reusable across projects that need to talk to ARM Cortex-M targets.