├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── Makefile ├── README.md ├── bsp ├── default │ ├── DAP_config.h │ └── unique.h ├── rp2040 │ ├── DAP_config.h │ ├── cdc_uart.c │ ├── picoprobe_config.h │ └── unique.h └── stm32f072disco │ ├── DAP_config.h │ ├── cdc_uart.c │ └── unique.h ├── main.c ├── tusb_config.h └── usb_descriptors.c /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tinyusb"] 2 | path = tinyusb 3 | url = https://github.com/hathach/tinyusb 4 | [submodule "CMSIS_5"] 5 | path = CMSIS_5 6 | url = https://github.com/ARM-software/CMSIS_5.git 7 | [submodule "pico-sdk"] 8 | path = pico-sdk 9 | url = https://github.com/raspberrypi/pico-sdk 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | include(${CMAKE_CURRENT_SOURCE_DIR}/tinyusb/hw/bsp/family_support.cmake) 4 | 5 | # gets PROJECT name for the example (e.g. -) 6 | get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME) 7 | set(PROJECT ${BOARD}-${PROJECT}) 8 | 9 | project(${PROJECT}) 10 | 11 | # Checks this example is valid for the family and initializes the project 12 | family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) 13 | 14 | add_executable(${PROJECT}) 15 | 16 | # Example source 17 | target_sources(${PROJECT} PUBLIC 18 | ${CMAKE_CURRENT_SOURCE_DIR}/main.c 19 | ${CMAKE_CURRENT_SOURCE_DIR}/usb_descriptors.c 20 | ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Source/DAP.c 21 | ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Source/JTAG_DP.c 22 | ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Source/DAP_vendor.c 23 | ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Source/SWO.c 24 | ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Source/SW_DP.c 25 | ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/cdc_uart.c 26 | ) 27 | 28 | # Example include 29 | target_include_directories(${PROJECT} PUBLIC 30 | ${CMAKE_CURRENT_SOURCE_DIR}/ 31 | ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/DAP/Firmware/Include/ 32 | ${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_5/CMSIS/Core/Include/ 33 | ${CMAKE_CURRENT_SOURCE_DIR}/bsp/${FAMILY}/ 34 | ${CMAKE_CURRENT_SOURCE_DIR}/bsp/default/ 35 | ) 36 | 37 | target_link_libraries(${PROJECT} PUBLIC pico_unique_id) 38 | 39 | # Configure compilation flags and libraries for the example... see the corresponding function 40 | # in hw/bsp/FAMILY/family.cmake for details. 41 | family_configure_device_example(${PROJECT}) 42 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | include ./tinyusb/tools/top.mk 2 | include ./tinyusb/examples/make.mk 3 | 4 | PICO_SDK_PATH = ../../pico-sdk 5 | 6 | INC += \ 7 | . \ 8 | ./CMSIS_5/CMSIS/DAP/Firmware/Include \ 9 | ./bsp/$(BOARD) \ 10 | ./bsp/default \ 11 | $(TOP)/hw 12 | 13 | APP_SOURCE += $(wildcard ./*.c) 14 | 15 | SRC_C += $(addprefix $(CURRENT_PATH)/, $(APP_SOURCE)) 16 | 17 | SRC_C += \ 18 | ./CMSIS_5/CMSIS/DAP/Firmware/Source/DAP.c \ 19 | ./CMSIS_5/CMSIS/DAP/Firmware/Source/JTAG_DP.c \ 20 | ./CMSIS_5/CMSIS/DAP/Firmware/Source/DAP_vendor.c \ 21 | ./CMSIS_5/CMSIS/DAP/Firmware/Source/SWO.c \ 22 | ./CMSIS_5/CMSIS/DAP/Firmware/Source/SW_DP.c \ 23 | ./bsp/$(BOARD)/cdc_uart.c 24 | 25 | include ./tinyusb/examples/rules.mk 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Dapper Mime 2 | 3 | This unearths the name of a weekend project that I did in 2014. Both then and now, this is a port of [ARM's CMSIS-DAP code](https://github.com/arm-software/CMSIS_5) to a platform without the need for an expensive proprietary compiler and USB drivers. 4 | 5 | Whereas the original code used ST's STM32 USB drivers, this new iteration uses [TinyUSB](https://github.com/hathach/tinyusb), an open source cross-platform USB stack for embedded systems. 6 | 7 | ## Variants 8 | 9 | Most [TinyUSB supported MCUs](https://github.com/hathach/tinyusb/blob/master/docs/boards.md) can run this code; a subdirectory under bsp needs to be added for the "BOARD" name with a DAP_config.h to control the SWD/JTAG GPIOs and a unique.h to provide unique serial number (if any) and prefix to the USB product name. 10 | 11 | Already added BOARD variants include: 12 | 13 | For BOARD=raspberry_pi_pico, this project results in a standards-based CMSIS-DAP alternative to the approaches suggested in Chapter 5 and Appendix A of [Getting Started with Raspberry Pi Pico](https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf). This uses two RP2040 boards (see [wiring loom shown in Figure 34](https://user-images.githubusercontent.com/12226419/134785445-5f651d5a-eda9-4e94-8860-d2ef619dc27a.png) of Appendix A) where one RP2040 is the debugger and the other RP2040 is being debugged. The instructions in Chapter 5 apply, except no Raspberry Pi is needed. 14 | 15 | Alternatively, a special one RP2040 “Raspberry Pi Pico” variant is [available here](https://github.com/majbthrd/pico-debug). 16 | 17 | For BOARD=stm32f072disco, the inexpensive [32F072BDISCOVERY evaluation board](https://www.st.com/en/evaluation-tools/32f072bdiscovery.html) can be used as a CMSIS-DAP SWD debugger. 18 | 19 | ## Building 20 | 21 | Unless you have a burning desire to build this from scratch, consider just downloading pre-build images [from the selection here](https://github.com/majbthrd/DapperMime/releases). 22 | 23 | If, however, you are determined to build from scratch (for example, if you are planning to port Dapper Mime to an additional MCU), after initially downloading this project's code, issue the following command to download TinyUSB and CMSIS_5 code (as well as all submodules): 24 | 25 | ``` 26 | git submodule update --init --recursive 27 | ``` 28 | 29 | Follow the TinyUSB build instructions [available here](https://github.com/hathach/tinyusb/blob/master/docs/reference/getting_started.rst), but issue the make command in the base directory of Dapper Mime. 30 | 31 | Note that each TinyUSB board name being targeted needs a corresponding subdirectory under the Dapper Mime ./bsp/ subdirectory and a customized version of DAP_config.h for the target. 32 | 33 | ## License 34 | 35 | TinyUSB is licensed under the [MIT license](https://opensource.org/licenses/MIT). 36 | 37 | ARM's CMSIS_5 code is licensed under the [Apache 2.0 license](https://opensource.org/licenses/Apache-2.0). 38 | 39 | Source code files within this project are licensed under the [MIT license](https://opensource.org/licenses/MIT) unless otherwise stated. 40 | 41 | -------------------------------------------------------------------------------- /bsp/default/DAP_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | This is *NOT* a valid CMSIS-DAP configuration; it is merely a fallback default to compile. 3 | */ 4 | 5 | /* 6 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 7 | * 8 | * SPDX-License-Identifier: Apache-2.0 9 | * 10 | * Licensed under the Apache License, Version 2.0 (the License); you may 11 | * not use this file except in compliance with the License. 12 | * You may obtain a copy of the License at 13 | * 14 | * www.apache.org/licenses/LICENSE-2.0 15 | * 16 | * Unless required by applicable law or agreed to in writing, software 17 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 18 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | * See the License for the specific language governing permissions and 20 | * limitations under the License. 21 | * 22 | * ---------------------------------------------------------------------- 23 | * 24 | * $Date: 1. December 2017 25 | * $Revision: V2.0.0 26 | * 27 | * Project: CMSIS-DAP Configuration 28 | * Title: DAP_config.h CMSIS-DAP Configuration File (Template) 29 | * 30 | *---------------------------------------------------------------------------*/ 31 | 32 | #ifndef __DAP_CONFIG_H__ 33 | #define __DAP_CONFIG_H__ 34 | 35 | 36 | //************************************************************************************************** 37 | /** 38 | \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information 39 | \ingroup DAP_ConfigIO_gr 40 | @{ 41 | Provides definitions about the hardware and configuration of the Debug Unit. 42 | 43 | This information includes: 44 | - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. 45 | - Debug Unit Identification strings (Vendor, Product, Serial Number). 46 | - Debug Unit communication packet size. 47 | - Debug Access Port supported modes and settings (JTAG/SWD and SWO). 48 | - Optional information about a connected Target Device (for Evaluation Boards). 49 | */ 50 | 51 | #include "cmsis_compiler.h" 52 | #include "bsp/board.h" 53 | 54 | /// Processor Clock of the Cortex-M MCU used in the Debug Unit. 55 | /// This value is used to calculate the SWD/JTAG clock speed. 56 | #define CPU_CLOCK 100000000U ///< Specifies the CPU Clock in Hz. 57 | 58 | /// Number of processor cycles for I/O Port write operations. 59 | /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O 60 | /// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors 61 | /// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses 62 | /// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be 63 | /// required. 64 | #define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. 65 | 66 | /// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. 67 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 68 | #define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. 69 | 70 | /// Indicate that JTAG communication mode is available at the Debug Port. 71 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 72 | #define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. 73 | 74 | /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. 75 | /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. 76 | #define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. 77 | 78 | /// Default communication mode on the Debug Access Port. 79 | /// Used for the command \ref DAP_Connect when Port Default mode is selected. 80 | #define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. 81 | 82 | /// Default communication speed on the Debug Access Port for SWD and JTAG mode. 83 | /// Used to initialize the default SWD/JTAG clock frequency. 84 | /// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. 85 | #define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. 86 | 87 | /// Maximum Package Size for Command and Response data. 88 | /// This configuration settings is used to optimize the communication performance with the 89 | /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, 90 | /// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. 91 | #define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes. 92 | 93 | /// Maximum Package Buffers for Command and Response data. 94 | /// This configuration settings is used to optimize the communication performance with the 95 | /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the 96 | /// setting can be reduced (valid range is 1 .. 255). 97 | #define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered. 98 | 99 | /// Indicate that UART Serial Wire Output (SWO) trace is available. 100 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 101 | #define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available. 102 | 103 | /// Maximum SWO UART Baudrate. 104 | #define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz. 105 | 106 | /// Indicate that Manchester Serial Wire Output (SWO) trace is available. 107 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 108 | #define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. 109 | 110 | /// SWO Trace Buffer Size. 111 | #define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). 112 | 113 | /// SWO Streaming Trace. 114 | #define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. 115 | 116 | /// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. 117 | #define TIMESTAMP_CLOCK 0U ///< Timestamp clock in Hz (0 = timestamps not supported). 118 | 119 | /// Debug Unit is connected to fixed Target Device. 120 | /// The Debug Unit may be part of an evaluation board and always connected to a fixed 121 | /// known device. In this case a Device Vendor and Device Name string is stored which 122 | /// may be used by the debugger or IDE to configure device parameters. 123 | #define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; 124 | 125 | #if TARGET_DEVICE_FIXED 126 | #define TARGET_DEVICE_VENDOR "ARM" ///< String indicating the Silicon Vendor 127 | #define TARGET_DEVICE_NAME "Cortex-M4" ///< String indicating the Target Device 128 | #endif 129 | 130 | /** Get Vendor ID string. 131 | \param str Pointer to buffer to store the string. 132 | \return String length. 133 | */ 134 | __STATIC_INLINE uint8_t DAP_GetVendorString (char *str) { 135 | (void)str; 136 | return (0U); 137 | } 138 | 139 | /** Get Product ID string. 140 | \param str Pointer to buffer to store the string. 141 | \return String length. 142 | */ 143 | __STATIC_INLINE uint8_t DAP_GetProductString (char *str) { 144 | (void)str; 145 | return (0U); 146 | } 147 | 148 | /** Get Serial Number string. 149 | \param str Pointer to buffer to store the string. 150 | \return String length. 151 | */ 152 | __STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) { 153 | (void)str; 154 | return (0U); 155 | } 156 | 157 | ///@} 158 | 159 | 160 | //************************************************************************************************** 161 | /** 162 | \defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access 163 | \ingroup DAP_ConfigIO_gr 164 | @{ 165 | 166 | Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode 167 | and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug 168 | interface of a device. The following I/O Pins are provided: 169 | 170 | JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode 171 | ---------------------------- | -------------------- | --------------------------------------------- 172 | TCK: Test Clock | SWCLK: Clock | Output Push/Pull 173 | TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) 174 | TDI: Test Data Input | | Output Push/Pull 175 | TDO: Test Data Output | | Input 176 | nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor 177 | nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor 178 | 179 | 180 | DAP Hardware I/O Pin Access Functions 181 | ------------------------------------- 182 | The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to 183 | these I/O Pins. 184 | 185 | For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. 186 | This functions are provided to achieve faster I/O that is possible with some advanced GPIO 187 | peripherals that can independently write/read a single I/O pin without affecting any other pins 188 | of the same I/O port. The following SWDIO I/O Pin functions are provided: 189 | - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. 190 | - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. 191 | - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. 192 | - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. 193 | */ 194 | 195 | 196 | // Configure DAP I/O pins ------------------------------ 197 | 198 | /** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. 199 | Configures the DAP Hardware I/O pins for JTAG mode: 200 | - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level. 201 | - TDO to input mode. 202 | */ 203 | __STATIC_INLINE void PORT_JTAG_SETUP (void) { 204 | ; 205 | } 206 | 207 | /** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. 208 | Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: 209 | - SWCLK, SWDIO, nRESET to output mode and set to default high level. 210 | - TDI, nTRST to HighZ mode (pins are unused in SWD mode). 211 | */ 212 | __STATIC_INLINE void PORT_SWD_SETUP (void) { 213 | ; 214 | } 215 | 216 | /** Disable JTAG/SWD I/O Pins. 217 | Disables the DAP Hardware I/O pins which configures: 218 | - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. 219 | */ 220 | __STATIC_INLINE void PORT_OFF (void) { 221 | ; 222 | } 223 | 224 | 225 | // SWCLK/TCK I/O pin ------------------------------------- 226 | 227 | /** SWCLK/TCK I/O pin: Get Input. 228 | \return Current status of the SWCLK/TCK DAP hardware I/O pin. 229 | */ 230 | __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) { 231 | return (0U); 232 | } 233 | 234 | /** SWCLK/TCK I/O pin: Set Output to High. 235 | Set the SWCLK/TCK DAP hardware I/O pin to high level. 236 | */ 237 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) { 238 | ; 239 | } 240 | 241 | /** SWCLK/TCK I/O pin: Set Output to Low. 242 | Set the SWCLK/TCK DAP hardware I/O pin to low level. 243 | */ 244 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) { 245 | ; 246 | } 247 | 248 | 249 | // SWDIO/TMS Pin I/O -------------------------------------- 250 | 251 | /** SWDIO/TMS I/O pin: Get Input. 252 | \return Current status of the SWDIO/TMS DAP hardware I/O pin. 253 | */ 254 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) { 255 | return (0U); 256 | } 257 | 258 | /** SWDIO/TMS I/O pin: Set Output to High. 259 | Set the SWDIO/TMS DAP hardware I/O pin to high level. 260 | */ 261 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) { 262 | ; 263 | } 264 | 265 | /** SWDIO/TMS I/O pin: Set Output to Low. 266 | Set the SWDIO/TMS DAP hardware I/O pin to low level. 267 | */ 268 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) { 269 | ; 270 | } 271 | 272 | /** SWDIO I/O pin: Get Input (used in SWD mode only). 273 | \return Current status of the SWDIO DAP hardware I/O pin. 274 | */ 275 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) { 276 | return (board_millis() & 1); /* pacify GCC warning */ 277 | } 278 | 279 | /** SWDIO I/O pin: Set Output (used in SWD mode only). 280 | \param bit Output value for the SWDIO DAP hardware I/O pin. 281 | */ 282 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) { 283 | (void)bit; 284 | } 285 | 286 | /** SWDIO I/O pin: Switch to Output mode (used in SWD mode only). 287 | Configure the SWDIO DAP hardware I/O pin to output mode. This function is 288 | called prior \ref PIN_SWDIO_OUT function calls. 289 | */ 290 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) { 291 | ; 292 | } 293 | 294 | /** SWDIO I/O pin: Switch to Input mode (used in SWD mode only). 295 | Configure the SWDIO DAP hardware I/O pin to input mode. This function is 296 | called prior \ref PIN_SWDIO_IN function calls. 297 | */ 298 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) { 299 | ; 300 | } 301 | 302 | 303 | // TDI Pin I/O --------------------------------------------- 304 | 305 | /** TDI I/O pin: Get Input. 306 | \return Current status of the TDI DAP hardware I/O pin. 307 | */ 308 | __STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) { 309 | return (0U); 310 | } 311 | 312 | /** TDI I/O pin: Set Output. 313 | \param bit Output value for the TDI DAP hardware I/O pin. 314 | */ 315 | __STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) { 316 | (void)bit; 317 | } 318 | 319 | 320 | // TDO Pin I/O --------------------------------------------- 321 | 322 | /** TDO I/O pin: Get Input. 323 | \return Current status of the TDO DAP hardware I/O pin. 324 | */ 325 | __STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) { 326 | return (board_millis() & 1); /* pacify GCC warning */ 327 | } 328 | 329 | 330 | // nTRST Pin I/O ------------------------------------------- 331 | 332 | /** nTRST I/O pin: Get Input. 333 | \return Current status of the nTRST DAP hardware I/O pin. 334 | */ 335 | __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) { 336 | return (0U); 337 | } 338 | 339 | /** nTRST I/O pin: Set Output. 340 | \param bit JTAG TRST Test Reset pin status: 341 | - 0: issue a JTAG TRST Test Reset. 342 | - 1: release JTAG TRST Test Reset. 343 | */ 344 | __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) { 345 | (void)bit; 346 | } 347 | 348 | // nRESET Pin I/O------------------------------------------ 349 | 350 | /** nRESET I/O pin: Get Input. 351 | \return Current status of the nRESET DAP hardware I/O pin. 352 | */ 353 | __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) { 354 | return (0U); 355 | } 356 | 357 | /** nRESET I/O pin: Set Output. 358 | \param bit target device hardware reset pin status: 359 | - 0: issue a device hardware reset. 360 | - 1: release device hardware reset. 361 | */ 362 | __STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) { 363 | (void)bit; 364 | } 365 | 366 | ///@} 367 | 368 | 369 | //************************************************************************************************** 370 | /** 371 | \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs 372 | \ingroup DAP_ConfigIO_gr 373 | @{ 374 | 375 | CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. 376 | 377 | It is recommended to provide the following LEDs for status indication: 378 | - Connect LED: is active when the DAP hardware is connected to a debugger. 379 | - Running LED: is active when the debugger has put the target device into running state. 380 | */ 381 | 382 | /** Debug Unit: Set status of Connected LED. 383 | \param bit status of the Connect LED. 384 | - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. 385 | - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. 386 | */ 387 | __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) { 388 | (void)bit; 389 | } 390 | 391 | /** Debug Unit: Set status Target Running LED. 392 | \param bit status of the Target Running LED. 393 | - 1: Target Running LED ON: program execution in target started. 394 | - 0: Target Running LED OFF: program execution in target stopped. 395 | */ 396 | __STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) { 397 | (void)bit; 398 | } 399 | 400 | ///@} 401 | 402 | 403 | //************************************************************************************************** 404 | /** 405 | \defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp 406 | \ingroup DAP_ConfigIO_gr 407 | @{ 408 | Access function for Test Domain Timer. 409 | 410 | The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By 411 | default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. 412 | 413 | */ 414 | 415 | /** Get timestamp of Test Domain Timer. 416 | \return Current timestamp value. 417 | */ 418 | __STATIC_INLINE uint32_t TIMESTAMP_GET (void) { 419 | #if TIMESTAMP_CLOCK > 0 420 | return (DWT->CYCCNT); 421 | #else 422 | return 0; 423 | #endif 424 | } 425 | 426 | ///@} 427 | 428 | 429 | //************************************************************************************************** 430 | /** 431 | \defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization 432 | \ingroup DAP_ConfigIO_gr 433 | @{ 434 | 435 | CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. 436 | */ 437 | 438 | /** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). 439 | This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the 440 | Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: 441 | - I/O clock system enabled. 442 | - all I/O pins: input buffer enabled, output pins are set to HighZ mode. 443 | - for nTRST, nRESET a weak pull-up (if available) is enabled. 444 | - LED output pins are enabled and LEDs are turned off. 445 | */ 446 | __STATIC_INLINE void DAP_SETUP (void) { 447 | ; 448 | } 449 | 450 | /** Reset Target Device with custom specific I/O pin or command sequence. 451 | This function allows the optional implementation of a device specific reset sequence. 452 | It is called when the command \ref DAP_ResetTarget and is for example required 453 | when a device needs a time-critical unlock sequence that enables the debug port. 454 | \return 0 = no device specific reset sequence is implemented.\n 455 | 1 = a device specific reset sequence is implemented. 456 | */ 457 | __STATIC_INLINE uint8_t RESET_TARGET (void) { 458 | return (0U); // change to '1' when a device reset sequence is implemented 459 | } 460 | 461 | ///@} 462 | 463 | 464 | #endif /* __DAP_CONFIG_H__ */ 465 | -------------------------------------------------------------------------------- /bsp/default/unique.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tusb.h" 3 | 4 | /* in the absence of the board-specific directory providing a unique ID, we provide a canned one */ 5 | 6 | static uint8_t get_unique_id(uint16_t *desc_str) 7 | { 8 | const char canned[] = "123456"; 9 | uint8_t i; 10 | 11 | for(i=0; i 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #include "picoprobe_config.h" 62 | 63 | #define PROBE_PIN_SWCLK_MASK (1UL << (PROBE_PIN_SWCLK)) 64 | #define PROBE_PIN_SWDIO_MASK (1UL << (PROBE_PIN_SWDIO)) 65 | 66 | /// Processor Clock of the Cortex-M MCU used in the Debug Unit. 67 | /// This value is used to calculate the SWD/JTAG clock speed. 68 | #define CPU_CLOCK 48000000U ///< Specifies the CPU Clock in Hz. 69 | 70 | /// Number of processor cycles for I/O Port write operations. 71 | /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O 72 | /// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors 73 | /// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses 74 | /// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be 75 | /// required. 76 | #define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. 77 | 78 | /// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. 79 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 80 | #define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. 81 | 82 | /// Indicate that JTAG communication mode is available at the Debug Port. 83 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 84 | #define DAP_JTAG 0 ///< JTAG Mode: 1 = available, 0 = not available. 85 | 86 | /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. 87 | /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. 88 | #define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. 89 | 90 | /// Default communication mode on the Debug Access Port. 91 | /// Used for the command \ref DAP_Connect when Port Default mode is selected. 92 | #define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. 93 | 94 | /// Default communication speed on the Debug Access Port for SWD and JTAG mode. 95 | /// Used to initialize the default SWD/JTAG clock frequency. 96 | /// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. 97 | #define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. 98 | 99 | /// Maximum Package Size for Command and Response data. 100 | /// This configuration settings is used to optimize the communication performance with the 101 | /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, 102 | /// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. 103 | #define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes. 104 | 105 | /// Maximum Package Buffers for Command and Response data. 106 | /// This configuration settings is used to optimize the communication performance with the 107 | /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the 108 | /// setting can be reduced (valid range is 1 .. 255). 109 | #define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered. 110 | 111 | /// Indicate that UART Serial Wire Output (SWO) trace is available. 112 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 113 | #define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available. 114 | 115 | /// Maximum SWO UART Baudrate. 116 | #define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz. 117 | 118 | /// Indicate that Manchester Serial Wire Output (SWO) trace is available. 119 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 120 | #define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. 121 | 122 | /// SWO Trace Buffer Size. 123 | #define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). 124 | 125 | /// SWO Streaming Trace. 126 | #define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. 127 | 128 | /// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. 129 | #define TIMESTAMP_CLOCK 0U ///< Timestamp clock in Hz (0 = timestamps not supported). 130 | 131 | /// Debug Unit is connected to fixed Target Device. 132 | /// The Debug Unit may be part of an evaluation board and always connected to a fixed 133 | /// known device. In this case a Device Vendor and Device Name string is stored which 134 | /// may be used by the debugger or IDE to configure device parameters. 135 | #define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; 136 | 137 | #if TARGET_DEVICE_FIXED 138 | #define TARGET_DEVICE_VENDOR "Raspberry Pi" ///< String indicating the Silicon Vendor 139 | #define TARGET_DEVICE_NAME "Pico" ///< String indicating the Target Device 140 | #endif 141 | 142 | #include "DAP.h" 143 | 144 | /** Get Vendor ID string. 145 | \param str Pointer to buffer to store the string. 146 | \return String length. 147 | */ 148 | __STATIC_INLINE uint8_t DAP_GetVendorString (char *str) { 149 | (void)str; 150 | return (0U); 151 | } 152 | 153 | /** Get Product ID string. 154 | \param str Pointer to buffer to store the string. 155 | \return String length. 156 | */ 157 | __STATIC_INLINE uint8_t DAP_GetProductString (char *str) { 158 | (void)str; 159 | return (0U); 160 | } 161 | 162 | /** Get Serial Number string. 163 | \param str Pointer to buffer to store the string. 164 | \return String length. 165 | */ 166 | __STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) { 167 | (void)str; 168 | return (0U); 169 | } 170 | 171 | ///@} 172 | 173 | 174 | //************************************************************************************************** 175 | /** 176 | \defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access 177 | \ingroup DAP_ConfigIO_gr 178 | @{ 179 | 180 | Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode 181 | and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug 182 | interface of a device. The following I/O Pins are provided: 183 | 184 | JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode 185 | ---------------------------- | -------------------- | --------------------------------------------- 186 | TCK: Test Clock | SWCLK: Clock | Output Push/Pull 187 | TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) 188 | TDI: Test Data Input | | Output Push/Pull 189 | TDO: Test Data Output | | Input 190 | nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor 191 | nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor 192 | 193 | 194 | DAP Hardware I/O Pin Access Functions 195 | ------------------------------------- 196 | The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to 197 | these I/O Pins. 198 | 199 | For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. 200 | This functions are provided to achieve faster I/O that is possible with some advanced GPIO 201 | peripherals that can independently write/read a single I/O pin without affecting any other pins 202 | of the same I/O port. The following SWDIO I/O Pin functions are provided: 203 | - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. 204 | - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. 205 | - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. 206 | - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. 207 | */ 208 | 209 | 210 | // Configure DAP I/O pins ------------------------------ 211 | 212 | /** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. 213 | Configures the DAP Hardware I/O pins for JTAG mode: 214 | - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level. 215 | - TDO to input mode. 216 | */ 217 | __STATIC_INLINE void PORT_JTAG_SETUP (void) { 218 | ; 219 | } 220 | 221 | /** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. 222 | Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: 223 | - SWCLK, SWDIO, nRESET to output mode and set to default high level. 224 | - TDI, nTRST to HighZ mode (pins are unused in SWD mode). 225 | */ 226 | __STATIC_INLINE void PORT_SWD_SETUP (void) { 227 | 228 | resets_hw->reset &= ~(RESETS_RESET_IO_BANK0_BITS | RESETS_RESET_PADS_BANK0_BITS); 229 | 230 | /* set to default high level */ 231 | sio_hw->gpio_oe_set = PROBE_PIN_SWCLK_MASK | PROBE_PIN_SWDIO_MASK; 232 | sio_hw->gpio_set = PROBE_PIN_SWCLK_MASK | PROBE_PIN_SWDIO_MASK; 233 | 234 | hw_write_masked(&padsbank0_hw->io[PROBE_PIN_SWCLK], PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); 235 | hw_write_masked(&padsbank0_hw->io[PROBE_PIN_SWDIO], PADS_BANK0_GPIO0_IE_BITS, PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS); 236 | iobank0_hw->io[PROBE_PIN_SWCLK].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; 237 | iobank0_hw->io[PROBE_PIN_SWDIO].ctrl = GPIO_FUNC_SIO << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; 238 | } 239 | 240 | /** Disable JTAG/SWD I/O Pins. 241 | Disables the DAP Hardware I/O pins which configures: 242 | - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. 243 | */ 244 | __STATIC_INLINE void PORT_OFF (void) { 245 | sio_hw->gpio_oe_clr = PROBE_PIN_SWCLK_MASK | PROBE_PIN_SWDIO_MASK; 246 | } 247 | 248 | 249 | // SWCLK/TCK I/O pin ------------------------------------- 250 | 251 | /** SWCLK/TCK I/O pin: Get Input. 252 | \return Current status of the SWCLK/TCK DAP hardware I/O pin. 253 | */ 254 | __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) { 255 | return (0U); 256 | } 257 | 258 | /** SWCLK/TCK I/O pin: Set Output to High. 259 | Set the SWCLK/TCK DAP hardware I/O pin to high level. 260 | */ 261 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) { 262 | sio_hw->gpio_set = PROBE_PIN_SWCLK_MASK; 263 | } 264 | 265 | /** SWCLK/TCK I/O pin: Set Output to Low. 266 | Set the SWCLK/TCK DAP hardware I/O pin to low level. 267 | */ 268 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) { 269 | sio_hw->gpio_clr = PROBE_PIN_SWCLK_MASK; 270 | } 271 | 272 | 273 | // SWDIO/TMS Pin I/O -------------------------------------- 274 | 275 | /** SWDIO/TMS I/O pin: Get Input. 276 | \return Current status of the SWDIO/TMS DAP hardware I/O pin. 277 | */ 278 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) { 279 | return (0U); 280 | } 281 | 282 | /* PIN_SWDIO_TMS_SET and PIN_SWDIO_TMS_CLR are used by SWJ_Sequence */ 283 | 284 | /** SWDIO/TMS I/O pin: Set Output to High. 285 | Set the SWDIO/TMS DAP hardware I/O pin to high level. 286 | */ 287 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) { 288 | sio_hw->gpio_set = PROBE_PIN_SWDIO_MASK; 289 | } 290 | 291 | /** SWDIO/TMS I/O pin: Set Output to Low. 292 | Set the SWDIO/TMS DAP hardware I/O pin to low level. 293 | */ 294 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) { 295 | sio_hw->gpio_clr = PROBE_PIN_SWDIO_MASK; 296 | } 297 | 298 | /** SWDIO I/O pin: Get Input (used in SWD mode only). 299 | \return Current status of the SWDIO DAP hardware I/O pin. 300 | */ 301 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) { 302 | return (sio_hw->gpio_in & PROBE_PIN_SWDIO_MASK) ? 1U : 0U; 303 | } 304 | 305 | /** SWDIO I/O pin: Set Output (used in SWD mode only). 306 | \param bit Output value for the SWDIO DAP hardware I/O pin. 307 | */ 308 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) { 309 | if (bit & 1) 310 | sio_hw->gpio_set = PROBE_PIN_SWDIO_MASK; 311 | else 312 | sio_hw->gpio_clr = PROBE_PIN_SWDIO_MASK; 313 | } 314 | 315 | /** SWDIO I/O pin: Switch to Output mode (used in SWD mode only). 316 | Configure the SWDIO DAP hardware I/O pin to output mode. This function is 317 | called prior \ref PIN_SWDIO_OUT function calls. 318 | */ 319 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) { 320 | sio_hw->gpio_oe_set = PROBE_PIN_SWDIO_MASK; 321 | } 322 | 323 | /** SWDIO I/O pin: Switch to Input mode (used in SWD mode only). 324 | Configure the SWDIO DAP hardware I/O pin to input mode. This function is 325 | called prior \ref PIN_SWDIO_IN function calls. 326 | */ 327 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) { 328 | sio_hw->gpio_oe_clr = PROBE_PIN_SWDIO_MASK; 329 | } 330 | 331 | 332 | // TDI Pin I/O --------------------------------------------- 333 | 334 | /** TDI I/O pin: Get Input. 335 | \return Current status of the TDI DAP hardware I/O pin. 336 | */ 337 | __STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) { 338 | return (0U); 339 | } 340 | 341 | /** TDI I/O pin: Set Output. 342 | \param bit Output value for the TDI DAP hardware I/O pin. 343 | */ 344 | __STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) { 345 | (void)bit; 346 | } 347 | 348 | 349 | // TDO Pin I/O --------------------------------------------- 350 | 351 | /** TDO I/O pin: Get Input. 352 | \return Current status of the TDO DAP hardware I/O pin. 353 | */ 354 | __STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) { 355 | return (0U); 356 | } 357 | 358 | 359 | // nTRST Pin I/O ------------------------------------------- 360 | 361 | /** nTRST I/O pin: Get Input. 362 | \return Current status of the nTRST DAP hardware I/O pin. 363 | */ 364 | __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) { 365 | return (0U); 366 | } 367 | 368 | /** nTRST I/O pin: Set Output. 369 | \param bit JTAG TRST Test Reset pin status: 370 | - 0: issue a JTAG TRST Test Reset. 371 | - 1: release JTAG TRST Test Reset. 372 | */ 373 | __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) { 374 | (void)bit; 375 | } 376 | 377 | // nRESET Pin I/O------------------------------------------ 378 | 379 | /** nRESET I/O pin: Get Input. 380 | \return Current status of the nRESET DAP hardware I/O pin. 381 | */ 382 | __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) { 383 | return (0U); 384 | } 385 | 386 | /** nRESET I/O pin: Set Output. 387 | \param bit target device hardware reset pin status: 388 | - 0: issue a device hardware reset. 389 | - 1: release device hardware reset. 390 | */ 391 | __STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) { 392 | (void)bit; 393 | } 394 | 395 | ///@} 396 | 397 | 398 | //************************************************************************************************** 399 | /** 400 | \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs 401 | \ingroup DAP_ConfigIO_gr 402 | @{ 403 | 404 | CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. 405 | 406 | It is recommended to provide the following LEDs for status indication: 407 | - Connect LED: is active when the DAP hardware is connected to a debugger. 408 | - Running LED: is active when the debugger has put the target device into running state. 409 | */ 410 | 411 | /** Debug Unit: Set status of Connected LED. 412 | \param bit status of the Connect LED. 413 | - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. 414 | - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. 415 | */ 416 | __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) { 417 | (void)bit; 418 | } 419 | 420 | /** Debug Unit: Set status Target Running LED. 421 | \param bit status of the Target Running LED. 422 | - 1: Target Running LED ON: program execution in target started. 423 | - 0: Target Running LED OFF: program execution in target stopped. 424 | */ 425 | __STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) { 426 | (void)bit; 427 | } 428 | 429 | ///@} 430 | 431 | 432 | //************************************************************************************************** 433 | /** 434 | \defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp 435 | \ingroup DAP_ConfigIO_gr 436 | @{ 437 | Access function for Test Domain Timer. 438 | 439 | The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By 440 | default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. 441 | 442 | */ 443 | 444 | /** Get timestamp of Test Domain Timer. 445 | \return Current timestamp value. 446 | */ 447 | __STATIC_INLINE uint32_t TIMESTAMP_GET (void) { 448 | #if TIMESTAMP_CLOCK > 0 449 | return (DWT->CYCCNT); 450 | #else 451 | return 0; 452 | #endif 453 | } 454 | 455 | ///@} 456 | 457 | 458 | //************************************************************************************************** 459 | /** 460 | \defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization 461 | \ingroup DAP_ConfigIO_gr 462 | @{ 463 | 464 | CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. 465 | */ 466 | 467 | /** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). 468 | This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the 469 | Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: 470 | - I/O clock system enabled. 471 | - all I/O pins: input buffer enabled, output pins are set to HighZ mode. 472 | - for nTRST, nRESET a weak pull-up (if available) is enabled. 473 | - LED output pins are enabled and LEDs are turned off. 474 | */ 475 | __STATIC_INLINE void DAP_SETUP (void) { 476 | ; 477 | } 478 | 479 | /** Reset Target Device with custom specific I/O pin or command sequence. 480 | This function allows the optional implementation of a device specific reset sequence. 481 | It is called when the command \ref DAP_ResetTarget and is for example required 482 | when a device needs a time-critical unlock sequence that enables the debug port. 483 | \return 0 = no device specific reset sequence is implemented.\n 484 | 1 = a device specific reset sequence is implemented. 485 | */ 486 | __STATIC_INLINE uint8_t RESET_TARGET (void) { 487 | return (0U); // change to '1' when a device reset sequence is implemented 488 | } 489 | 490 | ///@} 491 | 492 | 493 | #endif /* __DAP_CONFIG_H__ */ 494 | -------------------------------------------------------------------------------- /bsp/rp2040/cdc_uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include 27 | 28 | #include "tusb.h" 29 | 30 | #include "picoprobe_config.h" 31 | 32 | void cdc_uart_init(void) { 33 | gpio_set_function(PICOPROBE_UART_TX, GPIO_FUNC_UART); 34 | gpio_set_function(PICOPROBE_UART_RX, GPIO_FUNC_UART); 35 | uart_init(PICOPROBE_UART_INTERFACE, PICOPROBE_UART_BAUDRATE); 36 | } 37 | 38 | void cdc_task(void) { 39 | uint8_t rx_buf[CFG_TUD_CDC_RX_BUFSIZE]; 40 | uint8_t tx_buf[CFG_TUD_CDC_TX_BUFSIZE]; 41 | 42 | // Consume uart fifo regardless even if not connected 43 | uint rx_len = 0; 44 | while(uart_is_readable(PICOPROBE_UART_INTERFACE) && (rx_len < sizeof(rx_buf))) { 45 | rx_buf[rx_len++] = uart_getc(PICOPROBE_UART_INTERFACE); 46 | } 47 | 48 | if (tud_cdc_connected()) { 49 | // Do we have anything to display on the host's terminal? 50 | if (rx_len) { 51 | for (uint i = 0; i < rx_len; i++) { 52 | tud_cdc_write_char(rx_buf[i]); 53 | } 54 | tud_cdc_write_flush(); 55 | } 56 | 57 | if (tud_cdc_available()) { 58 | // Is there any data from the host for us to tx 59 | uint tx_len = tud_cdc_read(tx_buf, sizeof(tx_buf)); 60 | uart_write_blocking(PICOPROBE_UART_INTERFACE, tx_buf, tx_len); 61 | } 62 | } 63 | } 64 | 65 | void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding) { 66 | picoprobe_info("New baud rate %d\n", line_coding->bit_rate); 67 | uart_init(PICOPROBE_UART_INTERFACE, line_coding->bit_rate); 68 | } 69 | -------------------------------------------------------------------------------- /bsp/rp2040/picoprobe_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Raspberry Pi (Trading) Ltd. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef PICOPROBE_H_ 27 | #define PICOPROBE_H_ 28 | 29 | #if false 30 | #define picoprobe_info(format,args...) printf(format, ## args) 31 | #else 32 | #define picoprobe_info(format,...) ((void)0) 33 | #endif 34 | 35 | 36 | #if false 37 | #define picoprobe_debug(format,args...) printf(format, ## args) 38 | #else 39 | #define picoprobe_debug(format,...) ((void)0) 40 | #endif 41 | 42 | #if false 43 | #define picoprobe_dump(format,args...) printf(format, ## args) 44 | #else 45 | #define picoprobe_dump(format,...) ((void)0) 46 | #endif 47 | 48 | 49 | // PIO config 50 | #define PROBE_SM 0 51 | #define PROBE_PIN_OFFSET 2 52 | #define PROBE_PIN_SWCLK PROBE_PIN_OFFSET + 0 // 2 53 | #define PROBE_PIN_SWDIO PROBE_PIN_OFFSET + 1 // 3 54 | 55 | // UART config 56 | #define PICOPROBE_UART_TX 4 57 | #define PICOPROBE_UART_RX 5 58 | #define PICOPROBE_UART_INTERFACE uart1 59 | #define PICOPROBE_UART_BAUDRATE 115200 60 | 61 | // LED config 62 | #ifndef PICOPROBE_LED 63 | 64 | #ifndef PICO_DEFAULT_LED_PIN 65 | #error PICO_DEFAULT_LED_PIN is not defined, run PICOPROBE_LED= cmake 66 | #elif PICO_DEFAULT_LED_PIN == -1 67 | #error PICO_DEFAULT_LED_PIN is defined as -1, run PICOPROBE_LED= cmake 68 | #else 69 | #define PICOPROBE_LED PICO_DEFAULT_LED_PIN 70 | #endif 71 | 72 | #endif 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /bsp/rp2040/unique.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pico/stdlib.h" 3 | #include "pico/unique_id.h" 4 | #include "tusb.h" 5 | 6 | static uint8_t get_unique_id(uint16_t *desc_str) 7 | { 8 | pico_unique_board_id_t uid; 9 | uint8_t chr_count = 0; 10 | 11 | pico_get_unique_board_id(&uid); 12 | 13 | for (int byte = 0; byte < TU_ARRAY_SIZE(uid.id); byte++) 14 | { 15 | uint8_t tmp = uid.id[byte]; 16 | for (int digit = 0; digit < 2; digit++) 17 | { 18 | desc_str[chr_count++] = "0123456789ABCDEF"[tmp & 0xf]; 19 | tmp >>= 4; 20 | } 21 | } 22 | 23 | return chr_count; 24 | } 25 | 26 | #define PRODUCT_PREFIX "RP2040 " 27 | -------------------------------------------------------------------------------- /bsp/stm32f072disco/DAP_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 Peter Lawrence 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | /* 26 | As written, pins PC6, PC7, PC8 were chosen as SWCLK, SWDIO, and RESETn respectively. 27 | These pins map to LEDs on the STM32F072DISCO, but can be customized as needed. 28 | */ 29 | 30 | #ifndef __DAP_CONFIG_H__ 31 | #define __DAP_CONFIG_H__ 32 | 33 | 34 | //************************************************************************************************** 35 | /** 36 | \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information 37 | \ingroup DAP_ConfigIO_gr 38 | @{ 39 | Provides definitions about the hardware and configuration of the Debug Unit. 40 | 41 | This information includes: 42 | - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. 43 | - Debug Unit Identification strings (Vendor, Product, Serial Number). 44 | - Debug Unit communication packet size. 45 | - Debug Access Port supported modes and settings (JTAG/SWD and SWO). 46 | - Optional information about a connected Target Device (for Evaluation Boards). 47 | */ 48 | 49 | #include "cmsis_compiler.h" 50 | #include "bsp/board.h" 51 | 52 | #include 53 | 54 | /// Processor Clock of the Cortex-M MCU used in the Debug Unit. 55 | /// This value is used to calculate the SWD/JTAG clock speed. 56 | #define CPU_CLOCK 48000000U ///< Specifies the CPU Clock in Hz. 57 | 58 | /// Number of processor cycles for I/O Port write operations. 59 | /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O 60 | /// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors 61 | /// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses 62 | /// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be 63 | /// required. 64 | #define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. 65 | 66 | /// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. 67 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 68 | #define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. 69 | 70 | /// Indicate that JTAG communication mode is available at the Debug Port. 71 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 72 | #define DAP_JTAG 0 ///< JTAG Mode: 1 = available, 0 = not available. 73 | 74 | /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. 75 | /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. 76 | #define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. 77 | 78 | /// Default communication mode on the Debug Access Port. 79 | /// Used for the command \ref DAP_Connect when Port Default mode is selected. 80 | #define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. 81 | 82 | /// Default communication speed on the Debug Access Port for SWD and JTAG mode. 83 | /// Used to initialize the default SWD/JTAG clock frequency. 84 | /// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. 85 | #define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. 86 | 87 | /// Maximum Package Size for Command and Response data. 88 | /// This configuration settings is used to optimize the communication performance with the 89 | /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, 90 | /// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. 91 | #define DAP_PACKET_SIZE CFG_TUD_HID_EP_BUFSIZE ///< Specifies Packet Size in bytes. 92 | 93 | /// Maximum Package Buffers for Command and Response data. 94 | /// This configuration settings is used to optimize the communication performance with the 95 | /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the 96 | /// setting can be reduced (valid range is 1 .. 255). 97 | #define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered. 98 | 99 | /// Indicate that UART Serial Wire Output (SWO) trace is available. 100 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 101 | #define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available. 102 | 103 | /// Maximum SWO UART Baudrate. 104 | #define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz. 105 | 106 | /// Indicate that Manchester Serial Wire Output (SWO) trace is available. 107 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 108 | #define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. 109 | 110 | /// SWO Trace Buffer Size. 111 | #define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). 112 | 113 | /// SWO Streaming Trace. 114 | #define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. 115 | 116 | /// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. 117 | #define TIMESTAMP_CLOCK 0U ///< Timestamp clock in Hz (0 = timestamps not supported). 118 | 119 | /// Debug Unit is connected to fixed Target Device. 120 | /// The Debug Unit may be part of an evaluation board and always connected to a fixed 121 | /// known device. In this case a Device Vendor and Device Name string is stored which 122 | /// may be used by the debugger or IDE to configure device parameters. 123 | #define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; 124 | 125 | #if TARGET_DEVICE_FIXED 126 | #define TARGET_DEVICE_VENDOR "ARM" ///< String indicating the Silicon Vendor 127 | #define TARGET_DEVICE_NAME "Cortex-M4" ///< String indicating the Target Device 128 | #endif 129 | 130 | #include "DAP.h" 131 | 132 | /** Get Vendor ID string. 133 | \param str Pointer to buffer to store the string. 134 | \return String length. 135 | */ 136 | __STATIC_INLINE uint8_t DAP_GetVendorString (char *str) { 137 | (void)str; 138 | return (0U); 139 | } 140 | 141 | /** Get Product ID string. 142 | \param str Pointer to buffer to store the string. 143 | \return String length. 144 | */ 145 | __STATIC_INLINE uint8_t DAP_GetProductString (char *str) { 146 | (void)str; 147 | return (0U); 148 | } 149 | 150 | /** Get Serial Number string. 151 | \param str Pointer to buffer to store the string. 152 | \return String length. 153 | */ 154 | __STATIC_INLINE uint8_t DAP_GetSerNumString (char *str) { 155 | (void)str; 156 | return (0U); 157 | } 158 | 159 | ///@} 160 | 161 | /* these macros are used by the API functions further below */ 162 | 163 | #define CLK_PIN 6 164 | #define DATA_PIN 7 165 | #define RESET_PIN 8 166 | 167 | #define CLK_LOW { GPIOC->BSRR = (1UL << CLK_PIN) << 16; } 168 | #define CLK_HIGH { GPIOC->BSRR = (1UL << CLK_PIN) << 0; } 169 | #define CLK_ENABLE { GPIOC->MODER = ( (GPIOC->MODER & ~(0x3 << (CLK_PIN * 2))) | (0x1 << (CLK_PIN * 2)) ); } 170 | #define CLK_HIZ { GPIOC->MODER = ( (GPIOC->MODER & ~(0x3 << (CLK_PIN * 2))) ); } 171 | 172 | #define DATA_LOW { GPIOC->BSRR = (1UL << DATA_PIN) << 16; } 173 | #define DATA_HIGH { GPIOC->BSRR = (1UL << DATA_PIN) << 0; } 174 | #define DATA_ENABLE { GPIOC->MODER = ( (GPIOC->MODER & ~(0x3 << (DATA_PIN * 2))) | (0x1 << (DATA_PIN * 2)) ); } 175 | #define DATA_HIZ { GPIOC->MODER = ( (GPIOC->MODER & ~(0x3 << (DATA_PIN * 2))) ); } 176 | 177 | #define RESET_LOW { GPIOC->BSRR = (1UL << RESET_PIN) << 16; } 178 | #define RESET_HIGH { GPIOC->BSRR = (1UL << RESET_PIN) << 0; } 179 | #define RESET_ENABLE { GPIOC->MODER = ( (GPIOC->MODER & ~(0x3 << (RESET_PIN * 2))) | (0x1 << (RESET_PIN * 2)) ); } 180 | #define RESET_HIZ { GPIOC->MODER = ( (GPIOC->MODER & ~(0x3 << (RESET_PIN * 2))) ); } 181 | 182 | #define SWDIO_INIT { __HAL_RCC_GPIOC_CLK_ENABLE(); } 183 | 184 | #define DATA_READ (GPIOC->IDR & (1UL << DATA_PIN)) 185 | #define CLK_READ (GPIOC->IDR & (1UL << CLK_PIN)) 186 | #define RESET_READ (GPIOC->IDR & (1UL << RESET_PIN)) 187 | 188 | //************************************************************************************************** 189 | /** 190 | \defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access 191 | \ingroup DAP_ConfigIO_gr 192 | @{ 193 | 194 | Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode 195 | and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug 196 | interface of a device. The following I/O Pins are provided: 197 | 198 | JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode 199 | ---------------------------- | -------------------- | --------------------------------------------- 200 | TCK: Test Clock | SWCLK: Clock | Output Push/Pull 201 | TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) 202 | TDI: Test Data Input | | Output Push/Pull 203 | TDO: Test Data Output | | Input 204 | nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor 205 | nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor 206 | 207 | 208 | DAP Hardware I/O Pin Access Functions 209 | ------------------------------------- 210 | The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to 211 | these I/O Pins. 212 | 213 | For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. 214 | This functions are provided to achieve faster I/O that is possible with some advanced GPIO 215 | peripherals that can independently write/read a single I/O pin without affecting any other pins 216 | of the same I/O port. The following SWDIO I/O Pin functions are provided: 217 | - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. 218 | - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. 219 | - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. 220 | - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. 221 | */ 222 | 223 | // Configure DAP I/O pins ------------------------------ 224 | 225 | /** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. 226 | Configures the DAP Hardware I/O pins for JTAG mode: 227 | - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level. 228 | - TDO to input mode. 229 | */ 230 | __STATIC_INLINE void PORT_JTAG_SETUP (void) { 231 | ; 232 | } 233 | 234 | /** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. 235 | Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: 236 | - SWCLK, SWDIO, nRESET to output mode and set to default high level. 237 | - TDI, nTRST to HighZ mode (pins are unused in SWD mode). 238 | */ 239 | __STATIC_INLINE void PORT_SWD_SETUP (void) { 240 | CLK_ENABLE; 241 | DATA_ENABLE; 242 | SWDIO_INIT; 243 | CLK_HIGH; DATA_HIGH; 244 | } 245 | 246 | /** Disable JTAG/SWD I/O Pins. 247 | Disables the DAP Hardware I/O pins which configures: 248 | - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. 249 | */ 250 | __STATIC_INLINE void PORT_OFF (void) { 251 | CLK_HIZ; 252 | DATA_HIZ; 253 | RESET_HIZ; 254 | } 255 | 256 | // SWCLK/TCK I/O pin ------------------------------------- 257 | 258 | /** SWCLK/TCK I/O pin: Get Input. 259 | \return Current status of the SWCLK/TCK DAP hardware I/O pin. 260 | */ 261 | __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN (void) { 262 | return (CLK_READ) ? 1 : 0; 263 | } 264 | 265 | /** SWCLK/TCK I/O pin: Set Output to High. 266 | Set the SWCLK/TCK DAP hardware I/O pin to high level. 267 | */ 268 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET (void) { 269 | CLK_HIGH; 270 | } 271 | 272 | /** SWCLK/TCK I/O pin: Set Output to Low. 273 | Set the SWCLK/TCK DAP hardware I/O pin to low level. 274 | */ 275 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR (void) { 276 | CLK_LOW; 277 | } 278 | 279 | 280 | // SWDIO/TMS Pin I/O -------------------------------------- 281 | 282 | /** SWDIO/TMS I/O pin: Get Input. 283 | \return Current status of the SWDIO/TMS DAP hardware I/O pin. 284 | */ 285 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN (void) { 286 | return (DATA_READ) ? 1 : 0; 287 | } 288 | 289 | /** SWDIO/TMS I/O pin: Set Output to High. 290 | Set the SWDIO/TMS DAP hardware I/O pin to high level. 291 | */ 292 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET (void) { 293 | DATA_HIGH; 294 | } 295 | 296 | /** SWDIO/TMS I/O pin: Set Output to Low. 297 | Set the SWDIO/TMS DAP hardware I/O pin to low level. 298 | */ 299 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR (void) { 300 | DATA_LOW; 301 | } 302 | 303 | /** SWDIO I/O pin: Get Input (used in SWD mode only). 304 | \return Current status of the SWDIO DAP hardware I/O pin. 305 | */ 306 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN (void) { 307 | return (DATA_READ) ? 1 : 0; 308 | } 309 | 310 | /** SWDIO I/O pin: Set Output (used in SWD mode only). 311 | \param bit Output value for the SWDIO DAP hardware I/O pin. 312 | */ 313 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT (uint32_t bit) { 314 | if (bit & 1) { DATA_HIGH; } else { DATA_LOW; } 315 | } 316 | 317 | /** SWDIO I/O pin: Switch to Output mode (used in SWD mode only). 318 | Configure the SWDIO DAP hardware I/O pin to output mode. This function is 319 | called prior \ref PIN_SWDIO_OUT function calls. 320 | */ 321 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE (void) { 322 | DATA_ENABLE; 323 | } 324 | 325 | /** SWDIO I/O pin: Switch to Input mode (used in SWD mode only). 326 | Configure the SWDIO DAP hardware I/O pin to input mode. This function is 327 | called prior \ref PIN_SWDIO_IN function calls. 328 | */ 329 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE (void) { 330 | DATA_HIZ; 331 | } 332 | 333 | 334 | // TDI Pin I/O --------------------------------------------- 335 | 336 | /** TDI I/O pin: Get Input. 337 | \return Current status of the TDI DAP hardware I/O pin. 338 | */ 339 | __STATIC_FORCEINLINE uint32_t PIN_TDI_IN (void) { 340 | return (0U); 341 | } 342 | 343 | /** TDI I/O pin: Set Output. 344 | \param bit Output value for the TDI DAP hardware I/O pin. 345 | */ 346 | __STATIC_FORCEINLINE void PIN_TDI_OUT (uint32_t bit) { 347 | ; 348 | } 349 | 350 | 351 | // TDO Pin I/O --------------------------------------------- 352 | 353 | /** TDO I/O pin: Get Input. 354 | \return Current status of the TDO DAP hardware I/O pin. 355 | */ 356 | __STATIC_FORCEINLINE uint32_t PIN_TDO_IN (void) { 357 | return (0U); 358 | } 359 | 360 | 361 | // nTRST Pin I/O ------------------------------------------- 362 | 363 | /** nTRST I/O pin: Get Input. 364 | \return Current status of the nTRST DAP hardware I/O pin. 365 | */ 366 | __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN (void) { 367 | return (0U); 368 | } 369 | 370 | /** nTRST I/O pin: Set Output. 371 | \param bit JTAG TRST Test Reset pin status: 372 | - 0: issue a JTAG TRST Test Reset. 373 | - 1: release JTAG TRST Test Reset. 374 | */ 375 | __STATIC_FORCEINLINE void PIN_nTRST_OUT (uint32_t bit) { 376 | (void)bit; 377 | } 378 | 379 | // nRESET Pin I/O------------------------------------------ 380 | 381 | /** nRESET I/O pin: Get Input. 382 | \return Current status of the nRESET DAP hardware I/O pin. 383 | */ 384 | __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN (void) { 385 | return (RESET_READ) ? 1 : 0; 386 | } 387 | 388 | /** nRESET I/O pin: Set Output. 389 | \param bit target device hardware reset pin status: 390 | - 0: issue a device hardware reset. 391 | - 1: release device hardware reset. 392 | */ 393 | __STATIC_FORCEINLINE void PIN_nRESET_OUT (uint32_t bit) { 394 | if (bit & 1) { RESET_HIGH; } else { RESET_LOW; } 395 | } 396 | 397 | ///@} 398 | 399 | 400 | //************************************************************************************************** 401 | /** 402 | \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs 403 | \ingroup DAP_ConfigIO_gr 404 | @{ 405 | 406 | CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. 407 | 408 | It is recommended to provide the following LEDs for status indication: 409 | - Connect LED: is active when the DAP hardware is connected to a debugger. 410 | - Running LED: is active when the debugger has put the target device into running state. 411 | */ 412 | 413 | /** Debug Unit: Set status of Connected LED. 414 | \param bit status of the Connect LED. 415 | - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. 416 | - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. 417 | */ 418 | __STATIC_INLINE void LED_CONNECTED_OUT (uint32_t bit) { 419 | (void)bit; 420 | } 421 | 422 | /** Debug Unit: Set status Target Running LED. 423 | \param bit status of the Target Running LED. 424 | - 1: Target Running LED ON: program execution in target started. 425 | - 0: Target Running LED OFF: program execution in target stopped. 426 | */ 427 | __STATIC_INLINE void LED_RUNNING_OUT (uint32_t bit) { 428 | (void)bit; 429 | } 430 | 431 | ///@} 432 | 433 | 434 | //************************************************************************************************** 435 | /** 436 | \defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp 437 | \ingroup DAP_ConfigIO_gr 438 | @{ 439 | Access function for Test Domain Timer. 440 | 441 | The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By 442 | default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. 443 | 444 | */ 445 | 446 | /** Get timestamp of Test Domain Timer. 447 | \return Current timestamp value. 448 | */ 449 | __STATIC_INLINE uint32_t TIMESTAMP_GET (void) { 450 | #if TIMESTAMP_CLOCK > 0 451 | return (DWT->CYCCNT); 452 | #else 453 | return 0; 454 | #endif 455 | } 456 | 457 | ///@} 458 | 459 | 460 | //************************************************************************************************** 461 | /** 462 | \defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization 463 | \ingroup DAP_ConfigIO_gr 464 | @{ 465 | 466 | CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. 467 | */ 468 | 469 | /** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). 470 | This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the 471 | Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: 472 | - I/O clock system enabled. 473 | - all I/O pins: input buffer enabled, output pins are set to HighZ mode. 474 | - for nTRST, nRESET a weak pull-up (if available) is enabled. 475 | - LED output pins are enabled and LEDs are turned off. 476 | */ 477 | __STATIC_INLINE void DAP_SETUP (void) { 478 | ; 479 | } 480 | 481 | /** Reset Target Device with custom specific I/O pin or command sequence. 482 | This function allows the optional implementation of a device specific reset sequence. 483 | It is called when the command \ref DAP_ResetTarget and is for example required 484 | when a device needs a time-critical unlock sequence that enables the debug port. 485 | \return 0 = no device specific reset sequence is implemented.\n 486 | 1 = a device specific reset sequence is implemented. 487 | */ 488 | __STATIC_INLINE uint8_t RESET_TARGET (void) { 489 | return (0U); // change to '1' when a device reset sequence is implemented 490 | } 491 | 492 | ///@} 493 | 494 | 495 | #endif /* __DAP_CONFIG_H__ */ 496 | -------------------------------------------------------------------------------- /bsp/stm32f072disco/cdc_uart.c: -------------------------------------------------------------------------------- 1 | void cdc_uart_init(void) 2 | { 3 | } 4 | 5 | void cdc_task(void) 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /bsp/stm32f072disco/unique.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tusb.h" 3 | 4 | static uint8_t get_unique_id(uint16_t *desc_str) 5 | { 6 | const uint32_t *idpnt = (uint32_t*)(0x1FFFF7AC); /*DEVICE_ID1*/ 7 | uint32_t tmp = 0; 8 | uint8_t chr_count = 0; 9 | 10 | for (int digit = 0; digit < 24; digit++) 11 | { 12 | if (0 == (digit & 7)) tmp = *idpnt++; 13 | desc_str[chr_count++] = "0123456789ABCDEF"[tmp & 0xf]; 14 | tmp >>= 4; 15 | } 16 | 17 | return chr_count; 18 | } 19 | 20 | #define PRODUCT_PREFIX "STM32F072 " 21 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "bsp/board.h" 31 | #include "tusb.h" 32 | 33 | #include "DAP_config.h" /* ARM code *assumes* this is included prior to DAP.h */ 34 | #include "DAP.h" 35 | 36 | void cdc_uart_init(void); 37 | void cdc_task(void); 38 | 39 | int main(void) 40 | { 41 | board_init(); 42 | cdc_uart_init(); 43 | DAP_Setup(); 44 | 45 | tusb_init(); 46 | 47 | while (1) 48 | { 49 | tud_task(); // tinyusb device task 50 | cdc_task(); 51 | } 52 | 53 | return 0; 54 | } 55 | 56 | //--------------------------------------------------------------------+ 57 | // USB HID 58 | //--------------------------------------------------------------------+ 59 | 60 | // Invoked when received GET_REPORT control request 61 | // Application must fill buffer report's content and return its length. 62 | // Return zero will cause the stack to STALL request 63 | uint16_t tud_hid_get_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) 64 | { 65 | // TODO not Implemented 66 | (void) itf; 67 | (void) report_id; 68 | (void) report_type; 69 | (void) buffer; 70 | (void) reqlen; 71 | 72 | return 0; 73 | } 74 | 75 | void tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const* RxDataBuffer, uint16_t bufsize) 76 | { 77 | static uint8_t TxDataBuffer[CFG_TUD_HID_EP_BUFSIZE]; 78 | 79 | // This doesn't use multiple report and report ID 80 | (void) itf; 81 | (void) report_id; 82 | (void) report_type; 83 | 84 | DAP_ProcessCommand(RxDataBuffer, TxDataBuffer); 85 | 86 | tud_hid_report(0, TxDataBuffer, sizeof(TxDataBuffer)); 87 | } 88 | -------------------------------------------------------------------------------- /tusb_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #ifndef _TUSB_CONFIG_H_ 27 | #define _TUSB_CONFIG_H_ 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | //-------------------------------------------------------------------- 34 | // COMMON CONFIGURATION 35 | //-------------------------------------------------------------------- 36 | 37 | // defined by board.mk 38 | #ifndef CFG_TUSB_MCU 39 | #error CFG_TUSB_MCU must be defined 40 | #endif 41 | 42 | // RHPort number used for device can be defined by board.mk, default to port 0 43 | #ifndef BOARD_DEVICE_RHPORT_NUM 44 | #define BOARD_DEVICE_RHPORT_NUM 0 45 | #endif 46 | 47 | // RHPort max operational speed can defined by board.mk 48 | // Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed 49 | #ifndef BOARD_DEVICE_RHPORT_SPEED 50 | #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \ 51 | CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56) 52 | #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED 53 | #else 54 | #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED 55 | #endif 56 | #endif 57 | 58 | // Device mode with rhport and speed defined by board.mk 59 | #if BOARD_DEVICE_RHPORT_NUM == 0 60 | #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) 61 | #elif BOARD_DEVICE_RHPORT_NUM == 1 62 | #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED) 63 | #else 64 | #error "Incorrect RHPort configuration" 65 | #endif 66 | 67 | #ifndef CFG_TUSB_OS 68 | #define CFG_TUSB_OS OPT_OS_NONE 69 | #endif 70 | 71 | // CFG_TUSB_DEBUG is defined by compiler in DEBUG build 72 | // #define CFG_TUSB_DEBUG 0 73 | 74 | /* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. 75 | * Tinyusb use follows macros to declare transferring memory so that they can be put 76 | * into those specific section. 77 | * e.g 78 | * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) 79 | * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) 80 | */ 81 | #ifndef CFG_TUSB_MEM_SECTION 82 | #define CFG_TUSB_MEM_SECTION 83 | #endif 84 | 85 | #ifndef CFG_TUSB_MEM_ALIGN 86 | #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) 87 | #endif 88 | 89 | //-------------------------------------------------------------------- 90 | // DEVICE CONFIGURATION 91 | //-------------------------------------------------------------------- 92 | 93 | #ifndef CFG_TUD_ENDPOINT0_SIZE 94 | #define CFG_TUD_ENDPOINT0_SIZE 64 95 | #endif 96 | 97 | //------------- CLASS -------------// 98 | #define CFG_TUD_CDC 1 99 | #define CFG_TUD_MSC 0 100 | #define CFG_TUD_HID 1 101 | #define CFG_TUD_MIDI 0 102 | #define CFG_TUD_VENDOR 0 103 | #define CFG_TUD_ECM_RNDIS 0 104 | 105 | #define CFG_TUD_HID_EP_BUFSIZE 64 106 | 107 | // CDC FIFO size of TX and RX 108 | #define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) 109 | #define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) 110 | 111 | #ifdef __cplusplus 112 | } 113 | #endif 114 | 115 | #endif /* _TUSB_CONFIG_H_ */ 116 | -------------------------------------------------------------------------------- /usb_descriptors.c: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #include "tusb.h" 27 | #include "unique.h" 28 | 29 | /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. 30 | * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. 31 | * 32 | * Auto ProductID layout's Bitmap: 33 | * [MSB] HID | MSC | CDC [LSB] 34 | */ 35 | #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) 36 | #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ 37 | _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) 38 | 39 | // String Descriptor Index 40 | enum 41 | { 42 | STRID_LANGID = 0, 43 | STRID_MANUFACTURER, 44 | STRID_PRODUCT, 45 | STRID_SERIAL, 46 | }; 47 | 48 | //--------------------------------------------------------------------+ 49 | // Device Descriptors 50 | //--------------------------------------------------------------------+ 51 | tusb_desc_device_t const desc_device = 52 | { 53 | .bLength = sizeof(tusb_desc_device_t), 54 | .bDescriptorType = TUSB_DESC_DEVICE, 55 | .bcdUSB = 0x0200, 56 | .bDeviceClass = 0x00, 57 | .bDeviceSubClass = 0x00, 58 | .bDeviceProtocol = 0x00, 59 | .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, 60 | 61 | .idVendor = 0xCafe, 62 | .idProduct = USB_PID, 63 | .bcdDevice = 0x0102, 64 | 65 | .iManufacturer = STRID_MANUFACTURER, 66 | .iProduct = STRID_PRODUCT, 67 | .iSerialNumber = STRID_SERIAL, 68 | 69 | .bNumConfigurations = 0x01 70 | }; 71 | 72 | // Invoked when received GET DEVICE DESCRIPTOR 73 | // Application return pointer to descriptor 74 | uint8_t const * tud_descriptor_device_cb(void) 75 | { 76 | return (uint8_t const *) &desc_device; 77 | } 78 | 79 | //--------------------------------------------------------------------+ 80 | // HID Report Descriptor 81 | //--------------------------------------------------------------------+ 82 | 83 | static uint8_t const desc_hid_report[] = 84 | { 85 | TUD_HID_REPORT_DESC_GENERIC_INOUT(CFG_TUD_HID_EP_BUFSIZE) 86 | }; 87 | 88 | // Invoked when received GET HID REPORT DESCRIPTOR 89 | // Application return pointer to descriptor 90 | // Descriptor contents must exist long enough for transfer to complete 91 | uint8_t const * tud_hid_descriptor_report_cb(uint8_t itf) 92 | { 93 | (void) itf; 94 | return desc_hid_report; 95 | } 96 | 97 | //--------------------------------------------------------------------+ 98 | // Configuration Descriptor 99 | //--------------------------------------------------------------------+ 100 | 101 | enum 102 | { 103 | ITF_NUM_HID, 104 | ITF_NUM_CDC_COM, 105 | ITF_NUM_CDC_DATA, 106 | ITF_NUM_TOTAL 107 | }; 108 | 109 | #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_HID_INOUT_DESC_LEN) 110 | 111 | #define EPNUM_HID 0x01 112 | #define EPNUM_CDC_NOTIF 0x83 113 | #define EPNUM_CDC_OUT 0x02 114 | #define EPNUM_CDC_IN 0x82 115 | 116 | uint8_t const desc_configuration[] = 117 | { 118 | // Config number, interface count, string index, total length, attribute, power in mA 119 | TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), 120 | 121 | // Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval 122 | TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID, 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), EPNUM_HID, 0x80 | EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 1), 123 | 124 | // Interface number, string index, EP notification address and size, EP data address (out, in) and size. 125 | TUD_CDC_DESCRIPTOR(ITF_NUM_CDC_COM, 0, EPNUM_CDC_NOTIF, 64, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), 126 | }; 127 | 128 | // Invoked when received GET CONFIGURATION DESCRIPTOR 129 | // Application return pointer to descriptor 130 | // Descriptor contents must exist long enough for transfer to complete 131 | uint8_t const * tud_descriptor_configuration_cb(uint8_t index) 132 | { 133 | (void) index; // for multiple configurations 134 | return desc_configuration; 135 | } 136 | 137 | //--------------------------------------------------------------------+ 138 | // String Descriptors 139 | //--------------------------------------------------------------------+ 140 | 141 | // array of pointer to string descriptors 142 | char const* string_desc_arr [] = 143 | { 144 | [STRID_LANGID] = (const char[]) { 0x09, 0x04 }, // supported language is English (0x0409) 145 | [STRID_MANUFACTURER] = "TinyUSB", // Manufacturer 146 | [STRID_PRODUCT] = PRODUCT_PREFIX "CMSIS-DAP", // Product 147 | }; 148 | static uint16_t _desc_str[32]; 149 | 150 | // Invoked when received GET STRING DESCRIPTOR request 151 | // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete 152 | uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) 153 | { 154 | (void) langid; 155 | 156 | uint8_t chr_count = 0; 157 | 158 | if (STRID_LANGID == index) 159 | { 160 | memcpy(&_desc_str[1], string_desc_arr[STRID_LANGID], 2); 161 | chr_count = 1; 162 | } else if (STRID_SERIAL == index) 163 | { 164 | chr_count = get_unique_id(_desc_str + 1); 165 | } else 166 | { 167 | // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. 168 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors 169 | 170 | if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; 171 | 172 | const char* str = string_desc_arr[index]; 173 | 174 | // Cap at max char 175 | chr_count = TU_MIN(strlen(str), 31); 176 | 177 | // Convert ASCII string into UTF-16 178 | for(uint8_t i=0; i