├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── components ├── DAP │ ├── CMakeLists.txt │ ├── config │ │ └── DAP_config.h │ ├── include │ │ ├── DAP.h │ │ ├── cmsis_compiler.h │ │ ├── dap_utility.h │ │ ├── gpio_op.h │ │ ├── spi_op.h │ │ ├── spi_switch.h │ │ └── uart_modify.h │ └── source │ │ ├── DAP.c │ │ ├── DAP_vendor.c │ │ ├── JTAG_DP.c │ │ ├── SWO.c │ │ ├── SW_DP.c │ │ ├── dap_utility.c │ │ ├── spi_op.c │ │ └── spi_switch.c ├── README.md └── USBIP │ ├── CMakeLists.txt │ ├── MSOS20_descriptor.c │ ├── MSOS20_descriptor.h │ ├── USBIP_defs.h │ ├── USB_defs.h │ ├── USB_descriptor.c │ ├── USB_descriptor.h │ ├── USB_handle.c │ └── USB_handle.h ├── main ├── CMakeLists.txt ├── dap_configuration.h ├── dap_handle.c ├── dap_handle.h ├── main.c ├── my_task.c ├── tcp_server.c ├── tcp_server.h ├── usbip_server.c ├── usbip_server.h ├── wifi_configuration.h ├── wifi_connect.c └── wifi_connect.h └── sdkconfig /.gitignore: -------------------------------------------------------------------------------- 1 | .history/ 2 | .vscode/ 3 | build/ 4 | main/my_task.c 5 | tmp/ 6 | sdkconfig.old 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | 7 | project(esp32_dap) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 windowsair 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/DAP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp_ringbuf/include/ $ENV{IDF_PATH}/components/soc/soc/") 2 | set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c ./source/dap_utility.c ./source/spi_switch.c ./source/spi_op.c") 3 | 4 | 5 | 6 | register_component() -------------------------------------------------------------------------------- /components/DAP/config/DAP_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Configuration 24 | * Title: DAP_config.h CMSIS-DAP Configuration File (Template) 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | /** 29 | * @file DAP_config.h 30 | * @author windowsair 31 | * @brief Adaptation of GPIO and SPI pin 32 | * @change: 2021-2-10 Support GPIO and SPI 33 | * @version 0.1 34 | * @date 2021-2-10 35 | * 36 | * @copyright Copyright (c) 2021 37 | * 38 | */ 39 | 40 | 41 | #ifndef __DAP_CONFIG_H__ 42 | #define __DAP_CONFIG_H__ 43 | 44 | #include 45 | #include 46 | 47 | #include "components/DAP/include/cmsis_compiler.h" 48 | #include "components/DAP/include/gpio_op.h" 49 | #include "components/DAP/include/spi_switch.h" 50 | 51 | #include "main/dap_configuration.h" 52 | 53 | //************************************************************************************************** 54 | /** 55 | \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information 56 | \ingroup DAP_ConfigIO_gr 57 | @{ 58 | Provides definitions about the hardware and configuration of the Debug Unit. 59 | 60 | This information includes: 61 | - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. 62 | - Debug Unit Identification strings (Vendor, Product, Serial Number). 63 | - Debug Unit communication packet size. 64 | - Debug Access Port supported modes and settings (JTAG/SWD and SWO). 65 | - Optional information about a connected Target Device (for Evaluation Boards). 66 | */ 67 | 68 | //#ifdef _RTE_ 69 | //#include "RTE_Components.h" 70 | //#include CMSIS_device_header 71 | //#else 72 | //#include "device.h" // Debug Unit Cortex-M Processor Header File 73 | //#endif 74 | 75 | /// Processor Clock of the Cortex-M MCU used in the Debug Unit. 76 | /// This value is used to calculate the SWD/JTAG clock speed. 77 | #define CPU_CLOCK 240000000 ///< Specifies the CPU Clock in Hz. 78 | // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<240MHz 79 | 80 | 81 | //#define MAX_USER_CLOCK 16000000 ///< Specifies the max Debug Clock in Hz. 82 | 83 | /// Number of processor cycles for I/O Port write operations. 84 | /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O 85 | /// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors 86 | /// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses 87 | /// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be 88 | /// required. 89 | #define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. 90 | 91 | /// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. 92 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 93 | #define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. 94 | 95 | /// Indicate that JTAG communication mode is available at the Debug Port. 96 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 97 | #define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. 98 | 99 | /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. 100 | /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. 101 | #define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. 102 | 103 | /// Default communication mode on the Debug Access Port. 104 | /// Used for the command \ref DAP_Connect when Port Default mode is selected. 105 | #define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. 106 | 107 | /// Default communication speed on the Debug Access Port for SWD and JTAG mode. 108 | /// Used to initialize the default SWD/JTAG clock frequency. 109 | /// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. 110 | #define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. 111 | // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<1MHz 112 | 113 | /// Maximum Package Buffers for Command and Response data. 114 | /// This configuration settings is used to optimize the communication performance with the 115 | /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the 116 | /// setting can be reduced (valid range is 1 .. 255). 117 | #define DAP_PACKET_COUNT 255 ///< Specifies number of packets buffered. 118 | 119 | /// Indicate that UART Serial Wire Output (SWO) trace is available. 120 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 121 | #define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available. 122 | 123 | /// Maximum SWO UART Baudrate. 124 | #define SWO_UART_MAX_BAUDRATE (115200U * 40U) ///< SWO UART Maximum Baudrate in Hz. 125 | // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz 126 | //// TODO: uncertain value 127 | 128 | /// Indicate that Manchester Serial Wire Output (SWO) trace is available. 129 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 130 | #define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. 131 | 132 | /// SWO Trace Buffer Size. 133 | #define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). 134 | 135 | /// SWO Streaming Trace. 136 | #define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. 137 | 138 | /// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. 139 | #define TIMESTAMP_CLOCK 5000000U ///< Timestamp clock in Hz (0 = timestamps not supported). 140 | // <<<<<<<<<<<<<<<<<<<<<5MHz 141 | 142 | /// Debug Unit is connected to fixed Target Device. 143 | /// The Debug Unit may be part of an evaluation board and always connected to a fixed 144 | /// known device. In this case a Device Vendor and Device Name string is stored which 145 | /// may be used by the debugger or IDE to configure device parameters. 146 | #define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; 147 | 148 | #if TARGET_DEVICE_FIXED 149 | #define TARGET_DEVICE_VENDOR "ARM" ///< String indicating the Silicon Vendor 150 | #define TARGET_DEVICE_NAME "Cortex-M4" ///< String indicating the Target Device 151 | #endif 152 | 153 | /** 154 | * @brief Get Vendor ID string. 155 | * 156 | * @param str Pointer to buffer to store the string. 157 | * @return String length. 158 | */ 159 | __STATIC_INLINE uint8_t DAP_GetVendorString(char *str) 160 | { 161 | ////TODO: fill this 162 | // In fact, Keil can get the corresponding information through USB 163 | // without filling in this information. 164 | // (void)str; 165 | strcpy(str, "windowsair"); 166 | return (sizeof("windowsair")); 167 | } 168 | 169 | /** 170 | * @brief Get Product ID string. 171 | * 172 | * @param str Pointer to buffer to store the string. 173 | * @return String length. 174 | */ 175 | __STATIC_INLINE uint8_t DAP_GetProductString(char *str) 176 | { 177 | //(void)str; 178 | strcpy(str, "CMSIS-DAP v2"); 179 | return (sizeof("CMSIS-DAP v2")); 180 | } 181 | 182 | /** 183 | * @brief Get Serial Number string. 184 | * 185 | * @param str Pointer to buffer to store the string. 186 | * @return String length. 187 | */ 188 | __STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) 189 | { 190 | strcpy(str, "1234"); 191 | return (sizeof("1234")); 192 | } 193 | 194 | ///@} 195 | 196 | 197 | // Note: DO NOT modify these pins: PIN_SWDIO PIN_SWDIO_MOSI PIN_SWCLK 198 | // Modify the following pins carefully: PIN_TDO 199 | #define PIN_SWDIO 12 // SPI MISO 200 | #define PIN_SWDIO_MOSI 13 // SPI MOSI 201 | #define PIN_SWCLK 14 202 | #define PIN_TDO 19 // device TDO -> Host Data Input ~~~(use RTC pin 16)~~~ 203 | #define PIN_TDI 18 204 | #define PIN_nTRST 25 // optional 205 | #define PIN_nRESET 26 206 | // LED_BUILTIN 207 | #define PIN_LED_CONNECTED 25 208 | // LED_BUILTIN 209 | #define PIN_LED_RUNNING 26 210 | 211 | //************************************************************************************************** 212 | /** 213 | \defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access 214 | \ingroup DAP_ConfigIO_gr 215 | @{ 216 | 217 | Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode 218 | and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug 219 | interface of a device. The following I/O Pins are provided: 220 | 221 | JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode 222 | ---------------------------- | -------------------- | --------------------------------------------- 223 | TCK: Test Clock | SWCLK: Clock | Output Push/Pull 224 | TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) 225 | TDI: Test Data Input | | Output Push/Pull 226 | TDO: Test Data Output | | Input 227 | nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor 228 | nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor 229 | 230 | 231 | DAP Hardware I/O Pin Access Functions 232 | ------------------------------------- 233 | The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to 234 | these I/O Pins. 235 | 236 | For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. 237 | This functions are provided to achieve faster I/O that is possible with some advanced GPIO 238 | peripherals that can independently write/read a single I/O pin without affecting any other pins 239 | of the same I/O port. The following SWDIO I/O Pin functions are provided: 240 | - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. 241 | - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. 242 | - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. 243 | - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. 244 | */ 245 | 246 | /** 247 | * @brief Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. 248 | * Configures the DAP Hardware I/O pins for JTAG mode: 249 | * - TCK, TMS, TDI, nTRST, nRESET to ***output*** mode and set to high level. 250 | * - TDO to ***input*** mode. 251 | * 252 | */ 253 | __STATIC_INLINE void PORT_JTAG_SETUP(void) 254 | { 255 | // set TCK, TMS pin 256 | //// FIXME: esp32 257 | //DAP_SPI_Deinit(); 258 | 259 | 260 | // PIN_TDO output disable 261 | GPIO.enable_w1tc = (0x1 << PIN_TDO); 262 | // PIN_TDO input enable 263 | PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[PIN_TDO]); 264 | 265 | 266 | 267 | // gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); 268 | GPIO.enable_w1ts = (0x1 << PIN_TDI); 269 | GPIO.pin[PIN_TDI].pad_driver = 0; 270 | REG_CLR_BIT(GPIO_PIN_MUX_REG[PIN_TDI], FUN_PD); // disable pull down 271 | 272 | // gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); 273 | // gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); 274 | GPIO.enable_w1tc = (0x1 << PIN_nTRST); 275 | GPIO.pin[PIN_nTRST].pad_driver = 1; 276 | GPIO.enable_w1tc = (0x1 << PIN_nRESET); 277 | GPIO.pin[PIN_nRESET].pad_driver = 1; 278 | 279 | // gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); 280 | // gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); 281 | GPIO_PULL_UP_ONLY_SET(PIN_nTRST); 282 | GPIO_PULL_UP_ONLY_SET(PIN_nRESET); 283 | } 284 | 285 | /** 286 | * @brief Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. 287 | * Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: 288 | * - SWCLK, SWDIO, nRESET to output mode and set to default high level. 289 | * - TDI, nTRST to HighZ mode (pins are unused in SWD mode). 290 | * 291 | */ 292 | __STATIC_INLINE void PORT_SWD_SETUP(void) 293 | { 294 | // At this stage we do not consider whether to use SPI or GPIO. 295 | // We will switch to the specific mode when setting the transfer rate. 296 | 297 | //// FIXME: esp32 298 | // DAP_SPI_Init(); 299 | // DAP_SPI_Disable(); 300 | DAP_SPI_Deinit(); 301 | } 302 | 303 | /** 304 | * @brief Disable JTAG/SWD I/O Pins. 305 | * Disables the DAP Hardware I/O pins which configures: 306 | * - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. 307 | * 308 | */ 309 | __STATIC_INLINE void PORT_OFF(void) 310 | { 311 | // Will be called when the DAP disconnected 312 | //// FIXME: esp32 313 | //DAP_SPI_Disable(); 314 | } 315 | 316 | // SWCLK/TCK I/O pin ------------------------------------- 317 | 318 | /** 319 | * @brief SWCLK/TCK I/O pin: Get Input. 320 | * 321 | * @return Current status of the SWCLK/TCK DAP hardware I/O pin. 322 | */ 323 | __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) 324 | { 325 | ////TODO: can we set to 0? 326 | return 0; 327 | } 328 | 329 | /** 330 | * @brief SWCLK/TCK I/O pin: Set Output to High. 331 | * 332 | * Set the SWCLK/TCK DAP hardware I/O pin to high level. 333 | */ 334 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET(void) 335 | { 336 | GPIO.out_w1ts = (0x1 << PIN_SWCLK); 337 | } 338 | 339 | /** 340 | * @brief SWCLK/TCK I/O pin: Set Output to Low. 341 | * 342 | * Set the SWCLK/TCK DAP hardware I/O pin to low level. 343 | */ 344 | __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) 345 | { 346 | GPIO.out_w1tc = (0x1 << PIN_SWCLK); 347 | } 348 | 349 | // SWDIO/TMS Pin I/O -------------------------------------- 350 | 351 | /** 352 | * @brief SWDIO/TMS I/O pin: Get Input. 353 | * 354 | * @return Current status of the SWDIO/TMS DAP hardware I/O pin. 355 | */ 356 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) 357 | { 358 | // Note that we only use mosi in GPIO mode 359 | return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; 360 | } 361 | 362 | /** 363 | * @brief SWDIO/TMS I/O pin: Set Output to High. 364 | * 365 | * Set the SWDIO/TMS DAP hardware I/O pin to high level. 366 | */ 367 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void) 368 | { 369 | GPIO.out_w1ts = (0x1 << PIN_SWDIO_MOSI); 370 | } 371 | 372 | /** 373 | * @brief SWDIO/TMS I/O pin: Set Output to Low. 374 | * 375 | * Set the SWDIO/TMS DAP hardware I/O pin to low level. 376 | */ 377 | __STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) 378 | { 379 | GPIO.out_w1tc = (0x1 << PIN_SWDIO_MOSI); 380 | } 381 | 382 | /** 383 | * @brief SWDIO I/O pin: Get Input (used in SWD mode only). 384 | * 385 | * @return Current status of the SWDIO DAP hardware I/O pin. 386 | */ 387 | __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) 388 | { 389 | // Note that we only use mosi in GPIO mode 390 | return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; 391 | } 392 | 393 | /** 394 | * @brief SWDIO I/O pin: Set Output (used in SWD mode only). 395 | * 396 | * @param bit Output value for the SWDIO DAP hardware I/O pin. 397 | * 398 | */ 399 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) 400 | { 401 | /** 402 | * Important: Use only one bit (bit0) of param! 403 | * Sometimes the func "SWD_TransferFunction" of SW_DP.c will 404 | * issue "2" as param instead of "0". Zach Lee 405 | */ 406 | if ((bit & 1U) == 1) 407 | { 408 | GPIO.out_w1ts = (0x1 << PIN_SWDIO_MOSI); // set bit 409 | } 410 | else 411 | { 412 | GPIO.out_w1tc = (0x1 << PIN_SWDIO_MOSI); // clear bit 413 | } 414 | } 415 | 416 | /** 417 | * @brief SWDIO I/O pin: Switch to Output mode (used in SWD mode only). 418 | * Configure the SWDIO DAP hardware I/O pin to output mode. This function is 419 | * called prior \ref PIN_SWDIO_OUT function calls. 420 | */ 421 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) 422 | { 423 | ////FIXME: may be have ... 424 | // set \ref gpio_set_direction -> OUTPUT 425 | // GPIO.enable_w1ts |= (0x1 << PIN_SWDIO_MOSI); 426 | // GPIO.pin[PIN_SWDIO_MOSI].driver = 0; 427 | do {}while (0); 428 | 429 | } 430 | 431 | /** 432 | * @brief SWDIO I/O pin: Switch to Input mode (used in SWD mode only). 433 | * Configure the SWDIO DAP hardware I/O pin to input mode. This function is 434 | * called prior \ref PIN_SWDIO_IN function calls. 435 | */ 436 | __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) 437 | { 438 | // Note that the input of esp32 is not always connected. 439 | PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[PIN_SWDIO_MOSI]); 440 | GPIO.out_w1ts = (0x1 << PIN_SWDIO_MOSI); 441 | } 442 | 443 | // TDI Pin I/O --------------------------------------------- 444 | 445 | /** 446 | * @brief TDI I/O pin: Get Input. 447 | * 448 | * @return Current status of the TDI DAP hardware I/O pin. 449 | */ 450 | __STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) 451 | { 452 | return ((GPIO.in >> PIN_TDI) & 0x1) ? 1 : 0; 453 | } 454 | 455 | /** 456 | * @brief TDI I/O pin: Set Output. 457 | * 458 | * @param bit Output value for the TDI DAP hardware I/O pin. 459 | * 460 | */ 461 | __STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) 462 | { 463 | if ((bit & 1U) == 1) 464 | { 465 | GPIO.out_w1ts = (0x1 << PIN_TDI); // set bit 466 | } 467 | else 468 | { 469 | GPIO.out_w1tc = (0x1 << PIN_TDI); // reset bit 470 | } 471 | } 472 | 473 | // TDO Pin I/O --------------------------------------------- 474 | 475 | /** 476 | * @brief TDO I/O pin: Get Input. 477 | * 478 | * @return Current status of the TDO DAP hardware I/O pin. 479 | */ 480 | __STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) 481 | { 482 | return ((GPIO.in >> PIN_TDO) & 0x1) ? 1 : 0; 483 | } 484 | 485 | // nTRST Pin I/O ------------------------------------------- 486 | 487 | /** 488 | * @brief nTRST I/O pin: Get Input. 489 | * 490 | * @return Current status of the nTRST DAP hardware I/O pin. 491 | */ 492 | __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) 493 | { 494 | return 0; // not available 495 | } 496 | 497 | /** 498 | * @brief nTRST I/O pin: Set Output. 499 | * 500 | * @param bit JTAG TRST Test Reset pin status: 501 | * - 0: issue a JTAG TRST Test Reset. 502 | - 1: release JTAG TRST Test Reset. 503 | */ 504 | __STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) 505 | { 506 | // Vendor reset sequence 507 | ; // not available 508 | } 509 | 510 | // nRESET Pin I/O------------------------------------------ 511 | 512 | /** 513 | * @brief nRESET I/O pin: Get Input. 514 | * 515 | * @return Current status of the nRESET DAP hardware I/O pin. 516 | */ 517 | __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) 518 | { 519 | return ((GPIO.in >> PIN_nRESET) & 0x1) ? 1 : 0; 520 | } 521 | 522 | /** 523 | * @brief nRESET I/O pin: Set Output. 524 | * 525 | * @param bit target device hardware reset pin status: 526 | * - 0: issue a device hardware reset. 527 | * - 1: release device hardware reset. 528 | */ 529 | __STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) 530 | { 531 | // Vendor reset sequence 532 | //// FIXME: unavailable 533 | if ((bit & 1U) == 1) 534 | { 535 | GPIO.out_w1ts = (0x1 << PIN_nRESET); // set bit 536 | } 537 | else 538 | { 539 | GPIO.out_w1tc = (0x1 << PIN_nRESET); // clear bit 540 | } 541 | } 542 | 543 | ///@} 544 | 545 | //************************************************************************************************** 546 | /** 547 | \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs 548 | \ingroup DAP_ConfigIO_gr 549 | @{ 550 | 551 | CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. 552 | 553 | It is recommended to provide the following LEDs for status indication: 554 | - Connect LED: is active when the DAP hardware is connected to a debugger. 555 | - Running LED: is active when the debugger has put the target device into running state. 556 | */ 557 | 558 | /** Debug Unit: Set status of Connected LED. 559 | \param bit status of the Connect LED. 560 | - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. 561 | - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. 562 | */ 563 | 564 | /** 565 | * @brief Debug Unit: Set status of Connected LED. 566 | * 567 | * @param bit status of the Connect LED. 568 | * - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. 569 | * - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. 570 | */ 571 | __STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit) 572 | { 573 | if (bit) 574 | { 575 | GPIO.out_w1ts = (0x1 << PIN_LED_CONNECTED); // set bit 576 | } 577 | else 578 | { 579 | GPIO.out_w1tc = (0x1 << PIN_LED_CONNECTED); // clear bit 580 | } 581 | } 582 | 583 | /** 584 | * @brief Debug Unit: Set status Target Running LED. 585 | * 586 | * @param bit status of the Target Running LED. 587 | * - 1: Target Running LED ON: program execution in target started. 588 | * - 0: Target Running LED OFF: program execution in target stopped. 589 | */ 590 | __STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit) 591 | { 592 | if (bit) 593 | { 594 | GPIO.out_w1ts = (0x1 << PIN_LED_RUNNING); // set bit 595 | } 596 | else 597 | { 598 | GPIO.out_w1tc = (0x1 << PIN_LED_RUNNING); // clear bit 599 | } 600 | } 601 | 602 | ///@} 603 | 604 | //************************************************************************************************** 605 | /** 606 | \defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp 607 | \ingroup DAP_ConfigIO_gr 608 | @{ 609 | Access function for Test Domain Timer. 610 | 611 | The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By 612 | default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. 613 | 614 | */ 615 | 616 | /** 617 | * @brief Get timestamp of Test Domain Timer. 618 | * 619 | * @return Current timestamp value. 620 | */ 621 | __STATIC_INLINE uint32_t TIMESTAMP_GET(void) 622 | { 623 | ////FIXME: esp32 624 | return 0; 625 | } 626 | 627 | ///@} 628 | 629 | //************************************************************************************************** 630 | /** 631 | \defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization 632 | \ingroup DAP_ConfigIO_gr 633 | @{ 634 | 635 | CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. 636 | */ 637 | 638 | /** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). 639 | This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the 640 | Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: 641 | - I/O clock system enabled. 642 | - all I/O pins: input buffer enabled, output pins are set to HighZ mode. 643 | - for nTRST, nRESET a weak pull-up (if available) is enabled. 644 | - LED output pins are enabled and LEDs are turned off. 645 | */ 646 | __STATIC_INLINE void DAP_SETUP(void) 647 | { 648 | // Connecting non-SWD pins to GPIO 649 | GPIO_FUNCTION_SET(PIN_TDO); 650 | GPIO_FUNCTION_SET(PIN_TDI); 651 | GPIO_FUNCTION_SET(PIN_nTRST); 652 | GPIO_FUNCTION_SET(PIN_nRESET); 653 | GPIO_FUNCTION_SET(PIN_LED_CONNECTED); 654 | GPIO_FUNCTION_SET(PIN_LED_RUNNING); 655 | 656 | 657 | // Configure: LED as output (turned off) 658 | 659 | GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_CONNECTED); 660 | GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_RUNNING); 661 | 662 | LED_CONNECTED_OUT(0); 663 | LED_RUNNING_OUT(0); 664 | 665 | PORT_OFF(); 666 | } 667 | 668 | /** Reset Target Device with custom specific I/O pin or command sequence. 669 | This function allows the optional implementation of a device specific reset sequence. 670 | It is called when the command \ref DAP_ResetTarget and is for example required 671 | when a device needs a time-critical unlock sequence that enables the debug port. 672 | \return 0 = no device specific reset sequence is implemented.\n 673 | 1 = a device specific reset sequence is implemented. 674 | */ 675 | __STATIC_INLINE uint8_t RESET_TARGET(void) 676 | { 677 | return (0U); // not available 678 | } 679 | 680 | ///@} 681 | 682 | #endif /* __DAP_CONFIG_H__ */ 683 | -------------------------------------------------------------------------------- /components/DAP/include/DAP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2019 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 26. November 2019 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Include 24 | * Title: DAP.h Definitions 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | #ifndef __DAP_H__ 29 | #define __DAP_H__ 30 | 31 | 32 | // DAP Firmware Version 33 | #ifdef DAP_FW_V1 34 | #define DAP_FW_VER "1.2.0" 35 | #else 36 | #define DAP_FW_VER "2.0.0" 37 | #endif 38 | 39 | // DAP Command IDs 40 | #define ID_DAP_Info 0x00U 41 | #define ID_DAP_HostStatus 0x01U 42 | #define ID_DAP_Connect 0x02U 43 | #define ID_DAP_Disconnect 0x03U 44 | #define ID_DAP_TransferConfigure 0x04U 45 | #define ID_DAP_Transfer 0x05U 46 | #define ID_DAP_TransferBlock 0x06U 47 | #define ID_DAP_TransferAbort 0x07U 48 | #define ID_DAP_WriteABORT 0x08U 49 | #define ID_DAP_Delay 0x09U 50 | #define ID_DAP_ResetTarget 0x0AU 51 | #define ID_DAP_SWJ_Pins 0x10U 52 | #define ID_DAP_SWJ_Clock 0x11U 53 | #define ID_DAP_SWJ_Sequence 0x12U 54 | #define ID_DAP_SWD_Configure 0x13U 55 | #define ID_DAP_SWD_Sequence 0x1DU 56 | #define ID_DAP_JTAG_Sequence 0x14U 57 | #define ID_DAP_JTAG_Configure 0x15U 58 | #define ID_DAP_JTAG_IDCODE 0x16U 59 | #define ID_DAP_SWO_Transport 0x17U 60 | #define ID_DAP_SWO_Mode 0x18U 61 | #define ID_DAP_SWO_Baudrate 0x19U 62 | #define ID_DAP_SWO_Control 0x1AU 63 | #define ID_DAP_SWO_Status 0x1BU 64 | #define ID_DAP_SWO_ExtendedStatus 0x1EU 65 | #define ID_DAP_SWO_Data 0x1CU 66 | 67 | #define ID_DAP_QueueCommands 0x7EU 68 | #define ID_DAP_ExecuteCommands 0x7FU 69 | 70 | // DAP Vendor Command IDs 71 | #define ID_DAP_Vendor0 0x80U 72 | #define ID_DAP_Vendor1 0x81U 73 | #define ID_DAP_Vendor2 0x82U 74 | #define ID_DAP_Vendor3 0x83U 75 | #define ID_DAP_Vendor4 0x84U 76 | #define ID_DAP_Vendor5 0x85U 77 | #define ID_DAP_Vendor6 0x86U 78 | #define ID_DAP_Vendor7 0x87U 79 | #define ID_DAP_Vendor8 0x88U 80 | #define ID_DAP_Vendor9 0x89U 81 | #define ID_DAP_Vendor10 0x8AU 82 | #define ID_DAP_Vendor11 0x8BU 83 | #define ID_DAP_Vendor12 0x8CU 84 | #define ID_DAP_Vendor13 0x8DU 85 | #define ID_DAP_Vendor14 0x8EU 86 | #define ID_DAP_Vendor15 0x8FU 87 | #define ID_DAP_Vendor16 0x90U 88 | #define ID_DAP_Vendor17 0x91U 89 | #define ID_DAP_Vendor18 0x92U 90 | #define ID_DAP_Vendor19 0x93U 91 | #define ID_DAP_Vendor20 0x94U 92 | #define ID_DAP_Vendor21 0x95U 93 | #define ID_DAP_Vendor22 0x96U 94 | #define ID_DAP_Vendor23 0x97U 95 | #define ID_DAP_Vendor24 0x98U 96 | #define ID_DAP_Vendor25 0x99U 97 | #define ID_DAP_Vendor26 0x9AU 98 | #define ID_DAP_Vendor27 0x9BU 99 | #define ID_DAP_Vendor28 0x9CU 100 | #define ID_DAP_Vendor29 0x9DU 101 | #define ID_DAP_Vendor30 0x9EU 102 | #define ID_DAP_Vendor31 0x9FU 103 | 104 | #define ID_DAP_Invalid 0xFFU 105 | 106 | // DAP Status Code 107 | #define DAP_OK 0U 108 | #define DAP_ERROR 0xFFU 109 | 110 | // DAP ID 111 | #define DAP_ID_VENDOR 1U 112 | #define DAP_ID_PRODUCT 2U 113 | #define DAP_ID_SER_NUM 3U 114 | #define DAP_ID_FW_VER 4U 115 | #define DAP_ID_DEVICE_VENDOR 5U 116 | #define DAP_ID_DEVICE_NAME 6U 117 | #define DAP_ID_CAPABILITIES 0xF0U 118 | #define DAP_ID_TIMESTAMP_CLOCK 0xF1U 119 | #define DAP_ID_SWO_BUFFER_SIZE 0xFDU 120 | #define DAP_ID_PACKET_COUNT 0xFEU 121 | #define DAP_ID_PACKET_SIZE 0xFFU 122 | 123 | // DAP Host Status 124 | #define DAP_DEBUGGER_CONNECTED 0U 125 | #define DAP_TARGET_RUNNING 1U 126 | 127 | // DAP Port 128 | #define DAP_PORT_AUTODETECT 0U // Autodetect Port 129 | #define DAP_PORT_DISABLED 0U // Port Disabled (I/O pins in High-Z) 130 | #define DAP_PORT_SWD 1U // SWD Port (SWCLK, SWDIO) + nRESET 131 | #define DAP_PORT_JTAG 2U // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET 132 | 133 | // DAP SWJ Pins 134 | #define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK 135 | #define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS 136 | #define DAP_SWJ_TDI 2 // TDI 137 | #define DAP_SWJ_TDO 3 // TDO 138 | #define DAP_SWJ_nTRST 5 // nTRST 139 | #define DAP_SWJ_nRESET 7 // nRESET 140 | 141 | // DAP Transfer Request 142 | #define DAP_TRANSFER_APnDP (1U<<0) 143 | #define DAP_TRANSFER_RnW (1U<<1) 144 | #define DAP_TRANSFER_A2 (1U<<2) 145 | #define DAP_TRANSFER_A3 (1U<<3) 146 | #define DAP_TRANSFER_MATCH_VALUE (1U<<4) 147 | #define DAP_TRANSFER_MATCH_MASK (1U<<5) 148 | #define DAP_TRANSFER_TIMESTAMP (1U<<7) 149 | 150 | // DAP Transfer Response 151 | #define DAP_TRANSFER_OK (1U<<0) 152 | #define DAP_TRANSFER_WAIT (1U<<1) 153 | #define DAP_TRANSFER_FAULT (1U<<2) 154 | #define DAP_TRANSFER_ERROR (1U<<3) 155 | #define DAP_TRANSFER_MISMATCH (1U<<4) 156 | 157 | // DAP SWO Trace Mode 158 | #define DAP_SWO_OFF 0U 159 | #define DAP_SWO_UART 1U 160 | #define DAP_SWO_MANCHESTER 2U 161 | 162 | // DAP SWO Trace Status 163 | #define DAP_SWO_CAPTURE_ACTIVE (1U<<0) 164 | #define DAP_SWO_CAPTURE_PAUSED (1U<<1) 165 | #define DAP_SWO_STREAM_ERROR (1U<<6) 166 | #define DAP_SWO_BUFFER_OVERRUN (1U<<7) 167 | 168 | 169 | // Debug Port Register Addresses 170 | #define DP_IDCODE 0x00U // IDCODE Register (SW Read only) 171 | #define DP_ABORT 0x00U // Abort Register (SW Write only) 172 | #define DP_CTRL_STAT 0x04U // Control & Status 173 | #define DP_WCR 0x04U // Wire Control Register (SW Only) 174 | #define DP_SELECT 0x08U // Select Register (JTAG R/W & SW W) 175 | #define DP_RESEND 0x08U // Resend (SW Read Only) 176 | #define DP_RDBUFF 0x0CU // Read Buffer (Read Only) 177 | 178 | // JTAG IR Codes 179 | #define JTAG_ABORT 0x08U 180 | #define JTAG_DPACC 0x0AU 181 | #define JTAG_APACC 0x0BU 182 | #define JTAG_IDCODE 0x0EU 183 | #define JTAG_BYPASS 0x0FU 184 | 185 | // JTAG Sequence Info 186 | #define JTAG_SEQUENCE_TCK 0x3FU // TCK count 187 | #define JTAG_SEQUENCE_TMS 0x40U // TMS value 188 | #define JTAG_SEQUENCE_TDO 0x80U // TDO capture 189 | 190 | // SWD Sequence Info 191 | #define SWD_SEQUENCE_CLK 0x3FU // SWCLK count 192 | #define SWD_SEQUENCE_DIN 0x80U // SWDIO capture 193 | 194 | 195 | #include 196 | #include 197 | #include "cmsis_compiler.h" 198 | 199 | // DAP Data structure 200 | typedef struct { 201 | uint8_t debug_port; // Debug Port 202 | uint8_t fast_clock; // Fast Clock Flag 203 | uint8_t padding[2]; 204 | uint32_t clock_delay; // Clock Delay 205 | uint32_t timestamp; // Last captured Timestamp 206 | struct { // Transfer Configuration 207 | uint8_t idle_cycles; // Idle cycles after transfer 208 | uint8_t padding[3]; 209 | uint16_t retry_count; // Number of retries after WAIT response 210 | uint16_t match_retry; // Number of retries if read value does not match 211 | uint32_t match_mask; // Match Mask 212 | } transfer; 213 | #if (DAP_SWD != 0) 214 | struct { // SWD Configuration 215 | uint8_t turnaround; // Turnaround period 216 | uint8_t data_phase; // Always generate Data Phase 217 | } swd_conf; 218 | #endif 219 | #if (DAP_JTAG != 0) 220 | struct { // JTAG Device Chain 221 | uint8_t count; // Number of devices 222 | uint8_t index; // Device index (device at TDO has index 0) 223 | #if (DAP_JTAG_DEV_CNT != 0) 224 | uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits 225 | uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR 226 | uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR 227 | #endif 228 | } jtag_dev; 229 | #endif 230 | } DAP_Data_t; 231 | 232 | extern DAP_Data_t DAP_Data; // DAP Data 233 | extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag 234 | 235 | 236 | enum transfer_type { 237 | kTransfer_GPIO_normal, 238 | kTransfer_GPIO_fast, 239 | kTransfer_SPI 240 | }; 241 | 242 | extern uint8_t SWD_TransferSpeed; 243 | 244 | #ifdef __cplusplus 245 | extern "C" 246 | { 247 | #endif 248 | 249 | // Functions 250 | extern void SWJ_Sequence (uint32_t count, const uint8_t *data); 251 | extern void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi); 252 | extern void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo); 253 | extern void JTAG_IR (uint32_t ir); 254 | extern uint32_t JTAG_ReadIDCode (void); 255 | extern void JTAG_WriteAbort (uint32_t data); 256 | extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data); 257 | extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); 258 | 259 | extern void Delayms (uint32_t delay); 260 | 261 | extern uint32_t SWO_Transport (const uint8_t *request, uint8_t *response); 262 | extern uint32_t SWO_Mode (const uint8_t *request, uint8_t *response); 263 | extern uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response); 264 | extern uint32_t SWO_Control (const uint8_t *request, uint8_t *response); 265 | extern uint32_t SWO_Status (uint8_t *response); 266 | extern uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response); 267 | extern uint32_t SWO_Data (const uint8_t *request, uint8_t *response); 268 | 269 | extern void SWO_QueueTransfer (uint8_t *buf, uint32_t num); 270 | extern void SWO_AbortTransfer (void); 271 | extern void SWO_TransferComplete (void); 272 | 273 | extern uint32_t UART_SWO_Mode (uint32_t enable); 274 | extern uint32_t UART_SWO_Baudrate (uint32_t baudrate); 275 | extern uint32_t UART_SWO_Control (uint32_t active); 276 | // extern void UART_SWO_Capture (uint8_t *buf, uint32_t num); 277 | // extern uint32_t UART_SWO_GetCount (void); 278 | 279 | extern uint32_t Manchester_SWO_Mode (uint32_t enable); 280 | extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate); 281 | extern uint32_t Manchester_SWO_Control (uint32_t active); 282 | extern void Manchester_SWO_Capture (uint8_t *buf, uint32_t num); 283 | extern uint32_t Manchester_SWO_GetCount (void); 284 | 285 | extern uint32_t DAP_ProcessVendorCommand (const uint8_t *request, uint8_t *response); 286 | extern uint32_t DAP_ProcessCommand (const uint8_t *request, uint8_t *response); 287 | extern uint32_t DAP_ExecuteCommand (const uint8_t *request, uint8_t *response); 288 | 289 | extern void DAP_Setup (void); 290 | 291 | // Configurable delay for clock generation 292 | #ifndef DELAY_SLOW_CYCLES 293 | #define DELAY_SLOW_CYCLES 3U // Number of cycles for one iteration 294 | #endif 295 | 296 | #define USE_ASSEMBLY 1 297 | 298 | #if (USE_ASSEMBLY == 0) 299 | __STATIC_FORCEINLINE void PIN_DELAY_SLOW(uint32_t delay) 300 | { 301 | uint32_t count = delay; 302 | while (--count) 303 | ; 304 | } 305 | #else 306 | __STATIC_FORCEINLINE void PIN_DELAY_SLOW(uint32_t delay) 307 | { 308 | __asm__ volatile( 309 | "l_PINDELAYSLOW%=:" 310 | "ADDI.N %[time], %[time], -1;" 311 | "BNEZ %[time], l_PINDELAYSLOW%=;" 312 | : [time] "+r"(delay)); 313 | } 314 | 315 | #endif 316 | 317 | // Fixed delay for fast clock generation 318 | #ifndef DELAY_FAST_CYCLES 319 | #define DELAY_FAST_CYCLES 0U // Number of cycles: 0..3 320 | #endif 321 | __STATIC_FORCEINLINE void PIN_DELAY_FAST (void) { 322 | #if (DELAY_FAST_CYCLES >= 1U) 323 | __NOP(); 324 | #endif 325 | #if (DELAY_FAST_CYCLES >= 2U) 326 | __NOP(); 327 | #endif 328 | #if (DELAY_FAST_CYCLES >= 3U) 329 | __NOP(); 330 | #endif 331 | } 332 | 333 | #ifdef __cplusplus 334 | } 335 | #endif 336 | 337 | 338 | #endif /* __DAP_H__ */ 339 | -------------------------------------------------------------------------------- /components/DAP/include/cmsis_compiler.h: -------------------------------------------------------------------------------- 1 | #ifndef __CMSIS_COMPILER_H__ 2 | #define __CMSIS_COMPILER_H__ 3 | 4 | #ifndef __STATIC_FORCEINLINE 5 | #define __STATIC_FORCEINLINE static inline __attribute__((always_inline)) 6 | #endif 7 | #ifndef __STATIC_INLINE 8 | #define __STATIC_INLINE static inline __attribute__((always_inline)) 9 | #endif 10 | #ifndef __FORCEINLINE 11 | #define __FORCEINLINE inline __attribute__((always_inline)) 12 | #endif 13 | #ifndef __WEAK 14 | #define __WEAK __attribute__((weak)) 15 | #endif 16 | 17 | 18 | #endif -------------------------------------------------------------------------------- /components/DAP/include/dap_utility.h: -------------------------------------------------------------------------------- 1 | #ifndef __DAP_UTILITY_H__ 2 | #define __DAP_UTILITY_H__ 3 | 4 | #include 5 | 6 | #ifndef __STATIC_FORCEINLINE 7 | #define __STATIC_FORCEINLINE static inline __attribute__((always_inline)) 8 | #endif 9 | #ifndef __STATIC_INLINE 10 | #define __STATIC_INLINE static inline __attribute__((always_inline)) 11 | #endif 12 | #ifndef __WEAK 13 | #define __WEAK __attribute__((weak)) 14 | #endif 15 | 16 | 17 | extern const uint8_t kParityByteTable[256]; 18 | 19 | __STATIC_FORCEINLINE uint8_t ParityEvenUint32(uint32_t v) 20 | { 21 | v ^= v >> 16; 22 | v ^= v >> 8; 23 | v ^= v >> 4; 24 | v &= 0xf; 25 | return (0x6996 >> v) & 1; 26 | } 27 | 28 | __STATIC_FORCEINLINE uint8_t ParityEvenUint8(uint8_t v) 29 | { 30 | return kParityByteTable[v]; 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /components/DAP/include/gpio_op.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file gpio_op.h 3 | * @author windowsair 4 | * @brief esp32 GPIO operation 5 | * @version 0.1 6 | * @date 2021-03-03 7 | * 8 | * @copyright Copyright (c) 2021 9 | * 10 | */ 11 | 12 | #ifndef __GPIO_OP_H__ 13 | #define __GPIO_OP_H__ 14 | 15 | #include "components/DAP/include/cmsis_compiler.h" 16 | 17 | // soc register 18 | #include "esp32/rom/gpio.h" 19 | #include "esp32/include/soc/gpio_struct.h" 20 | #include "hal/gpio_types.h" 21 | 22 | //extern uint32_t GPIO_PIN_MUX_REG[]; 23 | 24 | 25 | __STATIC_INLINE void GPIO_FUNCTION_SET(int io_num) 26 | { 27 | // function number 2 is GPIO_FUNC for each pin 28 | // Note that the index starts at 0, so we are using function 3. 29 | PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[io_num], PIN_FUNC_GPIO); 30 | } 31 | 32 | static void GPIO_SET_DIRECTION_NORMAL_OUT(int io_num) 33 | { 34 | GPIO.enable_w1ts = (0x1 << io_num); 35 | // PP out 36 | GPIO.pin[io_num].pad_driver = 0; 37 | } 38 | 39 | __STATIC_INLINE void GPIO_PULL_UP_ONLY_SET(int io_num) 40 | { 41 | // disable pull down 42 | REG_CLR_BIT(GPIO_PIN_MUX_REG[io_num], FUN_PD); 43 | // enable pull up 44 | REG_SET_BIT(GPIO_PIN_MUX_REG[io_num], FUN_PU); 45 | } 46 | 47 | 48 | 49 | 50 | // static void GPIO_SET_DIRECTION_NORMAL_IN(int io_num) 51 | // { 52 | // GPIO.enable_w1tc |= (0x1 << io_num); 53 | // } 54 | 55 | #endif -------------------------------------------------------------------------------- /components/DAP/include/spi_op.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPI_OP_H__ 2 | #define __SPI_OP_H__ 3 | 4 | #include 5 | 6 | 7 | void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf); 8 | void DAP_SPI_ReadBits(const uint8_t count, uint8_t *buf); 9 | 10 | void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *ack, uint8_t TrnAfterACK); 11 | void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity); 12 | void DAP_SPI_Write_Data(uint32_t data, uint8_t parity); 13 | 14 | void DAP_SPI_Generate_Cycle(uint8_t num); 15 | void DAP_SPI_Fast_Cycle(); 16 | 17 | void DAP_SPI_Protocol_Error_Read(); 18 | void DAP_SPI_Protocol_Error_Write(); 19 | 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /components/DAP/include/spi_switch.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPI_SWITCH_H__ 2 | #define __SPI_SWITCH_H__ 3 | 4 | void DAP_SPI_Init(); 5 | void DAP_SPI_Deinit(); 6 | 7 | void DAP_SPI_Enable(); 8 | void DAP_SPI_Disable(); 9 | 10 | void DAP_SPI_Acquire(); 11 | void DAP_SPI_Release(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /components/DAP/include/uart_modify.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief Made some simple modifications to the official UART 3 | * 4 | */ 5 | 6 | // Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD 7 | // 8 | // Licensed under the Apache License, Version 2.0 (the "License"); 9 | // you may not use this file except in compliance with the License. 10 | // You may obtain a copy of the License at 11 | // 12 | // http://www.apache.org/licenses/LICENSE-2.0 13 | // 14 | // Unless required by applicable law or agreed to in writing, software 15 | // distributed under the License is distributed on an "AS IS" BASIS, 16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | // See the License for the specific language governing permissions and 18 | // limitations under the License. 19 | 20 | 21 | #ifndef _DRIVER_UART_H_ 22 | #define _DRIVER_UART_H_ 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #include "esp_err.h" 29 | #include "esp_log.h" 30 | #include "freertos/queue.h" 31 | #include "freertos/semphr.h" 32 | 33 | // SWO modify 34 | extern volatile uint32_t kSWO_read_index; 35 | extern volatile uint32_t kSWO_read_num; 36 | extern volatile uint8_t kSWO_uart_notify_enable; 37 | extern SemaphoreHandle_t kSWO_read_mux; 38 | 39 | #define UART_FIFO_LEN (128) /*!< Length of the hardware FIFO buffers */ 40 | #define UART_INTR_MASK 0x1ff /*!< Mask of all UART interrupts */ 41 | #define UART_LINE_INV_MASK (0x3f << 19) /*!< TBD */ 42 | 43 | #define UART_INVERSE_DISABLE (0x0) /*!< Disable UART signal inverse*/ 44 | #define UART_INVERSE_RXD (BIT(19)) /*!< UART RXD input inverse*/ 45 | #define UART_INVERSE_CTS (BIT(20)) /*!< UART CTS input inverse*/ 46 | #define UART_INVERSE_TXD (BIT(22)) /*!< UART TXD output inverse*/ 47 | #define UART_INVERSE_RTS (BIT(23)) /*!< UART RTS output inverse*/ 48 | 49 | /** 50 | * @brief UART mode selection 51 | */ 52 | typedef enum { 53 | UART_MODE_UART = 0x00, /*!< mode: regular UART mode*/ 54 | } uart_mode_t; 55 | 56 | /** 57 | * @brief UART word length constants 58 | */ 59 | typedef enum { 60 | UART_DATA_5_BITS = 0x0, /*!< word length: 5bits*/ 61 | UART_DATA_6_BITS = 0x1, /*!< word length: 6bits*/ 62 | UART_DATA_7_BITS = 0x2, /*!< word length: 7bits*/ 63 | UART_DATA_8_BITS = 0x3, /*!< word length: 8bits*/ 64 | UART_DATA_BITS_MAX = 0x4, 65 | } uart_word_length_t; 66 | 67 | /** 68 | * @brief UART stop bits number 69 | */ 70 | typedef enum { 71 | UART_STOP_BITS_1 = 0x1, /*!< stop bit: 1bit*/ 72 | UART_STOP_BITS_1_5 = 0x2, /*!< stop bit: 1.5bits*/ 73 | UART_STOP_BITS_2 = 0x3, /*!< stop bit: 2bits*/ 74 | UART_STOP_BITS_MAX = 0x4, 75 | } uart_stop_bits_t; 76 | 77 | /** 78 | * @brief UART peripheral number 79 | */ 80 | typedef enum { 81 | UART_NUM_0 = 0x0, 82 | UART_NUM_1 = 0x1, 83 | UART_NUM_MAX, 84 | } uart_port_t; 85 | 86 | /** 87 | * @brief UART parity constants 88 | */ 89 | typedef enum { 90 | UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/ 91 | UART_PARITY_EVEN = 0x2, /*!< Enable UART even parity*/ 92 | UART_PARITY_ODD = 0x3 /*!< Enable UART odd parity*/ 93 | } uart_parity_t; 94 | 95 | /** 96 | * @brief UART hardware flow control modes 97 | */ 98 | typedef enum { 99 | UART_HW_FLOWCTRL_DISABLE = 0x0, /*!< disable hardware flow control*/ 100 | UART_HW_FLOWCTRL_RTS = 0x1, /*!< enable RX hardware flow control (rts)*/ 101 | UART_HW_FLOWCTRL_CTS = 0x2, /*!< enable TX hardware flow control (cts)*/ 102 | UART_HW_FLOWCTRL_CTS_RTS = 0x3, /*!< enable hardware flow control*/ 103 | UART_HW_FLOWCTRL_MAX = 0x4, 104 | } uart_hw_flowcontrol_t; 105 | 106 | /** 107 | * @brief UART configuration parameters for my_uart_param_config function 108 | */ 109 | typedef struct { 110 | int baud_rate; /*!< UART baud rate*/ 111 | uart_word_length_t data_bits; /*!< UART byte size*/ 112 | uart_parity_t parity; /*!< UART parity mode*/ 113 | uart_stop_bits_t stop_bits; /*!< UART stop bits*/ 114 | uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode (cts/rts)*/ 115 | uint8_t rx_flow_ctrl_thresh; /*!< UART HW RTS threshold*/ 116 | } uart_config_t; 117 | 118 | /** 119 | * @brief UART interrupt configuration parameters for my_uart_intr_config function 120 | */ 121 | typedef struct { 122 | uint32_t intr_enable_mask; /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/ 123 | uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold (unit: time of sending one byte)*/ 124 | uint8_t txfifo_empty_intr_thresh; /*!< UART TX empty interrupt threshold.*/ 125 | uint8_t rxfifo_full_thresh; /*!< UART RX full interrupt threshold.*/ 126 | } uart_intr_config_t; 127 | 128 | /** 129 | * @brief UART event types used in the ring buffer 130 | */ 131 | typedef enum { 132 | UART_DATA, /*!< UART data event*/ 133 | UART_BUFFER_FULL, /*!< UART RX buffer full event*/ 134 | UART_FIFO_OVF, /*!< UART FIFO overflow event*/ 135 | UART_FRAME_ERR, /*!< UART RX frame error event*/ 136 | UART_PARITY_ERR, /*!< UART RX parity event*/ 137 | UART_EVENT_MAX, /*!< UART event max index*/ 138 | } uart_event_type_t; 139 | 140 | /** 141 | * @brief Event structure used in UART event queue 142 | */ 143 | typedef struct { 144 | uart_event_type_t type; /*!< UART event type */ 145 | size_t size; /*!< UART data size for UART_DATA event*/ 146 | } uart_event_t; 147 | 148 | 149 | /** 150 | * @brief Set UART data bits. 151 | * 152 | * @param uart_num Uart port number. 153 | * @param data_bit Uart data bits. 154 | * 155 | * @return 156 | * - ESP_OK success 157 | * - ESP_ERR_INVALID_ARG Parameter error 158 | */ 159 | esp_err_t my_uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit); 160 | 161 | /** 162 | * @brief Get UART data bits. 163 | * 164 | * @param uart_num Uart port number. 165 | * @param data_bit Pointer to accept value of UART data bits. 166 | * 167 | * @return 168 | * - ESP_OK success 169 | * - ESP_ERR_INVALID_ARG Parameter error 170 | */ 171 | esp_err_t my_uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data_bit); 172 | 173 | /** 174 | * @brief Set UART stop bits. 175 | * 176 | * @param uart_num Uart port number 177 | * @param stop_bits Uart stop bits 178 | * 179 | * @return 180 | * - ESP_OK success 181 | * - ESP_ERR_INVALID_ARG Parameter error 182 | */ 183 | esp_err_t my_uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits); 184 | 185 | /** 186 | * @brief Get UART stop bits. 187 | * 188 | * @param uart_num Uart port number. 189 | * @param stop_bits Pointer to accept value of UART stop bits. 190 | * 191 | * @return 192 | * - ESP_OK success 193 | * - ESP_ERR_INVALID_ARG Parameter error 194 | */ 195 | esp_err_t my_uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bits); 196 | 197 | /** 198 | * @brief Set UART parity mode. 199 | * 200 | * @param uart_num Uart port number. 201 | * @param parity_mode The enum of uart parity configuration. 202 | * 203 | * @return 204 | * - ESP_OK success 205 | * - ESP_ERR_INVALID_ARG Parameter error 206 | */ 207 | esp_err_t my_uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode); 208 | 209 | /** 210 | * @brief Get UART parity mode. 211 | * 212 | * @param uart_num Uart port number 213 | * @param parity_mode Pointer to accept value of UART parity mode. 214 | * 215 | * @return 216 | * - ESP_OK success 217 | * - ESP_ERR_INVALID_ARG Parameter error 218 | */ 219 | esp_err_t my_uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode); 220 | 221 | /** 222 | * @brief Set UART baud rate. 223 | * 224 | * @param uart_num Uart port number 225 | * @param baudrate UART baud rate. 226 | * 227 | * @return 228 | * - ESP_OK success 229 | * - ESP_ERR_INVALID_ARG Parameter error 230 | */ 231 | esp_err_t my_uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate); 232 | 233 | /** 234 | * @brief Get UART baud rate. 235 | * 236 | * @param uart_num Uart port number. 237 | * @param baudrate Pointer to accept value of Uart baud rate. 238 | * 239 | * @return 240 | * - ESP_OK success 241 | * - ESP_ERR_INVALID_ARG Parameter error 242 | */ 243 | esp_err_t my_uart_get_baudrate(uart_port_t uart_num, uint32_t *baudrate); 244 | 245 | /** 246 | * @brief Set UART line inverse mode 247 | * 248 | * @param uart_num UART_NUM_0 249 | * @param inverse_mask Choose the wires that need to be inverted. 250 | * Inverse_mask should be chosen from 251 | * UART_INVERSE_RXD / UART_INVERSE_TXD / UART_INVERSE_RTS / UART_INVERSE_CTS, 252 | * combined with OR operation. 253 | * 254 | * @return 255 | * - ESP_OK success 256 | * - ESP_ERR_INVALID_ARG Parameter error 257 | */ 258 | esp_err_t my_uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask); 259 | 260 | /** 261 | * @brief Configure Hardware flow control. 262 | * 263 | * @param uart_num Uart port number. 264 | * @param flow_ctrl Hardware flow control mode. 265 | * @param rx_thresh Threshold of Hardware flow control. 266 | * 267 | * @return 268 | * - ESP_OK success 269 | * - ESP_ERR_INVALID_ARG Parameter error 270 | */ 271 | esp_err_t my_uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh); 272 | 273 | /** 274 | * @brief Get hardware flow control mode 275 | * 276 | * @param uart_num Uart port number. 277 | * @param flow_ctrl Option for different flow control mode. 278 | * 279 | * @return 280 | * - ESP_OK Success, result will be put in (*flow_ctrl) 281 | * - ESP_ERR_INVALID_ARG Parameter error 282 | */ 283 | esp_err_t my_uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl); 284 | 285 | /** 286 | * @brief UART0 swap. 287 | * Use MTCK as UART0 RX, MTDO as UART0 TX, so ROM log will not output from 288 | * this new UART0. We also need to use MTDO (U0RTS) and MTCK (U0CTS) as UART0 in hardware. 289 | * 290 | * @return 291 | * - ESP_OK Success 292 | */ 293 | esp_err_t my_uart_enable_swap(void); 294 | 295 | /** 296 | * @brief Disable UART0 swap. 297 | * Use the original UART0, not MTCK and MTDO. 298 | * 299 | * @return 300 | * - ESP_OK Success 301 | */ 302 | esp_err_t my_uart_disable_swap(void); 303 | 304 | /** 305 | * @brief Clear uart interrupts status. 306 | * 307 | * @param uart_num Uart port number. 308 | * @param mask Uart interrupt bits mask. 309 | * 310 | * @return 311 | * - ESP_OK success 312 | * - ESP_ERR_INVALID_ARG Parameter error 313 | */ 314 | esp_err_t my_uart_clear_intr_status(uart_port_t uart_num, uint32_t mask); 315 | 316 | /** 317 | * @brief Set UART interrupt enable 318 | * 319 | * @param uart_num Uart port number 320 | * @param enable_mask Bit mask of the enable bits. 321 | * The bit mask should be composed from the fields of register UART_INT_ENA_REG. 322 | * 323 | * @return 324 | * - ESP_OK Success 325 | * - ESP_ERR_INVALID_ARG Parameter error 326 | */ 327 | esp_err_t my_uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); 328 | 329 | /** 330 | * @brief Clear UART interrupt enable bits 331 | * 332 | * @param uart_num Uart port number 333 | * @param disable_mask Bit mask of the disable bits. 334 | * The bit mask should be composed from the fields of register UART_INT_ENA_REG. 335 | * 336 | * @return 337 | * - ESP_OK Success 338 | * - ESP_ERR_INVALID_ARG Parameter error 339 | */ 340 | esp_err_t my_uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); 341 | 342 | /** 343 | * @brief Enable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT) 344 | * 345 | * @param uart_num UART_NUM_0 346 | * 347 | * @return 348 | * - ESP_OK Success 349 | * - ESP_ERR_INVALID_ARG Parameter error 350 | */ 351 | esp_err_t my_uart_enable_rx_intr(uart_port_t uart_num); 352 | 353 | /** 354 | * @brief Disable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT) 355 | * 356 | * @param uart_num UART_NUM_0 357 | * 358 | * @return 359 | * - ESP_OK Success 360 | * - ESP_ERR_INVALID_ARG Parameter error 361 | */ 362 | esp_err_t my_uart_disable_rx_intr(uart_port_t uart_num); 363 | 364 | /** 365 | * @brief Disable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT) 366 | * 367 | * @param uart_num UART_NUM_0 368 | * 369 | * @return 370 | * - ESP_OK Success 371 | * - ESP_ERR_INVALID_ARG Parameter error 372 | */ 373 | esp_err_t my_uart_disable_tx_intr(uart_port_t uart_num); 374 | 375 | /** 376 | * @brief Enable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT) 377 | * 378 | * @param uart_num UART_NUM_0 379 | * @param enable 1: enable; 0: disable 380 | * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN 381 | * 382 | * @return 383 | * - ESP_OK Success 384 | * - ESP_ERR_INVALID_ARG Parameter error 385 | */ 386 | esp_err_t my_uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); 387 | 388 | /** 389 | * @brief Register UART interrupt handler (ISR). 390 | * 391 | * @param uart_num UART_NUM_0 392 | * @param fn Interrupt handler function. 393 | * @param arg parameter for handler function 394 | * 395 | * @return 396 | * - ESP_OK Success 397 | * - ESP_ERR_INVALID_ARG Parameter error 398 | */ 399 | esp_err_t my_uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg); 400 | 401 | /** 402 | * @brief Config Common parameters of serial ports. 403 | * 404 | * @param uart_num Uart port number. 405 | * @param uart_conf Uart config parameters. 406 | * 407 | * @return 408 | * - ESP_OK success 409 | * - ESP_ERR_INVALID_ARG Parameter error 410 | */ 411 | esp_err_t my_uart_param_config(uart_port_t uart_num, uart_config_t *uart_conf); 412 | 413 | /** 414 | * @brief Config types of uarts. 415 | * 416 | * @param uart_num Uart port number. 417 | * @param uart_intr_conf Uart interrupt config parameters. 418 | * 419 | * @return 420 | * - ESP_OK success 421 | * - ESP_ERR_INVALID_ARG Parameter error 422 | */ 423 | esp_err_t my_uart_intr_config(uart_port_t uart_num, uart_intr_config_t *uart_intr_conf); 424 | 425 | /** 426 | * @brief Install UART driver. 427 | * 428 | * @note Rx_buffer_size should be greater than UART_FIFO_LEN. Tx_buffer_size should be either zero or greater than UART_FIFO_LEN. 429 | * 430 | * @param uart_num Uart port number. 431 | * @param rx_buffer_size UART RX ring buffer size. 432 | * @param tx_buffer_size UART TX ring buffer size. 433 | * If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out. 434 | * @param queue_size UART event queue size/depth. 435 | * @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide 436 | * access to UART events. If set to NULL, driver will not use an event queue. 437 | * @param no_use Invalid parameters, just to fit some modules. 438 | * 439 | * @return 440 | * - ESP_OK Success 441 | * - ESP_ERR_INVALID_ARG Parameter error 442 | */ 443 | esp_err_t my_uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int no_use); 444 | 445 | /** 446 | * @brief Uninstall UART driver. 447 | * 448 | * @param uart_num Uart port number. 449 | * 450 | * @return 451 | * - ESP_OK Success 452 | * - ESP_ERR_INVALID_ARG Parameter error 453 | */ 454 | esp_err_t my_uart_driver_delete(uart_port_t uart_num); 455 | 456 | /** 457 | * @brief Waiting for the last byte of data to be sent 458 | * 459 | * @param uart_num Uart port number. 460 | * @param ticks_to_wait Timeout, count in RTOS ticks 461 | * 462 | * @return 463 | * - ESP_OK Success 464 | * - ESP_ERR_INVALID_ARG Parameter error 465 | */ 466 | esp_err_t my_uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); 467 | 468 | /** 469 | * @brief Send data to the UART port from a given buffer and length. 470 | * 471 | * This function will not wait for enough space in TX FIFO. It will just fill the available TX FIFO and return when the FIFO is full. 472 | * @note This function should only be used when UART TX buffer is not enabled. 473 | * 474 | * @param uart_num Uart port number. 475 | * @param buffer data buffer address 476 | * @param len data length to send 477 | * 478 | * @return 479 | * - (-1) Parameter error 480 | * - OTHERS (>=0) The number of bytes pushed to the TX FIFO 481 | */ 482 | int my_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len); 483 | 484 | /** 485 | * @brief Send data to the UART port from a given buffer and length, 486 | * 487 | * If the UART driver's parameter 'tx_buffer_size' is set to zero: 488 | * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. 489 | * 490 | * Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer, 491 | * UART ISR will then move data from the ring buffer to TX FIFO gradually. 492 | * 493 | * @param uart_num Uart port number. 494 | * @param src data buffer address 495 | * @param size data length to send 496 | * 497 | * @return 498 | * - (-1) Parameter error 499 | * - OTHERS (>=0) The number of bytes pushed to the TX FIFO 500 | */ 501 | int my_uart_write_bytes(uart_port_t uart_num, const char *src, size_t size); 502 | 503 | /** 504 | * @brief UART read bytes from UART buffer 505 | * 506 | * @param uart_num Uart port number. 507 | * @param buf pointer to the buffer. 508 | * @param length data length 509 | * @param ticks_to_wait sTimeout, count in RTOS ticks 510 | * 511 | * @return 512 | * - (-1) Error 513 | * - OTHERS (>=0) The number of bytes read from UART FIFO 514 | */ 515 | int my_uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, TickType_t ticks_to_wait); 516 | 517 | /** 518 | * @brief Alias of my_uart_flush_input. 519 | * UART ring buffer flush. This will discard all data in the UART RX buffer. 520 | * @note Instead of waiting the data sent out, this function will clear UART rx buffer. 521 | * In order to send all the data in tx FIFO, we can use my_uart_wait_tx_done function. 522 | * @param uart_num UART port number. 523 | * 524 | * @return 525 | * - ESP_OK Success 526 | * - ESP_ERR_INVALID_ARG Parameter error 527 | */ 528 | esp_err_t my_uart_flush(uart_port_t uart_num); 529 | 530 | /** 531 | * @brief Clear input buffer, discard all the data is in the ring-buffer. 532 | * @note In order to send all the data in tx FIFO, we can use my_uart_wait_tx_done function. 533 | * @param uart_num UART port number. 534 | * 535 | * @return 536 | * - ESP_OK Success 537 | * - ESP_ERR_INVALID_ARG Parameter error 538 | */ 539 | esp_err_t my_uart_flush_input(uart_port_t uart_num); 540 | 541 | /** 542 | * @brief UART get RX ring buffer cached data length 543 | * 544 | * @param uart_num UART port number. 545 | * @param size Pointer of size_t to accept cached data length 546 | * 547 | * @return 548 | * - ESP_OK Success 549 | * - ESP_ERR_INVALID_ARG Parameter error 550 | */ 551 | esp_err_t my_uart_get_buffered_data_len(uart_port_t uart_num, size_t *size); 552 | 553 | /** 554 | * @brief UART set threshold timeout for TOUT feature 555 | * 556 | * @param uart_num Uart number to configure 557 | * @param tout_thresh This parameter defines timeout threshold in uart symbol periods. The maximum value of threshold is 126. 558 | * tout_thresh = 1, defines TOUT interrupt timeout equal to transmission time of one symbol (~11 bit) on current baudrate. 559 | * If the time is expired the UART_RXFIFO_TOUT_INT interrupt is triggered. If tout_thresh == 0, 560 | * the TOUT feature is disabled. 561 | * 562 | * @return 563 | * - ESP_OK Success 564 | * - ESP_ERR_INVALID_ARG Parameter error 565 | */ 566 | esp_err_t my_uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh); 567 | 568 | 569 | /** 570 | * @brief Asynchronously read bytes to swo buffer 571 | * @note This function only serves as a notification, 572 | * and will initiate a callback when the buffer reaches the length since we modify the uart 573 | * @param index buffer index to read 574 | * @param length data length 575 | * @return esp_err_t 576 | * - ESP_OK Success 577 | * - ESP_FAIL There are still unfinished requests 578 | */ 579 | esp_err_t my_uart_read_bytes_async_swo(uint32_t index, uint32_t length); 580 | 581 | 582 | /** 583 | * @brief UART get RX ring buffer cached data length 584 | * @note This function is basically equivalent to \ref my_uart_get_buffered_data_len 585 | * @param uart_num UART port number. 586 | * 587 | * @return data length 588 | */ 589 | int my_uart_get_rx_buffered_data_len(uart_port_t uart_num); 590 | 591 | 592 | #ifdef __cplusplus 593 | } 594 | #endif 595 | 596 | #endif // _DRIVER_UART_H_ 597 | -------------------------------------------------------------------------------- /components/DAP/source/DAP_vendor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Source 24 | * Title: DAP_vendor.c CMSIS-DAP Vendor Commands 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | #include "components/DAP/config/DAP_config.h" 29 | #include "components/DAP/include/DAP.h" 30 | 31 | //************************************************************************************************** 32 | /** 33 | \defgroup DAP_Vendor_Adapt_gr Adapt Vendor Commands 34 | \ingroup DAP_Vendor_gr 35 | @{ 36 | 37 | The file DAP_vendor.c provides template source code for extension of a Debug Unit with 38 | Vendor Commands. Copy this file to the project folder of the Debug Unit and add the 39 | file to the MDK-ARM project under the file group Configuration. 40 | */ 41 | 42 | /** Process DAP Vendor Command and prepare Response Data 43 | \param request pointer to request data 44 | \param response pointer to response data 45 | \return number of bytes in response (lower 16 bits) 46 | number of bytes in request (upper 16 bits) 47 | */ 48 | uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) { 49 | uint32_t num = (1U << 16) | 1U; 50 | 51 | *response++ = *request; // copy Command ID 52 | 53 | switch (*request++) { // first byte in request is Command ID 54 | case ID_DAP_Vendor0: 55 | #if 0 // example user command 56 | num += 1U << 16; // increment request count 57 | if (*request == 1U) { // when first command data byte is 1 58 | *response++ = 'X'; // send 'X' as response 59 | num++; // increment response count 60 | } 61 | #endif 62 | break; 63 | 64 | case ID_DAP_Vendor1: break; 65 | case ID_DAP_Vendor2: break; 66 | case ID_DAP_Vendor3: break; 67 | case ID_DAP_Vendor4: break; 68 | case ID_DAP_Vendor5: break; 69 | case ID_DAP_Vendor6: break; 70 | case ID_DAP_Vendor7: break; 71 | case ID_DAP_Vendor8: break; 72 | case ID_DAP_Vendor9: break; 73 | case ID_DAP_Vendor10: break; 74 | case ID_DAP_Vendor11: break; 75 | case ID_DAP_Vendor12: break; 76 | case ID_DAP_Vendor13: break; 77 | case ID_DAP_Vendor14: break; 78 | case ID_DAP_Vendor15: break; 79 | case ID_DAP_Vendor16: break; 80 | case ID_DAP_Vendor17: break; 81 | case ID_DAP_Vendor18: break; 82 | case ID_DAP_Vendor19: break; 83 | case ID_DAP_Vendor20: break; 84 | case ID_DAP_Vendor21: break; 85 | case ID_DAP_Vendor22: break; 86 | case ID_DAP_Vendor23: break; 87 | case ID_DAP_Vendor24: break; 88 | case ID_DAP_Vendor25: break; 89 | case ID_DAP_Vendor26: break; 90 | case ID_DAP_Vendor27: break; 91 | case ID_DAP_Vendor28: break; 92 | case ID_DAP_Vendor29: break; 93 | case ID_DAP_Vendor30: break; 94 | case ID_DAP_Vendor31: break; 95 | } 96 | 97 | return (num); 98 | } 99 | 100 | ///@} 101 | -------------------------------------------------------------------------------- /components/DAP/source/JTAG_DP.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Source 24 | * Title: JTAG_DP.c CMSIS-DAP JTAG DP I/O 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | 29 | #include "components/DAP/config/DAP_config.h" 30 | #include "components/DAP/include/DAP.h" 31 | 32 | 33 | // JTAG Macros 34 | 35 | #define PIN_TCK_SET PIN_SWCLK_TCK_SET 36 | #define PIN_TCK_CLR PIN_SWCLK_TCK_CLR 37 | #define PIN_TMS_SET PIN_SWDIO_TMS_SET 38 | #define PIN_TMS_CLR PIN_SWDIO_TMS_CLR 39 | 40 | #define JTAG_CYCLE_TCK() \ 41 | PIN_TCK_CLR(); \ 42 | PIN_DELAY(); \ 43 | PIN_TCK_SET(); \ 44 | PIN_DELAY() 45 | 46 | #define JTAG_CYCLE_TDI(tdi) \ 47 | PIN_TDI_OUT(tdi); \ 48 | PIN_TCK_CLR(); \ 49 | PIN_DELAY(); \ 50 | PIN_TCK_SET(); \ 51 | PIN_DELAY() 52 | 53 | #define JTAG_CYCLE_TDO(tdo) \ 54 | PIN_TCK_CLR(); \ 55 | PIN_DELAY(); \ 56 | tdo = PIN_TDO_IN(); \ 57 | PIN_TCK_SET(); \ 58 | PIN_DELAY() 59 | 60 | #define JTAG_CYCLE_TDIO(tdi,tdo) \ 61 | PIN_TDI_OUT(tdi); \ 62 | PIN_TCK_CLR(); \ 63 | PIN_DELAY(); \ 64 | tdo = PIN_TDO_IN(); \ 65 | PIN_TCK_SET(); \ 66 | PIN_DELAY() 67 | 68 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 69 | 70 | 71 | #if (DAP_JTAG != 0) 72 | 73 | 74 | // Generate JTAG Sequence 75 | // info: sequence information 76 | // tdi: pointer to TDI generated data 77 | // tdo: pointer to TDO captured data 78 | // return: none 79 | void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo) { 80 | uint32_t i_val; 81 | uint32_t o_val; 82 | uint32_t bit; 83 | uint32_t n, k; 84 | 85 | n = info & JTAG_SEQUENCE_TCK; 86 | if (n == 0U) { 87 | n = 64U; 88 | } 89 | 90 | if (info & JTAG_SEQUENCE_TMS) { 91 | PIN_TMS_SET(); 92 | } else { 93 | PIN_TMS_CLR(); 94 | } 95 | 96 | while (n) { 97 | i_val = *tdi++; 98 | o_val = 0U; 99 | for (k = 8U; k && n; k--, n--) { 100 | JTAG_CYCLE_TDIO(i_val, bit); 101 | i_val >>= 1; 102 | o_val >>= 1; 103 | o_val |= bit << 7; 104 | } 105 | o_val >>= k; 106 | if (info & JTAG_SEQUENCE_TDO) { 107 | *tdo++ = (uint8_t)o_val; 108 | } 109 | } 110 | } 111 | 112 | 113 | // JTAG Set IR 114 | // ir: IR value 115 | // return: none 116 | #define JTAG_IR_Function(speed) /**/ \ 117 | static void JTAG_IR_##speed (uint32_t ir) { \ 118 | uint32_t n; \ 119 | \ 120 | PIN_TMS_SET(); \ 121 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ 122 | JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \ 123 | PIN_TMS_CLR(); \ 124 | JTAG_CYCLE_TCK(); /* Capture-IR */ \ 125 | JTAG_CYCLE_TCK(); /* Shift-IR */ \ 126 | \ 127 | PIN_TDI_OUT(1U); \ 128 | for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \ 129 | JTAG_CYCLE_TCK(); /* Bypass before data */ \ 130 | } \ 131 | for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1U; n; n--) { \ 132 | JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \ 133 | ir >>= 1; \ 134 | } \ 135 | n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \ 136 | if (n) { \ 137 | JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \ 138 | PIN_TDI_OUT(1U); \ 139 | for (--n; n; n--) { \ 140 | JTAG_CYCLE_TCK(); /* Bypass after data */ \ 141 | } \ 142 | PIN_TMS_SET(); \ 143 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \ 144 | } else { \ 145 | PIN_TMS_SET(); \ 146 | JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \ 147 | } \ 148 | \ 149 | JTAG_CYCLE_TCK(); /* Update-IR */ \ 150 | PIN_TMS_CLR(); \ 151 | JTAG_CYCLE_TCK(); /* Idle */ \ 152 | PIN_TDI_OUT(1U); \ 153 | } 154 | 155 | 156 | // JTAG Transfer I/O 157 | // request: A[3:2] RnW APnDP 158 | // data: DATA[31:0] 159 | // return: ACK[2:0] 160 | #define JTAG_TransferFunction(speed) /**/ \ 161 | static uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \ 162 | uint32_t ack; \ 163 | uint32_t bit; \ 164 | uint32_t val; \ 165 | uint32_t n; \ 166 | \ 167 | PIN_TMS_SET(); \ 168 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ 169 | PIN_TMS_CLR(); \ 170 | JTAG_CYCLE_TCK(); /* Capture-DR */ \ 171 | JTAG_CYCLE_TCK(); /* Shift-DR */ \ 172 | \ 173 | for (n = DAP_Data.jtag_dev.index; n; n--) { \ 174 | JTAG_CYCLE_TCK(); /* Bypass before data */ \ 175 | } \ 176 | \ 177 | JTAG_CYCLE_TDIO(request >> 1, bit); /* Set RnW, Get ACK.0 */ \ 178 | ack = bit << 1; \ 179 | JTAG_CYCLE_TDIO(request >> 2, bit); /* Set A2, Get ACK.1 */ \ 180 | ack |= bit << 0; \ 181 | JTAG_CYCLE_TDIO(request >> 3, bit); /* Set A3, Get ACK.2 */ \ 182 | ack |= bit << 2; \ 183 | \ 184 | if (ack != DAP_TRANSFER_OK) { \ 185 | /* Exit on error */ \ 186 | PIN_TMS_SET(); \ 187 | JTAG_CYCLE_TCK(); /* Exit1-DR */ \ 188 | goto exit; \ 189 | } \ 190 | \ 191 | if (request & DAP_TRANSFER_RnW) { \ 192 | /* Read Transfer */ \ 193 | val = 0U; \ 194 | for (n = 31U; n; n--) { \ 195 | JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \ 196 | val |= bit << 31; \ 197 | val >>= 1; \ 198 | } \ 199 | n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \ 200 | if (n) { \ 201 | JTAG_CYCLE_TDO(bit); /* Get D31 */ \ 202 | for (--n; n; n--) { \ 203 | JTAG_CYCLE_TCK(); /* Bypass after data */ \ 204 | } \ 205 | PIN_TMS_SET(); \ 206 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ 207 | } else { \ 208 | PIN_TMS_SET(); \ 209 | JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \ 210 | } \ 211 | val |= bit << 31; \ 212 | if (data) { *data = val; } \ 213 | } else { \ 214 | /* Write Transfer */ \ 215 | val = *data; \ 216 | for (n = 31U; n; n--) { \ 217 | JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \ 218 | val >>= 1; \ 219 | } \ 220 | n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \ 221 | if (n) { \ 222 | JTAG_CYCLE_TDI(val); /* Set D31 */ \ 223 | for (--n; n; n--) { \ 224 | JTAG_CYCLE_TCK(); /* Bypass after data */ \ 225 | } \ 226 | PIN_TMS_SET(); \ 227 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ 228 | } else { \ 229 | PIN_TMS_SET(); \ 230 | JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \ 231 | } \ 232 | } \ 233 | \ 234 | exit: \ 235 | JTAG_CYCLE_TCK(); /* Update-DR */ \ 236 | PIN_TMS_CLR(); \ 237 | JTAG_CYCLE_TCK(); /* Idle */ \ 238 | PIN_TDI_OUT(1U); \ 239 | \ 240 | /* Capture Timestamp */ \ 241 | if (request & DAP_TRANSFER_TIMESTAMP) { \ 242 | DAP_Data.timestamp = TIMESTAMP_GET(); \ 243 | } \ 244 | \ 245 | /* Idle cycles */ \ 246 | n = DAP_Data.transfer.idle_cycles; \ 247 | while (n--) { \ 248 | JTAG_CYCLE_TCK(); /* Idle */ \ 249 | } \ 250 | \ 251 | return ((uint8_t)ack); \ 252 | } 253 | 254 | 255 | #undef PIN_DELAY 256 | #define PIN_DELAY() PIN_DELAY_FAST() 257 | JTAG_IR_Function(Fast) 258 | JTAG_TransferFunction(Fast) 259 | 260 | #undef PIN_DELAY 261 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 262 | JTAG_IR_Function(Slow) 263 | JTAG_TransferFunction(Slow) 264 | 265 | 266 | // JTAG Read IDCODE register 267 | // return: value read 268 | uint32_t JTAG_ReadIDCode (void) { 269 | uint32_t bit; 270 | uint32_t val; 271 | uint32_t n; 272 | 273 | PIN_TMS_SET(); 274 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ 275 | PIN_TMS_CLR(); 276 | JTAG_CYCLE_TCK(); /* Capture-DR */ 277 | JTAG_CYCLE_TCK(); /* Shift-DR */ 278 | 279 | for (n = DAP_Data.jtag_dev.index; n; n--) { 280 | JTAG_CYCLE_TCK(); /* Bypass before data */ 281 | } 282 | 283 | val = 0U; 284 | for (n = 31U; n; n--) { 285 | JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ 286 | val |= bit << 31; 287 | val >>= 1; 288 | } 289 | PIN_TMS_SET(); 290 | JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ 291 | val |= bit << 31; 292 | 293 | JTAG_CYCLE_TCK(); /* Update-DR */ 294 | PIN_TMS_CLR(); 295 | JTAG_CYCLE_TCK(); /* Idle */ 296 | 297 | return (val); 298 | } 299 | 300 | 301 | // JTAG Write ABORT register 302 | // data: value to write 303 | // return: none 304 | void JTAG_WriteAbort (uint32_t data) { 305 | uint32_t n; 306 | 307 | PIN_TMS_SET(); 308 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ 309 | PIN_TMS_CLR(); 310 | JTAG_CYCLE_TCK(); /* Capture-DR */ 311 | JTAG_CYCLE_TCK(); /* Shift-DR */ 312 | 313 | for (n = DAP_Data.jtag_dev.index; n; n--) { 314 | JTAG_CYCLE_TCK(); /* Bypass before data */ 315 | } 316 | 317 | PIN_TDI_OUT(0U); 318 | JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */ 319 | JTAG_CYCLE_TCK(); /* Set A2=0 */ 320 | JTAG_CYCLE_TCK(); /* Set A3=0 */ 321 | 322 | for (n = 31U; n; n--) { 323 | JTAG_CYCLE_TDI(data); /* Set D0..D30 */ 324 | data >>= 1; 325 | } 326 | n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; 327 | if (n) { 328 | JTAG_CYCLE_TDI(data); /* Set D31 */ 329 | for (--n; n; n--) { 330 | JTAG_CYCLE_TCK(); /* Bypass after data */ 331 | } 332 | PIN_TMS_SET(); 333 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ 334 | } else { 335 | PIN_TMS_SET(); 336 | JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */ 337 | } 338 | 339 | JTAG_CYCLE_TCK(); /* Update-DR */ 340 | PIN_TMS_CLR(); 341 | JTAG_CYCLE_TCK(); /* Idle */ 342 | PIN_TDI_OUT(1U); 343 | } 344 | 345 | 346 | // JTAG Set IR 347 | // ir: IR value 348 | // return: none 349 | void JTAG_IR (uint32_t ir) { 350 | if (DAP_Data.fast_clock) { 351 | JTAG_IR_Fast(ir); 352 | } else { 353 | JTAG_IR_Slow(ir); 354 | } 355 | } 356 | 357 | 358 | // JTAG Transfer I/O 359 | // request: A[3:2] RnW APnDP 360 | // data: DATA[31:0] 361 | // return: ACK[2:0] 362 | uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) { 363 | if (DAP_Data.fast_clock) { 364 | return JTAG_TransferFast(request, data); 365 | } else { 366 | return JTAG_TransferSlow(request, data); 367 | } 368 | } 369 | 370 | 371 | #endif /* (DAP_JTAG != 0) */ 372 | -------------------------------------------------------------------------------- /components/DAP/source/SW_DP.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Source 24 | * Title: SW_DP.c CMSIS-DAP SW DP I/O 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | /** 29 | * @file SW_DP.c 30 | * @author windowsair 31 | * @brief Adaptation of GPIO and SPI 32 | * @change: 33 | * 2021-2-10 Support GPIO and SPI for SWD sequence / SWJ sequence / SWD transfer 34 | * Note: SWD sequence not yet tested 35 | * @version 0.1 36 | * @date 2021-2-10 37 | * 38 | * @copyright Copyright (c) 2021 39 | * 40 | */ 41 | 42 | #include 43 | 44 | #include "components/DAP/config/DAP_config.h" 45 | #include "components/DAP/include/DAP.h" 46 | 47 | #include "components/DAP/include/spi_op.h" 48 | #include "components/DAP/include/spi_switch.h" 49 | 50 | #include "components/DAP/include/dap_utility.h" 51 | 52 | // Debug 53 | #define PRINT_SWD_PROTOCOL 0 54 | 55 | // SW Macros 56 | 57 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 58 | 59 | #define PIN_SWCLK_SET PIN_SWCLK_TCK_SET 60 | #define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR 61 | 62 | // Space for time in the original version, 63 | // and time for space in our implementation 64 | 65 | #define SW_CLOCK_CYCLE() \ 66 | PIN_SWCLK_CLR(); \ 67 | if (need_delay) { PIN_DELAY(); } \ 68 | PIN_SWCLK_SET(); \ 69 | if (need_delay) { PIN_DELAY(); } 70 | 71 | #define SW_WRITE_BIT(bit) \ 72 | PIN_SWDIO_OUT(bit); \ 73 | PIN_SWCLK_CLR(); \ 74 | if (need_delay) { PIN_DELAY(); } \ 75 | PIN_SWCLK_SET(); \ 76 | if (need_delay) { PIN_DELAY(); } 77 | 78 | #define SW_READ_BIT(bit) \ 79 | PIN_SWCLK_CLR(); \ 80 | if (need_delay) { PIN_DELAY(); } \ 81 | bit = PIN_SWDIO_IN(); \ 82 | PIN_SWCLK_SET(); \ 83 | if (need_delay) { PIN_DELAY(); } 84 | 85 | 86 | 87 | uint8_t SWD_TransferSpeed = kTransfer_GPIO_normal; 88 | 89 | 90 | void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay); 91 | void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data); 92 | 93 | void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi); 94 | void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi); 95 | 96 | 97 | // Generate SWJ Sequence 98 | // count: sequence bit count 99 | // data: pointer to sequence bit data 100 | // return: none 101 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 102 | void SWJ_Sequence (uint32_t count, const uint8_t *data) { 103 | // if (count != 8 && count != 16 && count!= 51) 104 | // { 105 | // printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count); 106 | // return; 107 | // } 108 | 109 | if(SWD_TransferSpeed == kTransfer_SPI) { 110 | SWJ_Sequence_SPI(count, data); 111 | } else { 112 | SWJ_Sequence_GPIO(count, data, 1); 113 | } 114 | 115 | } 116 | 117 | 118 | void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay) { 119 | uint32_t val; 120 | uint32_t n; 121 | 122 | val = 0U; 123 | n = 0U; 124 | while (count--) { 125 | if (n == 0U) { 126 | val = *data++; 127 | n = 8U; 128 | } 129 | if (val & 1U) { 130 | PIN_SWDIO_TMS_SET(); 131 | } else { 132 | PIN_SWDIO_TMS_CLR(); 133 | } 134 | SW_CLOCK_CYCLE(); 135 | val >>= 1; 136 | n--; 137 | } 138 | } 139 | 140 | void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data) { 141 | DAP_SPI_Enable(); 142 | DAP_SPI_WriteBits(count, data); 143 | } 144 | #endif 145 | 146 | 147 | // Generate SWD Sequence 148 | // info: sequence information 149 | // swdo: pointer to SWDIO generated data 150 | // swdi: pointer to SWDIO captured data 151 | // return: none 152 | #if (DAP_SWD != 0) 153 | void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { 154 | if (SWD_TransferSpeed == kTransfer_SPI) { 155 | SWD_Sequence_SPI(info, swdo, swdi); 156 | } else { 157 | SWD_Sequence_GPIO(info, swdo, swdi); 158 | } 159 | } 160 | 161 | void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { 162 | const uint8_t need_delay = 1; 163 | 164 | uint32_t val; 165 | uint32_t bit; 166 | uint32_t n, k; 167 | 168 | n = info & SWD_SEQUENCE_CLK; 169 | if (n == 0U) { 170 | n = 64U; 171 | } 172 | // n = 1 ~ 64 173 | 174 | // LSB 175 | if (info & SWD_SEQUENCE_DIN) { 176 | while (n) { 177 | val = 0U; 178 | for (k = 8U; k && n; k--, n--) { 179 | SW_READ_BIT(bit); 180 | val >>= 1; 181 | val |= bit << 7; 182 | } 183 | val >>= k; 184 | *swdi++ = (uint8_t)val; 185 | } 186 | } else { 187 | while (n) { 188 | val = *swdo++; 189 | for (k = 8U; k && n; k--, n--) { 190 | SW_WRITE_BIT(val); 191 | val >>= 1; 192 | } 193 | } 194 | } 195 | } 196 | 197 | void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { 198 | uint32_t n; 199 | n = info & SWD_SEQUENCE_CLK; 200 | if (n == 0U) { 201 | n = 64U; 202 | } 203 | // n = 1 ~ 64 204 | 205 | if (info & SWD_SEQUENCE_DIN) { 206 | DAP_SPI_ReadBits(n, swdi); 207 | } else { 208 | DAP_SPI_WriteBits(n, swdo); 209 | } 210 | } 211 | 212 | #endif 213 | 214 | 215 | #if (DAP_SWD != 0) 216 | 217 | 218 | // SWD Transfer I/O 219 | // request: A[3:2] RnW APnDP 220 | // data: DATA[31:0] 221 | // return: ACK[2:0] 222 | static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) { 223 | //// FIXME: overrun detection 224 | // SPI transfer mode does not require operations such as PIN_DELAY 225 | uint8_t ack; 226 | // uint32_t bit; 227 | uint32_t val; 228 | uint8_t parity; 229 | uint8_t computedParity; 230 | 231 | uint32_t n; 232 | 233 | const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */ 234 | uint8_t requestByte; /* LSB */ 235 | 236 | 237 | DAP_SPI_Enable(); 238 | 239 | requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U); 240 | /* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */ 241 | 242 | #if (PRINT_SWD_PROTOCOL == 1) 243 | switch (requestByte) 244 | { 245 | case 0xA5U: 246 | printf("IDCODE\r\n"); 247 | break; 248 | case 0xA9U: 249 | printf("W CTRL/STAT\r\n"); 250 | break; 251 | case 0xBDU: 252 | printf("RDBUFF\r\n"); 253 | break; 254 | case 0x8DU: 255 | printf("R CTRL/STAT\r\n"); 256 | break; 257 | case 0x81U: 258 | printf("W ABORT\r\n"); 259 | break; 260 | case 0xB1U: 261 | printf("W SELECT\r\n"); 262 | break; 263 | case 0xBBU: 264 | printf("W APc\r\n"); 265 | break; 266 | case 0x9FU: 267 | printf("R APc\r\n"); 268 | break; 269 | case 0x8BU: 270 | printf("W AP4\r\n"); 271 | break; 272 | case 0xA3U: 273 | printf("W AP0\r\n"); 274 | break; 275 | case 0X87U: 276 | printf("R AP0\r\n"); 277 | break; 278 | case 0xB7U: 279 | printf("R AP8\r\n"); 280 | break; 281 | default: 282 | //W AP8 283 | printf("Unknown:%08x\r\n", requestByte); 284 | break; 285 | } 286 | #endif // PRINT_SWD_PROTOCOL == 1 287 | 288 | if (request & DAP_TRANSFER_RnW) { 289 | /* Read data */ 290 | 291 | DAP_SPI_Send_Header(requestByte, &ack, 0); // 0 Trn After ACK 292 | if (ack == DAP_TRANSFER_OK) { 293 | DAP_SPI_Read_Data(&val, &parity); 294 | computedParity = ParityEvenUint32(val); 295 | 296 | if ((computedParity ^ parity) & 1U) { 297 | ack = DAP_TRANSFER_ERROR; 298 | } 299 | if (data) { *data = val; } 300 | 301 | /* Capture Timestamp */ 302 | if (request & DAP_TRANSFER_TIMESTAMP) { 303 | DAP_Data.timestamp = TIMESTAMP_GET(); 304 | } 305 | 306 | } 307 | else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { 308 | DAP_SPI_Fast_Cycle(); 309 | #if (PRINT_SWD_PROTOCOL == 1) 310 | printf("WAIT\r\n"); 311 | #endif 312 | 313 | // return DAP_TRANSFER_WAIT; 314 | } 315 | else { 316 | /* Protocol error */ 317 | DAP_SPI_Disable(); 318 | PIN_SWDIO_TMS_SET(); 319 | 320 | DAP_SPI_Enable(); 321 | DAP_SPI_Protocol_Error_Read(); 322 | 323 | DAP_SPI_Disable(); 324 | PIN_SWDIO_TMS_SET(); 325 | #if (PRINT_SWD_PROTOCOL == 1) 326 | printf("Protocol Error: Read\r\n"); 327 | #endif 328 | } 329 | 330 | return ((uint8_t)ack); 331 | } 332 | else { 333 | /* Write data */ 334 | parity = ParityEvenUint32(*data); 335 | DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK 336 | if (ack == DAP_TRANSFER_OK) { 337 | DAP_SPI_Write_Data(*data, parity); 338 | /* Capture Timestamp */ 339 | if (request & DAP_TRANSFER_TIMESTAMP) { 340 | DAP_Data.timestamp = TIMESTAMP_GET(); 341 | } 342 | /* Idle cycles */ 343 | n = DAP_Data.transfer.idle_cycles; 344 | if (n) { DAP_SPI_Generate_Cycle(n); } 345 | 346 | DAP_SPI_Disable(); 347 | PIN_SWDIO_TMS_SET(); 348 | 349 | return ((uint8_t)ack); 350 | } 351 | else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { 352 | /* already turnaround. */ 353 | 354 | /* TODO: overrun transfer -> for read */ 355 | #if (PRINT_SWD_PROTOCOL == 1) 356 | printf("WAIT\r\n"); 357 | #endif 358 | 359 | } 360 | else { 361 | /* Protocol error */ 362 | DAP_SPI_Disable(); 363 | PIN_SWDIO_TMS_SET(); 364 | 365 | DAP_SPI_Enable(); 366 | DAP_SPI_Protocol_Error_Write(); 367 | 368 | DAP_SPI_Disable(); 369 | PIN_SWDIO_TMS_SET(); 370 | 371 | #if (PRINT_SWD_PROTOCOL == 1) 372 | printf("Protocol Error: Write\r\n"); 373 | #endif 374 | } 375 | 376 | return ((uint8_t)ack); 377 | 378 | } 379 | 380 | return DAP_TRANSFER_ERROR; 381 | } 382 | 383 | 384 | 385 | static uint8_t SWD_Transfer_GPIO (uint32_t request, uint32_t *data, uint8_t need_delay) { 386 | uint32_t ack; 387 | uint32_t bit; 388 | uint32_t val; 389 | uint32_t parity; 390 | 391 | uint32_t n; 392 | 393 | /* Packet Request */ 394 | parity = 0U; 395 | SW_WRITE_BIT(1U); /* Start Bit */ 396 | bit = request >> 0; 397 | SW_WRITE_BIT(bit); /* APnDP Bit */ 398 | parity += bit; 399 | bit = request >> 1; 400 | SW_WRITE_BIT(bit); /* RnW Bit */ 401 | parity += bit; 402 | bit = request >> 2; 403 | SW_WRITE_BIT(bit); /* A2 Bit */ 404 | parity += bit; 405 | bit = request >> 3; 406 | SW_WRITE_BIT(bit); /* A3 Bit */ 407 | parity += bit; 408 | SW_WRITE_BIT(parity); /* Parity Bit */ 409 | SW_WRITE_BIT(0U); /* Stop Bit */ 410 | SW_WRITE_BIT(1U); /* Park Bit */ 411 | 412 | /* Turnaround */ 413 | PIN_SWDIO_OUT_DISABLE(); 414 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { 415 | SW_CLOCK_CYCLE(); 416 | } 417 | 418 | /* Acknowledge response */ 419 | SW_READ_BIT(bit); 420 | ack = bit << 0; 421 | SW_READ_BIT(bit); 422 | ack |= bit << 1; 423 | SW_READ_BIT(bit); 424 | ack |= bit << 2; 425 | 426 | if (ack == DAP_TRANSFER_OK) { /* OK response */ 427 | /* Data transfer */ 428 | if (request & DAP_TRANSFER_RnW) { 429 | /* Read data */ 430 | val = 0U; 431 | parity = 0U; 432 | for (n = 32U; n; n--) { 433 | SW_READ_BIT(bit); /* Read RDATA[0:31] */ 434 | parity += bit; 435 | val >>= 1; 436 | val |= bit << 31; 437 | } 438 | SW_READ_BIT(bit); /* Read Parity */ 439 | if ((parity ^ bit) & 1U) { 440 | ack = DAP_TRANSFER_ERROR; 441 | } 442 | if (data) { *data = val; } 443 | /* Turnaround */ 444 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { 445 | SW_CLOCK_CYCLE(); 446 | } 447 | PIN_SWDIO_OUT_ENABLE(); 448 | } else { 449 | /* Turnaround */ 450 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { 451 | SW_CLOCK_CYCLE(); 452 | } 453 | PIN_SWDIO_OUT_ENABLE(); 454 | /* Write data */ 455 | val = *data; 456 | parity = 0U; 457 | for (n = 32U; n; n--) { 458 | SW_WRITE_BIT(val); /* Write WDATA[0:31] */ 459 | parity += val; 460 | val >>= 1; 461 | } 462 | SW_WRITE_BIT(parity); /* Write Parity Bit */ 463 | } 464 | /* Capture Timestamp */ 465 | if (request & DAP_TRANSFER_TIMESTAMP) { 466 | DAP_Data.timestamp = TIMESTAMP_GET(); 467 | } 468 | /* Idle cycles */ 469 | n = DAP_Data.transfer.idle_cycles; 470 | if (n) { 471 | PIN_SWDIO_OUT(0U); 472 | for (; n; n--) { 473 | SW_CLOCK_CYCLE(); 474 | } 475 | } 476 | PIN_SWDIO_OUT(1U); 477 | return ((uint8_t)ack); 478 | } 479 | 480 | if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { 481 | /* WAIT or FAULT response */ 482 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) { 483 | for (n = 32U+1U; n; n--) { 484 | SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ 485 | } 486 | } 487 | /* Turnaround */ 488 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { 489 | SW_CLOCK_CYCLE(); 490 | } 491 | PIN_SWDIO_OUT_ENABLE(); 492 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) { 493 | PIN_SWDIO_OUT(0U); 494 | for (n = 32U+1U; n; n--) { 495 | SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ 496 | } 497 | } 498 | PIN_SWDIO_OUT(1U); 499 | return ((uint8_t)ack); 500 | } 501 | 502 | /* Protocol error */ 503 | for (n = DAP_Data.swd_conf.turnaround + 32U + 1U; n; n--) { 504 | SW_CLOCK_CYCLE(); /* Back off data phase */ 505 | } 506 | PIN_SWDIO_OUT_ENABLE(); 507 | PIN_SWDIO_OUT(1U); 508 | return ((uint8_t)ack); 509 | } 510 | 511 | 512 | // SWD Transfer I/O 513 | // request: A[3:2] RnW APnDP 514 | // data: DATA[31:0] 515 | // return: ACK[2:0] 516 | uint8_t SWD_Transfer(uint32_t request, uint32_t *data) { 517 | switch (SWD_TransferSpeed) { 518 | case kTransfer_SPI: 519 | return SWD_Transfer_SPI(request, data); 520 | case kTransfer_GPIO_fast: 521 | return SWD_Transfer_GPIO(request, data, 0); 522 | case kTransfer_GPIO_normal: 523 | return SWD_Transfer_GPIO(request, data, 1); 524 | default: 525 | return SWD_Transfer_GPIO(request, data, 1); 526 | } 527 | } 528 | 529 | 530 | #endif /* (DAP_SWD != 0) */ 531 | -------------------------------------------------------------------------------- /components/DAP/source/dap_utility.c: -------------------------------------------------------------------------------- 1 | #include "components/DAP/include/dap_utility.h" 2 | 3 | 4 | const uint8_t kParityByteTable[256] = 5 | { 6 | #define P2(n) n, n^1, n^1, n 7 | #define P4(n) P2(n), P2(n^1), P2(n^1), P2(n) 8 | #define P6(n) P4(n), P4(n^1), P4(n^1), P4(n) 9 | 10 | P6(0), P6(1), P6(1), P6(0) 11 | }; 12 | -------------------------------------------------------------------------------- /components/DAP/source/spi_op.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file spi_op.c 3 | * @author windowsair 4 | * @brief Using SPI for common transfer operations 5 | * @change: 2021-3-7 Support esp32 SPI 6 | * 2021-3-10 Support 3-wire spi 7 | * @version 0.2 8 | * @date 2021-3-10 9 | * 10 | * @copyright Copyright (c) 2021 11 | * 12 | */ 13 | #include 14 | 15 | 16 | #include "components/DAP/include/cmsis_compiler.h" 17 | 18 | #include "components/DAP/include/spi_op.h" 19 | #include "components/DAP/include/spi_switch.h" 20 | 21 | // soc register 22 | #include "esp32/rom/gpio.h" 23 | #include "esp32/include/soc/gpio_struct.h" 24 | #include "hal/gpio_types.h" 25 | 26 | #include "esp32/include/soc/dport_access.h" 27 | #include "esp32/include/soc/dport_reg.h" 28 | #include "esp32/include/soc/periph_defs.h" 29 | #include "esp32/include/soc/spi_struct.h" 30 | #include "esp32/include/soc/spi_reg.h" 31 | 32 | //// FIXME: esp32 33 | #define DAP_SPI SPI2 34 | 35 | /** 36 | * @brief Calculate integer division and round up 37 | * 38 | * @param A 39 | * @param B 40 | * @return result 41 | */ 42 | __STATIC_FORCEINLINE int div_round_up(int A, int B) 43 | { 44 | return (A + B - 1) / B; 45 | } 46 | 47 | 48 | /** 49 | * @brief Write bits. LSB & little-endian 50 | * Note: No check. The pointer must be valid. 51 | * @param count Number of bits to be written (<= 64 bits, no length check) 52 | * @param buf Data Buf 53 | */ 54 | void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf) 55 | { 56 | DAP_SPI.user.usr_command = 0; 57 | DAP_SPI.user.usr_addr = 0; 58 | 59 | // have data to send 60 | DAP_SPI.user.usr_mosi = 1; 61 | DAP_SPI.mosi_dlen.usr_mosi_dbitlen = count - 1; 62 | // copy data to reg 63 | switch (count) 64 | { 65 | case 8: 66 | DAP_SPI.data_buf[0] = (buf[0] << 0) | (0U << 8) | (0U << 16) | (0U << 24); 67 | break; 68 | case 16: 69 | DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (0x000U << 16) | (0x000U << 24); 70 | break; 71 | case 33: // 32bits data & 1 bit parity 72 | DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 73 | DAP_SPI.data_buf[1] = (buf[4] << 0) | (0x000U << 8) | (0x000U << 16) | (0x000U << 24); 74 | break; 75 | case 51: // for line reset 76 | DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); 77 | DAP_SPI.data_buf[1] = (buf[4] << 0) | (buf[5] << 8) | (buf[2] << 16) | (0x000U << 24); 78 | break; 79 | default: 80 | { 81 | uint32_t data_buf[2]; 82 | uint8_t *pData = (uint8_t *)data_buf; 83 | int i; 84 | 85 | for (i = 0; i < div_round_up(count, 8); i++) 86 | { 87 | pData[i] = buf[i]; 88 | } 89 | // last byte use mask: 90 | pData[i-1] = pData[i-1] & ((2U >> (count % 8)) - 1U); 91 | 92 | DAP_SPI.data_buf[0] = data_buf[0]; 93 | DAP_SPI.data_buf[1] = data_buf[1]; 94 | } 95 | } 96 | 97 | // Start transmission 98 | DAP_SPI.cmd.usr = 1; 99 | // Wait for sending to complete 100 | while (DAP_SPI.cmd.usr) continue; 101 | } 102 | 103 | 104 | 105 | /** 106 | * @brief Read bits. LSB & little-endian 107 | * Note: No check. The pointer must be valid. 108 | * @param count Number of bits to be read (<= 64 bits, no length check) 109 | * @param buf Data Buf 110 | */ 111 | void DAP_SPI_ReadBits(const uint8_t count, uint8_t *buf) { 112 | int i; 113 | uint32_t data_buf[2]; 114 | 115 | uint8_t * pData = (uint8_t *)data_buf; 116 | 117 | DAP_SPI.user.usr_mosi = 0; 118 | DAP_SPI.user.usr_miso = 1; 119 | 120 | DAP_SPI.user.sio = true; 121 | DAP_SPI.miso_dlen.usr_miso_dbitlen = count - 1U; 122 | 123 | // Start transmission 124 | DAP_SPI.cmd.usr = 1; 125 | // Wait for reading to complete 126 | while (DAP_SPI.cmd.usr) continue; 127 | 128 | DAP_SPI.user.sio = false; 129 | 130 | data_buf[0] = DAP_SPI.data_buf[0]; 131 | data_buf[1] = DAP_SPI.data_buf[1]; 132 | 133 | for (i = 0; i < div_round_up(count, 8); i++) 134 | { 135 | buf[i] = pData[i]; 136 | } 137 | // last byte use mask: 138 | buf[i-1] = buf[i-1] & ((2 >> (count % 8)) - 1); 139 | } 140 | 141 | 142 | /** 143 | * @brief Step1: Packet Request 144 | * 145 | * @param packetHeaderData data from host 146 | * @param ack ack from target 147 | * @param TrnAfterACK num of trn after ack 148 | */ 149 | __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *ack, uint8_t TrnAfterACK) 150 | { 151 | volatile uint32_t dataBuf; 152 | 153 | // have data to send 154 | DAP_SPI.user.usr_mosi = 1; 155 | DAP_SPI.mosi_dlen.usr_mosi_dbitlen = 8 - 1; 156 | 157 | DAP_SPI.user.usr_miso = 1; 158 | 159 | DAP_SPI.user.sio = true; 160 | 161 | // 1 bit Trn(Before ACK) + 3bits ACK + TrnAferACK - 1(prescribed) 162 | DAP_SPI.miso_dlen.usr_miso_dbitlen = 1U + 3U + TrnAfterACK - 1U; 163 | 164 | // copy data to reg 165 | DAP_SPI.data_buf[0] = (packetHeaderData << 0) | (0U << 8) | (0U << 16) | (0U << 24); 166 | 167 | // Start transmission 168 | DAP_SPI.cmd.usr = 1; 169 | // Wait for sending to complete 170 | while (DAP_SPI.cmd.usr) continue; 171 | 172 | DAP_SPI.user.sio = false; 173 | 174 | dataBuf = DAP_SPI.data_buf[0]; 175 | *ack = (dataBuf >> 1) & 0b111; 176 | } 177 | 178 | 179 | /** 180 | * @brief Step2: Read Data 181 | * 182 | * @param resData data from target 183 | * @param resParity parity from target 184 | */ 185 | __FORCEINLINE void DAP_SPI_Read_Data(uint32_t *resData, uint8_t *resParity) 186 | { 187 | volatile uint64_t dataBuf; 188 | uint32_t *pU32Data = (uint32_t *)&dataBuf; 189 | 190 | DAP_SPI.user.usr_mosi = 0; 191 | DAP_SPI.user.usr_miso = 1; 192 | 193 | DAP_SPI.user.sio = true; 194 | 195 | // 1 bit Trn(End) + 3bits ACK + 32bis data + 1bit parity - 1(prescribed) 196 | DAP_SPI.miso_dlen.usr_miso_dbitlen = 1U + 32U + 1U - 1U; 197 | 198 | // Start transmission 199 | DAP_SPI.cmd.usr = 1; 200 | // Wait for sending to complete 201 | while (DAP_SPI.cmd.usr) continue; 202 | 203 | pU32Data[0] = DAP_SPI.data_buf[0]; 204 | pU32Data[1] = DAP_SPI.data_buf[1]; 205 | 206 | DAP_SPI.user.sio = false; 207 | 208 | *resData = (dataBuf >> 0U) & 0xFFFFFFFFU; // 32bits Response Data 209 | *resParity = (dataBuf >> (0U + 32U)) & 1U; // 3bits ACK + 32bis data 210 | } 211 | 212 | /** 213 | * @brief Step2: Write Data 214 | * 215 | * @param data data from host 216 | * @param parity parity from host 217 | */ 218 | __FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity) 219 | { 220 | DAP_SPI.user.usr_mosi = 1; 221 | DAP_SPI.user.usr_miso = 0; 222 | 223 | DAP_SPI.mosi_dlen.usr_mosi_dbitlen = 32U + 1U - 1U; // 32bis data + 1bit parity - 1(prescribed) 224 | 225 | // copy data to reg 226 | DAP_SPI.data_buf[0] = data; 227 | DAP_SPI.data_buf[1] = parity; 228 | 229 | // Start transmission 230 | DAP_SPI.cmd.usr = 1; 231 | // Wait for sending to complete 232 | while (DAP_SPI.cmd.usr) continue; 233 | } 234 | 235 | /** 236 | * @brief Generate Clock Cycle 237 | * 238 | * @param num Cycle Num 239 | */ 240 | __FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num) 241 | { 242 | //// TODO: It may take long time to generate just one clock 243 | DAP_SPI.user.usr_mosi = 1; 244 | DAP_SPI.user.usr_miso = 0; 245 | DAP_SPI.mosi_dlen.usr_mosi_dbitlen = num - 1U; 246 | 247 | DAP_SPI.data_buf[0] = 0x00000000U; 248 | 249 | // Start transmission 250 | DAP_SPI.cmd.usr = 1; 251 | // Wait for sending to complete 252 | // while (DAP_SPI.cmd.usr) continue; 253 | // 200us reduce 254 | } 255 | 256 | /** 257 | * @brief Quickly generate 1 clock 258 | * 259 | */ 260 | __FORCEINLINE void DAP_SPI_Fast_Cycle() 261 | { 262 | DAP_SPI_Release(); 263 | DAP_SPI_Acquire(); 264 | } 265 | 266 | 267 | /** 268 | * @brief Generate Protocol Error Cycle 269 | * 270 | */ 271 | __FORCEINLINE void DAP_SPI_Protocol_Error_Read() 272 | { 273 | DAP_SPI.user.usr_mosi = 1; 274 | DAP_SPI.user.usr_miso = 0; 275 | DAP_SPI.mosi_dlen.usr_mosi_dbitlen = 32U + 1U - 1; // 32bit ignore data + 1 bit - 1(prescribed) 276 | 277 | DAP_SPI.data_buf[0] = 0xFFFFFFFFU; 278 | DAP_SPI.data_buf[1] = 0xFFFFFFFFU; 279 | 280 | // Start transmission 281 | DAP_SPI.cmd.usr = 1; 282 | // Wait for sending to complete 283 | while (DAP_SPI.cmd.usr) continue; 284 | } 285 | 286 | 287 | /** 288 | * @brief Generate Protocol Error Cycle 289 | * 290 | */ 291 | __FORCEINLINE void DAP_SPI_Protocol_Error_Write() 292 | { 293 | DAP_SPI.user.usr_mosi = 1; 294 | DAP_SPI.user.usr_miso = 0; 295 | DAP_SPI.mosi_dlen.usr_mosi_dbitlen = 1U + 32U + 1U - 1; // 1bit Trn + 32bit ignore data + 1 bit - 1(prescribed) 296 | 297 | DAP_SPI.data_buf[0] = 0xFFFFFFFFU; 298 | DAP_SPI.data_buf[1] = 0xFFFFFFFFU; 299 | 300 | // Start transmission 301 | DAP_SPI.cmd.usr = 1; 302 | // Wait for sending to complete 303 | while (DAP_SPI.cmd.usr) continue; 304 | } 305 | -------------------------------------------------------------------------------- /components/DAP/source/spi_switch.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file spi_switch.c 3 | * @author windowsair 4 | * @brief Switching between SPI mode and IO mode 5 | * @change: 2021-3-7 Support esp32 SPI 6 | * 2021-3-20 Fix pure GPIO and problem of mode switching 7 | * @version 0.2 8 | * @date 2021-3-20 9 | * 10 | * @copyright Copyright (c) 2021 11 | * 12 | */ 13 | #include 14 | 15 | #include "components/DAP/include/cmsis_compiler.h" 16 | #include "components/DAP/include/spi_switch.h" 17 | 18 | // soc register 19 | #include "esp32/rom/gpio.h" 20 | #include "esp32/include/soc/gpio_struct.h" 21 | #include "hal/gpio_types.h" 22 | 23 | #include "esp32/include/soc/dport_access.h" 24 | #include "esp32/include/soc/dport_reg.h" 25 | #include "esp32/include/soc/periph_defs.h" 26 | #include "esp32/include/soc/spi_struct.h" 27 | #include "esp32/include/soc/spi_reg.h" 28 | 29 | //// FIXME: esp32 30 | #define DAP_SPI SPI2 31 | 32 | #define ENTER_CRITICAL() portENTER_CRITICAL() 33 | #define EXIT_CRITICAL() portEXIT_CRITICAL() 34 | 35 | // Note that the index starts at 0, so we are using function 2(SPI). 36 | #define FUNC_SPI 1 37 | 38 | #define SPI2_HOST 1 39 | 40 | #define SPI_LL_RST_MASK (SPI_OUT_RST | SPI_IN_RST | SPI_AHBM_RST | SPI_AHBM_FIFO_RST) 41 | 42 | 43 | typedef enum { 44 | SPI_40MHz_DIV = 2, 45 | // SPI_80MHz_DIV = 1, //// FIXME: high speed clock 46 | } spi_clk_div_t; 47 | 48 | 49 | /** 50 | * @brief Initialize on first use 51 | * 52 | */ 53 | void DAP_SPI_Init() 54 | { 55 | // In esp32, the driving of GPIO should be stopped, 56 | // otherwise there will be issue in the spi 57 | GPIO.out_w1tc = (0x1 << 13); 58 | GPIO.out_w1tc = (0x1 << 14); 59 | 60 | // Enable spi module, We use SPI2(HSPI) 61 | DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI2_CLK_EN); 62 | DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI2_RST); 63 | 64 | 65 | // We will use IO_MUX to get the maximum speed. 66 | GPIO.func_in_sel_cfg[HSPID_IN_IDX].sig_in_sel = 0; // IO_MUX direct connnect 67 | PIN_INPUT_ENABLE(IO_MUX_GPIO13_REG); // MOSI 68 | GPIO.func_out_sel_cfg[13].oen_sel = 0; // use output enable signal from peripheral 69 | GPIO.func_out_sel_cfg[13].oen_inv_sel = 0; // do not invert the output value 70 | PIN_FUNC_SELECT(IO_MUX_GPIO13_REG, FUNC_SPI); 71 | 72 | // GPIO.func_in_sel_cfg[HSPIQ_IN_IDX].sig_in_sel = 0; 73 | // PIN_INPUT_ENABLE(IO_MUX_GPIO12_REG); // MISO 74 | // GPIO.func_out_sel_cfg[12].oen_sel = 0; 75 | // GPIO.func_out_sel_cfg[12].oen_inv_sel = 0; 76 | // PIN_FUNC_SELECT(IO_MUX_GPIO12_REG, FUNC_SPI); 77 | 78 | GPIO.func_in_sel_cfg[HSPICLK_IN_IDX].sig_in_sel = 0; 79 | PIN_INPUT_ENABLE(IO_MUX_GPIO14_REG); // SCLK 80 | GPIO.func_out_sel_cfg[14].oen_sel = 0; 81 | GPIO.func_out_sel_cfg[14].oen_inv_sel = 0; 82 | PIN_FUNC_SELECT(IO_MUX_GPIO14_REG, FUNC_SPI); 83 | 84 | 85 | // Not using DMA 86 | // esp32 only 87 | DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, 0, (SPI2_HOST * 2)); 88 | 89 | 90 | // Reset DMA 91 | DAP_SPI.dma_conf.val |= SPI_LL_RST_MASK; 92 | DAP_SPI.dma_out_link.start = 0; 93 | DAP_SPI.dma_in_link.start = 0; 94 | DAP_SPI.dma_conf.val &= ~SPI_LL_RST_MASK; 95 | // Disable DMA 96 | DAP_SPI.dma_conf.dma_continue = 0; 97 | 98 | 99 | // Set to Master mode 100 | DAP_SPI.slave.slave_mode = false; 101 | 102 | 103 | // use all 64 bytes of the buffer 104 | DAP_SPI.user.usr_mosi_highpart = false; 105 | DAP_SPI.user.usr_miso_highpart = false; 106 | 107 | 108 | // Disable cs pin 109 | DAP_SPI.user.cs_setup = false; 110 | DAP_SPI.user.cs_hold = false; 111 | 112 | // Disable CS signal 113 | DAP_SPI.pin.cs0_dis = 1; 114 | DAP_SPI.pin.cs1_dis = 1; 115 | DAP_SPI.pin.cs2_dis = 1; 116 | 117 | // Duplex transmit 118 | DAP_SPI.user.doutdin = false; // half dulex 119 | 120 | 121 | // Set data bit order 122 | DAP_SPI.ctrl.wr_bit_order = 1; // SWD -> LSB 123 | DAP_SPI.ctrl.rd_bit_order = 1; // SWD -> LSB 124 | // Set data byte order 125 | DAP_SPI.user.wr_byte_order = 0; // SWD -> litte_endian && Risc V -> litte_endian 126 | DAP_SPI.user.rd_byte_order = 0; // SWD -> litte_endian && Risc V -> litte_endian 127 | 128 | // Set dummy 129 | DAP_SPI.user.usr_dummy = 0; // not use 130 | 131 | // Set spi clk: 40Mhz 50% duty 132 | // CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK); 133 | 134 | // See esp32 TRM `SPI_CLOCK_REG` 135 | DAP_SPI.clock.clk_equ_sysclk = false; 136 | DAP_SPI.clock.clkdiv_pre = 0; 137 | DAP_SPI.clock.clkcnt_n = SPI_40MHz_DIV - 1; 138 | DAP_SPI.clock.clkcnt_h = SPI_40MHz_DIV / 2 - 1; 139 | DAP_SPI.clock.clkcnt_l = SPI_40MHz_DIV - 1; 140 | // Dummy is not required, but it may still need to be delayed 141 | // by half a clock cycle (espressif) 142 | 143 | 144 | // MISO delay setting 145 | DAP_SPI.user.ck_i_edge = true; //// TODO: may be used in slave mode? 146 | DAP_SPI.ctrl2.miso_delay_mode = 0; 147 | DAP_SPI.ctrl2.miso_delay_num = 0; 148 | 149 | 150 | // Set the clock polarity and phase CPOL = CPHA = 1 151 | DAP_SPI.pin.ck_idle_edge = 1; // HIGH while idle 152 | DAP_SPI.user.ck_out_edge = 0; 153 | 154 | // No command and addr for now 155 | DAP_SPI.user.usr_command = 0; 156 | DAP_SPI.user.usr_addr = 0; 157 | } 158 | 159 | 160 | /** 161 | * @brief Switch to GPIO 162 | * Note: You may be able to pull the pin high in SPI mode, though you cannot set it to LOW 163 | */ 164 | __FORCEINLINE void DAP_SPI_Deinit() 165 | { 166 | PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[14], PIN_FUNC_GPIO); 167 | PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[13], PIN_FUNC_GPIO); // MOSI 168 | //PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[12], PIN_FUNC_GPIO); // MISO 169 | 170 | // enable SWCLK output 171 | GPIO.enable_w1ts = (0x01 << 14); 172 | 173 | // disable MISO output connect 174 | // GPIO.enable_w1tc = (0x1 << 12); 175 | 176 | // enable MOSI output & input 177 | GPIO.enable_w1ts |= (0x1 << 13); 178 | PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[13]); 179 | 180 | // enable MOSI OD output 181 | //GPIO.pin[13].pad_driver = 1; 182 | 183 | // disable MOSI pull up 184 | // REG_CLR_BIT(GPIO_PIN_MUX_REG[13], FUN_PU); 185 | } 186 | 187 | 188 | /** 189 | * @brief Gain control of SPI 190 | * 191 | */ 192 | __FORCEINLINE void DAP_SPI_Acquire() 193 | { 194 | PIN_FUNC_SELECT(IO_MUX_GPIO14_REG, FUNC_SPI); 195 | } 196 | 197 | 198 | /** 199 | * @brief Release control of SPI 200 | * 201 | */ 202 | __FORCEINLINE void DAP_SPI_Release() 203 | { 204 | PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[14], PIN_FUNC_GPIO); 205 | GPIO.enable_w1ts = (0x01 << 14); 206 | } 207 | 208 | 209 | /** 210 | * @brief Use SPI acclerate 211 | * 212 | */ 213 | void DAP_SPI_Enable() 214 | { 215 | // may be unuse 216 | //// FIXME: esp32 nop? 217 | //PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out) 218 | } 219 | 220 | 221 | /** 222 | * @brief Disable SPI 223 | * Drive capability not yet known 224 | */ 225 | __FORCEINLINE void DAP_SPI_Disable() 226 | { 227 | ; 228 | //CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_MTCK_U, (PERIPHS_IO_MUX_FUNC << PERIPHS_IO_MUX_FUNC_S)); 229 | // may be unuse 230 | // gpio_pin_reg_t pin_reg; 231 | // GPIO.enable_w1ts |= (0x1 << 13); 232 | // GPIO.pin[13].driver = 0; // OD Output 233 | // pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13)); 234 | // pin_reg.pullup = 1; 235 | // WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val); 236 | } 237 | 238 | -------------------------------------------------------------------------------- /components/README.md: -------------------------------------------------------------------------------- 1 | # done: 2 | 3 | `PIN_SWDIO_TMS_IN` 4 | `PIN_SWDIO_IN` 5 | `PIN_TDI_IN` 6 | `PIN_nRESET_IN` 7 | 8 | `PIN_SWCLK_TCK_SET` 9 | `PIN_SWCLK_TCK_CLR` 10 | 11 | `PIN_SWDIO_TMS_SET` 12 | `PIN_SWDIO_TMS_CLR` 13 | 14 | `PIN_SWDIO_OUT_DISABLE` 15 | 16 | `PIN_TDI_OUT` 17 | 18 | `PIN_nRESET_OUT` 19 | 20 | `LED_CONNECTED_OUT` 21 | `LED_RUNNING_OUT` 22 | 23 | `DAP_SETUP` 24 | 25 | `PIN_TDO_IN` 26 | 27 | 28 | `PORT_JTAG_SETUP` 29 | `PIN_SWCLK_TCK_IN` 30 | 31 | `PIN_SWDIO_OUT` 32 | 33 | 34 | 35 | # todo: 36 | 37 | 38 | 39 | `TIMESTAMP_GET` 40 | 41 | `PORT_OFF` 42 | `PORT_SWD_SETUP` 43 | 44 | # bug? 45 | 46 | `PIN_SWDIO_OUT_ENABLE` 47 | 48 | `PIN_nTRST_IN` -------------------------------------------------------------------------------- /components/USBIP/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_ADD_INCLUDEDIRS ". ../../main") 2 | set(COMPONENT_SRCS "MSOS20_descriptor.c USB_handle.c USB_descriptor.c") 3 | 4 | register_component() -------------------------------------------------------------------------------- /components/USBIP/MSOS20_descriptor.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MSOS20_descriptor.c 3 | * @author windowsair 4 | * @brief Store related data of Microsoft OS 2.0 descriptor 5 | * @version 0.1 6 | * @date 2019-11-21 7 | * 8 | * @copyright Copyright (c) 2019 9 | * 10 | */ 11 | 12 | ////TODO: refactoring into structure 13 | 14 | #include 15 | 16 | #include "components/USBIP/MSOS20_descriptor.h" 17 | 18 | #define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) 19 | 20 | 21 | 22 | // Microsoft OS 2.0 descriptor set header 23 | const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20] = 24 | { 25 | // Microsoft OS 2.0 Descriptor Set header (Table 10) 26 | 0x0A, 0x00, // wLength (Shall be set to 0x0A) 27 | MS_OS_20_SET_HEADER_DESCRIPTOR, 0x00, 28 | 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) 29 | USBShort(kLengthOfMsOS20), // wTotalLength 30 | 31 | // Support WinUSB 32 | // See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/automatic-installation-of-winusb 33 | 34 | // Microsoft OS 2.0 compatible ID descriptor (Table 13) 35 | 0x14, 0x00, // wLength 36 | USBShort(MS_OS_20_FEATURE_COMPATIBLE_ID), // wDescriptorType 37 | 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleID 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompatibleID 39 | 40 | // Microsoft OS 2.0 registry property descriptor (Table 14) 41 | 0x84, 0x00, // wLength 42 | USBShort(MS_OS_20_FEATURE_REG_PROPERTY), 43 | 0x07, 0x00, // wPropertyDataType: REG_MULTI_SZ (Unicode Strings) 44 | 0x2A, 0x00, // wPropertyNameLength 45 | 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0, 46 | 'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,'s',0,0,0, 47 | // Set to "DeviceInterfaceGUID" to support WinUSB 48 | 0x50, 0x00, // wPropertyDataLength 49 | // WinUSB GUID 50 | '{',0,'C',0,'D',0,'B',0,'3',0,'B',0,'5',0,'A',0,'D',0,'-',0, 51 | '2',0,'9',0,'3',0,'B',0,'-',0,'4',0,'6',0,'6',0,'3',0,'-',0, 52 | 'A',0,'A',0,'3',0,'6',0,'-',0,'1',0,'A',0,'A',0,'E',0,'4',0, 53 | '6',0,'4',0,'6',0,'3',0,'7',0,'7',0,'6',0,'}',0,0,0,0,0, 54 | // identify a CMSIS-DAP V2 configuration, 55 | // must set to "{CDB3B5AD-293B-4663-AA36-1AAE46463776}" 56 | 57 | }; 58 | 59 | const uint8_t bosDescriptor[kLengthOfBos] = 60 | { 61 | // Universal Serial Bus 3.0 Specification, Table 9-9. 62 | 0x05, // bLength of this descriptor 63 | USB_DESCRIPTOR_TYPE_BOS, // BOS Descriptor type(Constant) 64 | USBShort(kLengthOfBos), // wLength 65 | 0x03, // bNumDeviceCaps -> only 0x01 for OS2.0 descriptor 66 | 67 | // USB 2.0 extension 68 | 0x07, /* Descriptor size */ 69 | USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY, /* Device capability type descriptor */ 70 | USB_DEVICE_CAPABILITY_TYPE_USB2_0_EXTENSION, /* USB 2.0 extension capability type */ 71 | 0x02, 0x00, 0x00, 0x00, /* Supported device level features: LPM support */ 72 | 73 | /* SuperSpeed device capability */ 74 | 0x0A, /* Descriptor size */ 75 | USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY, /* Device capability type descriptor */ 76 | USB_DEVICE_CAPABILITY_TYPE_SUPERSPEED_USB, /* SuperSpeed device capability type */ 77 | 0x00, /* Supported device level features(LTM Capable) */ 78 | 0x08, 0x00, /* Speeds supported by the device : SS, ~~HS~ and ~~FS~~ */ 79 | 0x03, /* Functionality support */ 80 | 0x00, /* U1 Device Exit latency */ 81 | 0x00, 0x00, /* U2 Device Exit latency */ 82 | 83 | 84 | 85 | 86 | // Microsoft OS 2.0 platform capability descriptor header (Table 4) 87 | // See also: 88 | // Universal Serial Bus 3.0 Specification : Format of a Device Capability Descriptor, Table 9-10. 89 | 90 | 0x1C, // bLength of this first device capability descriptor 91 | // bLength -> The total length of the remaining arrays containing this field 92 | USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY, // bDescriptorType 93 | USB_DEVICE_CAPABILITY_TYPE_PLATFORM, // bDevCapabilityType 94 | 95 | // Capability-Dependent (See USB3.0 Specification Table 9-10.) 96 | 0x00, // bReserved 97 | USB_DEVICE_CAPABILITY_UUID, // MS_OS_20_Platform_Capability_ID 98 | 99 | 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) 100 | USBShort(kLengthOfMsOS20), // wMSOSDescriptorSetTotalLength(length of descriptor set header) 101 | kValueOfbMS_VendorCode, // bMS_VendorCode (0x01 will be ok) 102 | ////TODO:change this 103 | 0, // bAltEnumCode 104 | }; -------------------------------------------------------------------------------- /components/USBIP/MSOS20_descriptor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file MSOS20_descriptor.h 3 | * @author windowsair 4 | * @brief 5 | * @version 0.1 6 | * @date 2019-11-21 7 | * 8 | * @copyright Copyright (c) 2019 9 | * 10 | */ 11 | 12 | #ifndef __MSOS20_DESCRIPTOR_H__ 13 | #define __MSOS20_DESCRIPTOR_H__ 14 | 15 | #define kLengthOfMsOS20 0xA2 16 | #define kLengthOfBos 0x32 17 | #define kValueOfbMS_VendorCode 0x01// Just set to 0x01 18 | extern const uint8_t bosDescriptor[kLengthOfBos]; 19 | extern const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20]; 20 | 21 | /* Microsoft OS 2.0 Descriptors BEGIN */ 22 | 23 | // Platform capability BOS descriptor, Table 1. 24 | #define USB_DEVICE_CAPABILITY_TYPE_PLATFORM 5 25 | 26 | // USB 2.0 Extension Descriptor, USB3.0 Specification Table 9-11 27 | #define USB_DEVICE_CAPABILITY_TYPE_USB2_0_EXTENSION 2 28 | // SuperSpeed USB specific device level capabilities, USB3.0 Specification Table 9-11 29 | #define USB_DEVICE_CAPABILITY_TYPE_SUPERSPEED_USB 3 30 | 31 | // Platform capability UUID, Table 3. 32 | // {D8DD60DF-4589-4CC7-9CD2-659D9E648A9F} 33 | #define USB_DEVICE_CAPABILITY_UUID 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F 34 | 35 | 36 | // Microsoft OS 2.0 descriptor wIndex values enum, Table 8. 37 | #define MS_OS_20_DESCRIPTOR_INDEX 7 38 | #define MS_OS_20_SET_ALT_ENUMERATION 8 39 | 40 | 41 | // Microsoft OS 2.0 descriptor types enum for wDescriptorType values, Table 9. 42 | #define MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 43 | #define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 44 | #define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 45 | #define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 46 | #define MS_OS_20_FEATURE_REG_PROPERTY 0x04 47 | #define MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 48 | #define MS_OS_20_FEATURE_MODEL_ID 0x06 49 | #define MS_OS_20_FEATURE_CCGP_DEVICE 0x07 50 | 51 | /* Microsoft OS 2.0 Descriptors END */ 52 | 53 | 54 | 55 | /* Wireless USB Standard Extension Descriptor Types BEGIN */ 56 | 57 | // Wireless USB Specification 1.1 revison 1.1, Table 7-21. 58 | #define USB_DESCRIPTOR_TYPE_SECURITY 12 59 | #define USB_DESCRIPTOR_TYPE_KEY 13 60 | #define USB_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 14 61 | #define USB_DESCRIPTOR_TYPE_BOS 15 62 | #define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 16 63 | #define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMPANION 17 64 | 65 | /* Wireless USB Standard Extension Descriptor Types END */ 66 | 67 | 68 | /* Microsoft Extended Compat ID OS Feature Descriptor BEGIN */ 69 | 70 | #define USB_MS_EXTENDED_COMPAT_ID_VERSION 0x0100 71 | #define USB_MS_EXTENDED_COMPAT_ID_TYPE 0x04 72 | 73 | #define USB_COMPATID_NONE {0} 74 | #define USB_SUBCOMPATID_NONE {0} 75 | #define USB_COMPATID_WINUSB "WINUSB\0" 76 | #define USB_COMPATID_RNDIS "RNDIS\0\0" 77 | #define USB_COMPATID_PTP "PTP\0\0\0\0" 78 | #define USB_COMPATID_MTP "MTP\0\0\0\0" 79 | #define USB_COMPATID_BLUETOOTH "BLUTUTH" 80 | #define USB_SUBCOMPATID_BT_V11 "11\0\0\0\0\0" 81 | #define USB_SUBCOMPATID_BT_V12 "12\0\0\0\0\0" 82 | #define USB_SUBCOMPATID_BT_V20EDR "EDR\0\0\0\0" 83 | 84 | /* Microsoft Extended Compat ID OS Feature Descriptor END */ 85 | 86 | 87 | #endif -------------------------------------------------------------------------------- /components/USBIP/USBIP_defs.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file USBIP_defs.h 3 | * @brief Simple modification 4 | * @version 0.1 5 | * @date 2020-01-22 6 | * 7 | * @copyright Copyright (c) 2020 8 | * 9 | */ 10 | 11 | // Focus on the following structures in this file: 12 | // usbip_stage2_header 13 | // usbip_stage1_response_devlist 14 | 15 | // 16 | // Created by thevoidnn on 10/25/17. 17 | // 18 | 19 | #ifndef __USBIP_DEFS_H__ 20 | #define __USBIP_DEFS_H__ 21 | 22 | #include 23 | 24 | #include "components/USBIP/USB_defs.h" 25 | 26 | #define USBIP_SYSFS_PATH_SIZE 256 27 | #define USBIP_BUSID_SIZE 32 28 | 29 | enum usbip_stage1_command 30 | { 31 | // Offset 2 32 | USBIP_STAGE1_CMD_DEVICE_LIST = 0x05, // OP_REQ_DEVLIST 33 | USBIP_STAGE1_CMD_DEVICE_ATTACH = 0x03, // OP_REQ_IMPORT 34 | }; 35 | 36 | enum usbip_stager2_command 37 | { 38 | //Offset 0 39 | USBIP_STAGE2_REQ_SUBMIT = 0x0001, 40 | USBIP_STAGE2_REQ_UNLINK = 0x0002, 41 | USBIP_STAGE2_RSP_SUBMIT = 0x0003, 42 | USBIP_STAGE2_RSP_UNLINK = 0x0004, 43 | }; 44 | 45 | enum usbip_stage2_direction 46 | { 47 | USBIP_DIR_OUT = 0x00, 48 | USBIP_DIR_IN = 0x01, 49 | }; 50 | 51 | typedef struct 52 | { 53 | uint16_t version; 54 | uint16_t command; 55 | uint32_t status; 56 | } __attribute__((__packed__)) usbip_stage1_header; 57 | ///////////////////////////////////////////////////////////// 58 | 59 | // Device description 60 | typedef struct 61 | { 62 | char path[USBIP_SYSFS_PATH_SIZE]; 63 | char busid[USBIP_BUSID_SIZE]; 64 | 65 | uint32_t busnum; 66 | uint32_t devnum; 67 | uint32_t speed; 68 | 69 | uint16_t idVendor; 70 | uint16_t idProduct; 71 | uint16_t bcdDevice; 72 | 73 | uint8_t bDeviceClass; 74 | uint8_t bDeviceSubClass; 75 | uint8_t bDeviceProtocol; 76 | 77 | uint8_t bConfigurationValue; 78 | uint8_t bNumConfigurations; 79 | uint8_t bNumInterfaces; 80 | } __attribute__((packed)) usbip_stage1_usb_device; 81 | 82 | // Interface description 83 | typedef struct 84 | { 85 | uint8_t bInterfaceClass; 86 | uint8_t bInterfaceSubClass; 87 | uint8_t bInterfaceProtocol; 88 | uint8_t padding; 89 | } __attribute__((packed)) usbip_stage1_usb_interface; 90 | 91 | typedef struct 92 | { 93 | usbip_stage1_usb_device udev; 94 | usbip_stage1_usb_interface uinf[]; 95 | } __attribute__((packed)) usbip_stage1_response_devlist_entry; 96 | 97 | typedef struct 98 | { 99 | uint32_t list_size; 100 | usbip_stage1_response_devlist_entry devices[]; 101 | } __attribute__((__packed__)) usbip_stage1_response_devlist; 102 | 103 | /////////////////////////////////////////////////////////////// 104 | /////////////////////////////////////////////////////////////// 105 | /////////////////////////////////////////////////////////////// 106 | 107 | /** 108 | * struct usbip_header_basic - data pertinent to every URB request 109 | * RESPONSE & REQUEST 110 | * 111 | * @command: the usbip request type 112 | * @seqnum: sequential number that identifies requests; incremented per 113 | * connection 114 | * @devid: specifies a remote USB device uniquely instead of busnum and devnum; 115 | * in the stub driver, this value is ((busnum << 16) | devnum) 116 | * @direction: direction of the transfer 117 | * @ep: endpoint number 118 | */ 119 | typedef struct 120 | { 121 | uint32_t command; 122 | uint32_t seqnum; 123 | uint32_t devid; 124 | uint32_t direction; 125 | uint32_t ep; 126 | } __attribute__((packed)) usbip_stage2_header_basic; 127 | 128 | /** 129 | * struct usbip_header_cmd_submit - USBIP_CMD_SUBMIT packet header 130 | * >>>REQUEST 131 | * 132 | * @transfer_flags: URB flags 133 | * @transfer_buffer_length: the data size for (in) or (out) transfer 134 | * @start_frame: initial frame for isochronous or interrupt transfers 135 | * @number_of_packets: number of isochronous packets 136 | * @interval: maximum time for the request on the server-side host controller 137 | * @setup: setup data for a control request 138 | */ 139 | typedef struct 140 | { 141 | uint32_t transfer_flags; 142 | int32_t data_length; 143 | 144 | /* it is difficult for usbip to sync frames (reserved only?) */ 145 | int32_t start_frame; 146 | int32_t number_of_packets; 147 | int32_t interval; 148 | 149 | union { 150 | uint8_t setup[8]; 151 | usb_standard_request request; 152 | }; 153 | } __attribute__((packed)) usbip_stage2_header_cmd_submit; 154 | 155 | /** 156 | * struct usbip_header_ret_submit - USBIP_RET_SUBMIT packet header 157 | * <<>>REQUEST 177 | * @seqnum: the URB seqnum to unlink 178 | */ 179 | typedef struct 180 | { 181 | uint32_t seqnum; 182 | } __attribute__((packed)) usbip_stage2_header_cmd_unlink; 183 | 184 | /** 185 | * struct usbip_header_ret_unlink - USBIP_RET_UNLINK packet header 186 | * << 19 | 20 | #define USB_CLASS_MISCELLANEOUS_DEVICE 0xef 21 | #define USB_MISC_SUBCLASS_COMMON 0x02 22 | #define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01 23 | 24 | typedef union { 25 | struct 26 | { 27 | uint8_t u8lo; 28 | uint8_t u8hi; 29 | } __attribute__((packed)); 30 | uint16_t u16; 31 | } word_t; 32 | 33 | typedef struct 34 | { 35 | uint8_t bmRequestType; 36 | uint8_t bRequest; 37 | word_t wValue; // 16bit 38 | word_t wIndex; 39 | word_t wLength; 40 | } __attribute__((packed)) usb_standard_request; 41 | 42 | //#define USB_CLASS_HID 3 43 | 44 | #define USB_DT_HID 0x21 45 | #define USB_DT_REPORT 0x22 46 | 47 | //struct usb_hid_descriptor { 48 | // uint8_t bLength; 49 | // uint8_t bDescriptorType; 50 | // uint16_t bcdHID; 51 | // uint8_t bCountryCode; 52 | // uint8_t bNumDescriptors; 53 | //} __attribute__((packed)); 54 | //#define USB_DT_HID_SIZE sizeof(struct usb_hid_descriptor) 55 | 56 | //struct usb_hid_report_descriptor { 57 | // uint8_t bDescriptorType; 58 | // uint16_t wReportLength; 59 | //} __attribute__((packed)); 60 | 61 | #define USB_DT_REPORT_SIZE sizeof(struct usb_hid_report_descriptor) 62 | 63 | /* Class Definition */ 64 | #define USB_CLASS_VENDOR 0xFF 65 | 66 | /////////////////////////////////////////////////////////////// 67 | /* Table 9-2. Format of Setup Data */ 68 | /* bmRequestType bit definitions */ 69 | 70 | /* bit 7 : Direction */ 71 | #define USB_REQ_TYPE_OUT 0x00 // Host-to-device 72 | #define USB_REQ_TYPE_IN 0x80 // Device-to-host 73 | /* bits 6..5 : Type */ 74 | #define USB_REQ_TYPE_STANDARD 0x00 75 | #define USB_REQ_TYPE_CLASS 0x20 76 | #define USB_REQ_TYPE_VENDOR 0x40 77 | //#define USB_REQ_TYPE_RESERVED 0x60 78 | /* bits 4..0 : Recipient */ 79 | #define USB_REQ_TYPE_DEVICE 0x00 80 | #define USB_REQ_TYPE_INTERFACE 0x01 81 | #define USB_REQ_TYPE_ENDPOINT 0x02 82 | #define USB_REQ_TYPE_OTHER 0x03 83 | //#define USB_REQ_TYPE_RESERVED 0x1F 84 | /////////////////////////////////////////////////////////////// 85 | 86 | /////////////////////////////////////////////////////////////// 87 | /* USB Standard Request Codes - Table 9-4 */ 88 | #define USB_REQ_GET_STATUS 0 89 | #define USB_REQ_CLEAR_FEATURE 1 90 | /* Reserved for future use: 2 */ 91 | #define USB_REQ_SET_FEATURE 3 92 | /* Reserved for future use: 3 */ 93 | #define USB_REQ_SET_ADDRESS 5 94 | #define USB_REQ_GET_DESCRIPTOR 6 95 | #define USB_REQ_SET_DESCRIPTOR 7 96 | #define USB_REQ_GET_CONFIGURATION 8 97 | #define USB_REQ_SET_CONFIGURATION 9 98 | #define USB_REQ_GET_INTERFACE 10 99 | #define USB_REQ_SET_INTERFACE 11 100 | #define USB_REQ_SET_SYNCH_FRAME 12 101 | 102 | // USB HID Request 103 | #define USB_REQ_GET_REPORT 0x01 104 | #define USB_REQ_GET_IDLE 0x02 105 | #define USB_REQ_GET_PROTOCOL 0x03 106 | #define USB_REQ_SET_REPORT 0x09 107 | #define USB_REQ_SET_IDLE 0X0A 108 | #define USB_REQ_SET_PROTOCOL 0X0B 109 | /////////////////////////////////////////////////////////////// 110 | 111 | /////////////////////////////////////////////////////////////// 112 | /* USB Descriptor Types - Table 9-5 */ 113 | #define USB_DT_DEVICE 1 114 | #define USB_DT_CONFIGURATION 2 115 | #define USB_DT_STRING 3 116 | #define USB_DT_INTERFACE 4 117 | #define USB_DT_ENDPOINT 5 118 | #define USB_DT_DEVICE_QUALIFIER 6 119 | #define USB_DT_OTHER_SPEED_CONFIGURATION 7 120 | #define USB_DT_INTERFACE_POWER 8 121 | #define USB_DT_BOS 15 122 | #define USB_DT_SUPERSPEED_USB_ENDPOINT_COMPANION 48 123 | /* From ECNs */ 124 | #define USB_DT_OTG 9 125 | #define USB_DT_DEBUG 10 126 | #define USB_DT_INTERFACE_ASSOCIATION 11 127 | /* USB HID */ 128 | #define USB_DT_HID 0x21 129 | #define USB_DT_HID_REPORT 0x22 130 | /////////////////////////////////////////////////////////////// 131 | 132 | /////////////////////////////////////////////////////////////// 133 | /* USB Standard Feature Selectors - Table 9-6 */ 134 | #define USB_FEAT_ENDPOINT_HALT 0 // Recipient: Device 135 | #define USB_FEAT_DEVICE_REMOTE_WAKEUP 1 // Recipient: Endpoint 136 | #define USB_FEAT_TEST_MODE 2 // Recipient: Device 137 | 138 | /* Information Returned by a GetStatus() Request to a Device - Figure 9-4 */ 139 | #define USB_DEV_STATUS_SELF_POWERED 0x01 140 | #define USB_DEV_STATUS_REMOTE_WAKEUP 0x02 141 | /////////////////////////////////////////////////////////////// 142 | 143 | /////////////////////////////////////////////////////////////// 144 | /* USB Standard Device Descriptor - Table 9-8 */ 145 | typedef struct 146 | { 147 | uint8_t bLength; 148 | uint8_t bDescriptorType; 149 | uint16_t bcdUSB; 150 | uint8_t bDeviceClass; 151 | uint8_t bDeviceSubClass; 152 | uint8_t bDeviceProtocol; 153 | uint8_t bMaxPacketSize0; 154 | uint16_t idVendor; 155 | uint16_t idProduct; 156 | uint16_t bcdDevice; 157 | uint8_t iManufacturer; 158 | uint8_t iProduct; 159 | uint8_t iSerialNumber; 160 | uint8_t bNumConfigurations; 161 | } __attribute__((packed)) usb_device_descriptor; 162 | #define USB_DT_DEVICE_SIZE sizeof(usb_device_descriptor) 163 | /////////////////////////////////////////////////////////////// 164 | 165 | /////////////////////////////////////////////////////////////// 166 | /* USB Device_Qualifier Descriptor - Table 9-9 167 | * Not used in this implementation. 168 | */ 169 | typedef struct 170 | { 171 | uint8_t bLength; 172 | uint8_t bDescriptorType; 173 | uint16_t bcdUSB; 174 | uint8_t bDeviceClass; 175 | uint8_t bDeviceSubClass; 176 | uint8_t bDeviceProtocol; 177 | uint8_t bMaxPacketSize0; 178 | uint8_t bNumConfigurations; 179 | uint8_t bReserved; 180 | } __attribute__((packed)) usb_device_qualifier_descriptor; 181 | /////////////////////////////////////////////////////////////// 182 | 183 | /* This is only defined as a top level named struct to improve c++ 184 | * compatibility. You should never need to instance this struct 185 | * in user code! */ 186 | typedef struct 187 | { 188 | uint8_t *cur_altsetting; 189 | uint8_t num_altsetting; 190 | const struct usb_iface_assoc_descriptor *iface_assoc; 191 | const struct usb_interface_descriptor *altsetting; 192 | } __attribute__((packed)) usb_interface; 193 | 194 | /////////////////////////////////////////////////////////////// 195 | /* USB Standard Configuration Descriptor - Table 9-10 */ 196 | typedef struct 197 | { 198 | uint8_t bLength; 199 | uint8_t bDescriptorType; 200 | uint16_t wTotalLength; 201 | uint8_t bNumInterfaces; 202 | uint8_t bConfigurationValue; 203 | uint8_t iConfiguration; 204 | uint8_t bmAttributes; 205 | uint8_t bMaxPower; 206 | } __attribute__((packed)) usb_config_descriptor; 207 | #define USB_DT_CONFIGURATION_SIZE sizeof(usb_config_descriptor) 208 | /////////////////////////////////////////////////////////////// 209 | 210 | /* USB Configuration Descriptor *bmAttributes* bit definitions */ 211 | #define USB_CONFIG_ATTR_DEFAULT 0x80 /** always required (USB2.0 table 9-10) */ 212 | #define USB_CONFIG_ATTR_SELF_POWERED 0x40 213 | #define USB_CONFIG_ATTR_REMOTE_WAKEUP 0x20 214 | 215 | /* Other Speed Configuration is the same as Configuration Descriptor. 216 | * - Table 9-11 217 | */ 218 | 219 | /////////////////////////////////////////////////////////////// 220 | /* USB Standard Interface Descriptor - Table 9-12 */ 221 | typedef struct 222 | { 223 | uint8_t bLength; 224 | uint8_t bDescriptorType; 225 | uint8_t bInterfaceNumber; 226 | uint8_t bAlternateSetting; 227 | uint8_t bNumEndpoints; 228 | uint8_t bInterfaceClass; 229 | uint8_t bInterfaceSubClass; 230 | uint8_t bInterfaceProtocol; 231 | uint8_t iInterface; 232 | } __attribute__((packed)) usb_interface_descriptor; 233 | #define USB_DT_INTERFACE_SIZE sizeof(usb_interface_descriptor) 234 | /////////////////////////////////////////////////////////////// 235 | 236 | /////////////////////////////////////////////////////////////// 237 | /* USB Standard Endpoint Descriptor - Table 9-13 */ 238 | typedef struct 239 | { 240 | uint8_t bLength; 241 | uint8_t bDescriptorType; 242 | uint8_t bEndpointAddress; 243 | uint8_t bmAttributes; 244 | uint16_t wMaxPacketSize; 245 | uint8_t bInterval; 246 | } __attribute__((packed))usb_endpoint_descriptor; 247 | #define USB_DT_ENDPOINT_SIZE sizeof(usb_endpoint_descriptor) 248 | /////////////////////////////////////////////////////////////// 249 | 250 | /* USB bEndpointAddress helper macros */ 251 | #define USB_ENDPOINT_ADDR_OUT(x) (x) 252 | #define USB_ENDPOINT_ADDR_IN(x) (0x80 | (x)) 253 | 254 | /////////////////////////////////////////////////////////////// 255 | /* USB Endpoint Descriptor bmAttributes bit definitions - Table 9-13 */ 256 | /* bits 1..0 : Transfer type */ 257 | #define USB_ENDPOINT_ATTR_CONTROL 0x00 258 | #define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01 259 | #define USB_ENDPOINT_ATTR_BULK 0x02 260 | #define USB_ENDPOINT_ATTR_INTERRUPT 0x03 261 | #define USB_ENDPOINT_ATTR_TYPE 0x03 262 | // If not an isochronous endpoint, bits 5..2 are reserved 263 | // and must be set to zero. 264 | /* bits 3..2 : Sync type (only if ISOCHRONOUS) */ 265 | #define USB_ENDPOINT_ATTR_NOSYNC 0x00 266 | #define USB_ENDPOINT_ATTR_ASYNC 0x04 267 | #define USB_ENDPOINT_ATTR_ADAPTIVE 0x08 268 | #define USB_ENDPOINT_ATTR_SYNC 0x0C 269 | #define USB_ENDPOINT_ATTR_SYNCTYPE 0x0C 270 | /* bits 5..4 : Usage type (only if ISOCHRONOUS) */ 271 | #define USB_ENDPOINT_ATTR_DATA 0x00 272 | #define USB_ENDPOINT_ATTR_FEEDBACK 0x10 273 | #define USB_ENDPOINT_ATTR_IMPLICIT_FEEDBACK_DATA 0x20 274 | #define USB_ENDPOINT_ATTR_USAGETYPE 0x30 275 | /////////////////////////////////////////////////////////////// 276 | 277 | /////////////////////////////////////////////////////////////// 278 | /* Table 9-15 specifies String Descriptor Zero. 279 | * Table 9-16 specified UNICODE String Descriptor. 280 | */ 281 | typedef struct 282 | { 283 | uint8_t bLength; 284 | uint8_t bDescriptorType; 285 | uint16_t wData[]; 286 | } __attribute__((packed)) usb_string_descriptor; 287 | 288 | /* From ECN: Interface Association Descriptors, Table 9-Z */ 289 | typedef struct 290 | { 291 | uint8_t bLength; 292 | uint8_t bDescriptorType; 293 | uint8_t bFirstInterface; 294 | uint8_t bInterfaceCount; 295 | uint8_t bFunctionClass; 296 | uint8_t bFunctionSubClass; 297 | uint8_t bFunctionProtocol; 298 | uint8_t iFunction; 299 | } __attribute__((packed)) usb_iface_assoc_descriptor; 300 | #define USB_DT_INTERFACE_ASSOCIATION_SIZE \ 301 | sizeof(usb_iface_assoc_descriptor) 302 | 303 | enum usb_language_id 304 | { 305 | USB_LANGID_ENGLISH_US = 0x409, 306 | }; 307 | /////////////////////////////////////////////////////////////// 308 | 309 | #endif 310 | -------------------------------------------------------------------------------- /components/USBIP/USB_descriptor.c: -------------------------------------------------------------------------------- 1 | ////TODO: refactoring into structure 2 | /** 3 | * @file USB_descriptor.c 4 | * @brief Standard USB Descriptor Definitions 5 | fix bugs 2020-1-23 6 | * @version 0.2 7 | * @date 2020-1-23 8 | * 9 | * 10 | */ 11 | #include 12 | #include 13 | 14 | 15 | #include "components/USBIP/USB_descriptor.h" 16 | #include "components/USBIP/USB_defs.h" 17 | 18 | #define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) 19 | 20 | 21 | /** 22 | * @brief step 1. Build Standard Device Descriptor 23 | * 24 | */ 25 | 26 | // Standard Device Descriptor 27 | const uint8_t kUSBd0DeviceDescriptor[0x12] = 28 | { 29 | 0x12, // bLength 30 | USB_DT_DEVICE, // bDescriptorType 31 | 32 | #if (USE_WINUSB == 1) 33 | USBShort(0x0300), // bcdUSB 34 | #else 35 | USBShort(0x0200), // bcdUSB 36 | #endif 37 | ////TODO: Is it also available elsewhere? 38 | 39 | // We need to use a device other than the USB-IF standard, set to 0x00 40 | 0x00, // bDeviceClass 41 | 0x00, // bDeviceSubClass 42 | 0x00, // bDeviceProtocol 43 | 44 | //USBD0_MAX_PACKET0, // bMaxPacketSize0 Maximum packet size for default pipe. 45 | 0x09, 46 | USBShort(USBD0_DEV_DESC_IDVENDOR), // idVendor Vendor ID (VID). 47 | USBShort(USBD0_DEV_DESC_IDPRODUCT), // idProduct Product ID (PID). 48 | USBShort(USBD0_DEV_DESC_BCDDEVICE), // bcdDevice Device Version BCD. 49 | 0x01, // iManufacturer Index of Manufacturer string identifier. 50 | 0x02, // iProduct Index of Product string identifier. 51 | 0x03 * USBD0_STR_DESC_SER_EN, // iSerialNumber Index of Product serial number. 52 | 0x01 // bNumConfigurations Number of configurations. 53 | }; 54 | 55 | 56 | 57 | 58 | /** 59 | * @brief step 2. Buid Standard Configuration Descriptor 60 | * 61 | */ 62 | 63 | 64 | // Standard Interface Descriptor 65 | 66 | #if (USE_WINUSB ==1) 67 | const uint8_t kUSBd0InterfaceDescriptor[0x30]= 68 | { 69 | 0x09, // bLength 70 | USB_DT_INTERFACE, // bDescriptorType 71 | USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber 72 | USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting 73 | 0x03, // bNumEndpoints(we will use 3 endpoints) 74 | // 75 | USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass 76 | USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass 77 | USBD_CUSTOM_CLASS0_IF0_PROTOCOL, // bInterfaceProtocol 78 | 0x00, // iInterface 79 | // Index of string descriptor describing this interface 80 | ////TODO: fix this 0x04 ? 81 | 82 | 83 | // Standard Endpoint Descriptor 84 | 85 | // Endpoint 1: Bulk Out – used for commands received from host PC. 86 | // Endpoint 2: Bulk In – used for responses send to host PC. 87 | // Endpoint 3: Bulk In (optional) – used for streaming SWO trace 88 | 89 | // ATTENTION: 90 | // physical endpoint 1 indeed included two "endpoints": Bulk OUT and Bulk IN 91 | // physical endpoint 1 -> Endpoint 1 & Endpoint 2 92 | // physical endpoint 2 -> Endpoint 3 93 | 94 | // See also : 95 | // http://www.keil.com/pack/doc/CMSIS/DAP/html/group__DAP__ConfigUSB__gr.html 96 | 97 | /* Pysical endpoint 1 */ 98 | 99 | // "Endpoint 1: Bulk Out – used for commands received from host PC." PC -> Device 100 | 0x07, // bLength 101 | USB_DT_ENDPOINT, // bDescriptorType 102 | 0x01, // bEndpointAddress 103 | USB_ENDPOINT_ATTR_BULK, // bmAttributes 104 | USBShort(1024), // wMaxPacketSize 105 | // We assume that it always runs in High Speed. 106 | 0x00, // bInterval 107 | 108 | /* SuperSpeed Endpoint Companion */ 109 | 0x06, // bLength 110 | USB_DT_SUPERSPEED_USB_ENDPOINT_COMPANION, 111 | 0x00, // bMaxBurst 112 | 0x00, // bmAttributes(MaxStream for Bulk) 113 | 0x00, 0x00, // wBytesPerInterval -> 0 for Bulk 114 | 115 | 116 | 117 | /* Pysical endpoint 1 */ 118 | 119 | // "Endpoint 2: Bulk In – used for responses send to host PC." Device -> PC 120 | 0x07, // bLength 121 | USB_DT_ENDPOINT, // bDescriptorType 122 | 0x81, // bEndpointAddress 123 | USB_ENDPOINT_ATTR_BULK, // bmAttributes 124 | USBShort(1024), // wMaxPacketSize 125 | 0x00, // bInterval 126 | 127 | /* SuperSpeed Endpoint Companion */ 128 | 0x06, // bLength 129 | USB_DT_SUPERSPEED_USB_ENDPOINT_COMPANION, 130 | 0x00, // bMaxBurst 131 | 0x00, // bmAttributes(MaxStream for Bulk) 132 | 0x00, 0x00, // wBytesPerInterval -> 0 for Bulk 133 | 134 | 135 | 136 | /* Pysical endpoint 2 */ 137 | 138 | // "Endpoint 3: Bulk In (optional) – used for streaming SWO trace" Device -> PC 139 | 0x07, // bLength 140 | USB_DT_ENDPOINT, // bDescriptorType 141 | 0x82, // bEndpointAddress 142 | USB_ENDPOINT_ATTR_BULK, // bmAttributes 143 | USBShort(1024), // wMaxPacketSize 144 | 0x00, // bInterval 145 | 146 | /* SuperSpeed Endpoint Companion */ 147 | 0x06, // bLength 148 | USB_DT_SUPERSPEED_USB_ENDPOINT_COMPANION, 149 | 0x00, // bMaxBurst 150 | 0x00, // bmAttributes(MaxStream for Bulk) 151 | 0x00, 0x00, // wBytesPerInterval -> 0 for Bulk 152 | 153 | 154 | }; 155 | 156 | #else 157 | const uint8_t kUSBd0InterfaceDescriptor[0x20]= 158 | { 159 | 0x09, // bLength 160 | USB_DT_INTERFACE, // bDescriptorType 161 | USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber 162 | USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting 163 | 0x02, // bNumEndpoints ----> 2 endpoint for USB HID 164 | // 165 | USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass 166 | USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass 167 | USBD_CUSTOM_CLASS0_IF0_PROTOCOL, // bInterfaceProtocol 168 | 0x00, // iInterface 169 | // Index of string descriptor describing this interface 170 | 171 | // HID Descriptor 172 | 0x09, // bLength 173 | 0x21, // bDescriptorType 174 | 0x11, 0x01, // bcdHID 175 | 0x00, // bCountryCode 176 | 0x01, // bNumDescriptors 177 | 0x22, // bDescriptorType1 178 | 0x21, 0x00, // wDescriptorLength1 179 | 180 | // Standard Endpoint Descriptor 181 | 182 | // We perform all transfer operations on Pysical endpoint 1. 183 | 184 | /* Pysical endpoint 1 */ 185 | 186 | 0x07, // bLength 187 | USB_DT_ENDPOINT, // bDescriptorType 188 | 0x81, // bEndpointAddress 189 | USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes 190 | USBShort(64), // wMaxPacketSize 191 | 0x01, // bInterval 192 | 193 | /* Pysical endpoint 1 */ 194 | 195 | 0x07, // bLength 196 | USB_DT_ENDPOINT, // bDescriptorType 197 | 0x01, // bEndpointAddress 198 | USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes 199 | USBShort(64), // wMaxPacketSize 200 | 0x01, // bInterval 201 | }; 202 | #endif 203 | 204 | // Standard Configuration Descriptor 205 | #define LENGTHOFCONFIGDESCRIPTOR 9 206 | 207 | #if (USE_WINUSB == 1) 208 | const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = 209 | { 210 | // Configuration descriptor header. 211 | 212 | 0x09, // bLength 213 | USB_DT_CONFIGURATION, // bDescriptorType 214 | 215 | USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (LENGTHOFCONFIGDESCRIPTOR)), 216 | // wTotalLength 217 | 218 | 0x01, // bNumInterfaces 219 | // There is only one interface in the CMSIS-DAP project 220 | 0x01, // bConfigurationValue: 0x01 is used to select this configuration */ 221 | 0x00, // iConfiguration: no string to describe this configuration */ 222 | USBD0_CFG_DESC_BMATTRIBUTES, // bmAttributes 223 | 224 | USBD0_CFG_DESC_BMAXPOWER, // bMaxPower 225 | }; 226 | 227 | #else 228 | const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = 229 | { 230 | // Configuration descriptor header. 231 | 232 | 0x09, // bLength 233 | USB_DT_CONFIGURATION, // bDescriptorType 234 | 235 | USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (LENGTHOFCONFIGDESCRIPTOR)), 236 | // wTotalLength 237 | 238 | 0x01, // bNumInterfaces 239 | // There is only one interface in the CMSIS-DAP project 240 | 0x01, // bConfigurationValue: 0x01 is used to select this configuration */ 241 | 0x00, // iConfiguration: no string to describe this configuration */ 242 | USBD0_CFG_DESC_BMATTRIBUTES, // bmAttributes 243 | 244 | USBD0_CFG_DESC_BMAXPOWER, // bMaxPower 245 | }; 246 | #endif 247 | 248 | 249 | // USB HID Report Descriptor 250 | const uint8_t kHidReportDescriptor[0x21] = { 251 | 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) 252 | 0x09, 0x01, // Usage (0x01) 253 | 0xA1, 0x01, // Collection (Application) 254 | 0x15, 0x00, // Logical Minimum (0) 255 | 0x26, 0xFF, 0x00, // Logical Maximum (255) 256 | 0x75, 0x08, // Report Size (8) 257 | 0x95, 0xFF, // Report Count (64) 258 | 0x09, 0x01, // Usage (0x01) 259 | 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 260 | 0x95, 0xFF, // Report Count (64) 261 | 0x09, 0x01, // Usage (0x01) 262 | 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 263 | 0x95, 0x01, // Report Count (1) 264 | 0x09, 0x01, // Usage (0x01) 265 | 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 266 | 0xC0, // End Collection 267 | // 33 bytes 268 | }; 269 | 270 | 271 | 272 | 273 | 274 | 275 | /** 276 | * @brief step 3. Build String Descriptor 277 | * 278 | */ 279 | 280 | 281 | const uint8_t kLangDescriptor[0x04] = 282 | { 283 | 4, 284 | USB_DT_STRING, 285 | USBShort(USB_LANGID_ENGLISH_US) 286 | }; 287 | 288 | 289 | /** 290 | * @brief We will use these string descriptor: 291 | * 1. Manufacturer string -> "KEIL - Tools By ARM" 292 | * 2. Product string -> "LPC-Link-II" 293 | * 3. Serial number string -> "0001A0000000" 294 | * 4. Interface string -> "LPC-Link-II CMSIS-DAP" 295 | * 296 | * 297 | */ 298 | 299 | const uint8_t kManufacturerString[0x28] = 300 | { 301 | 0x28, // bLength 302 | 0x03, // bDescriptorType 303 | // "KEIL - Tools By ARM" 304 | 'K', 0, 'E', 0, 'I', 0, 'L', 0, ' ', 0, '-', 0, ' ', 0, 'T', 0, 'o', 0, 'o', 0, 305 | 'l', 0, 's', 0, ' ', 0, 'B', 0, 'y', 0, ' ', 0, 'A', 0, 'R', 0, 'M', 0 306 | }; 307 | 308 | const uint8_t kProductString[0x18] = 309 | { 310 | 0x18, // bLength 311 | 0x03, // bDescriptorType 312 | // "LPC-Link-II" 313 | 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, 314 | 'I', 0 315 | }; 316 | 317 | const uint8_t kSerialNumberString[0x1A] = 318 | { 319 | 0x1A, // bLength 320 | 0x03, // bDescriptorType 321 | // "0001A0000000" 322 | '0', 0, '0', 0, '0', 0, '1', 0, 'A', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, 323 | '0', 0, '0', 0 324 | }; 325 | 326 | const uint8_t kInterfaceString[0x2C] = 327 | { 328 | 0x2C, // bLength 329 | 0x03, // bDescriptorType 330 | // "LPC-Link-II CMSIS-DAP" 331 | 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, 332 | 'I', 0, ' ', 0, 'C', 0, 'M', 0, 'S', 0, 'I', 0, 'S', 0, '-', 0, 'D', 0, 'A', 0, 333 | 'P', 0 334 | }; 335 | 336 | const uint8_t * const kUSBd0StringDescriptorsSet[0x05] = 337 | { 338 | kLangDescriptor, 339 | kManufacturerString, 340 | kProductString, 341 | kSerialNumberString, 342 | kInterfaceString 343 | }; -------------------------------------------------------------------------------- /components/USBIP/USB_descriptor.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_DESCRIPTOR_H__ 2 | #define __USB_DESCRIPTOR_H__ 3 | 4 | #include "dap_configuration.h" 5 | 6 | // Vendor ID assigned by USB-IF (idVendor). 7 | #define USBD0_DEV_DESC_IDVENDOR 0xC251 8 | // Product ID assigned by manufacturer (idProduct). 9 | #define USBD0_DEV_DESC_IDPRODUCT 0xF00B 10 | // Device Release Number in binary-coded decimal (bcdDevice). 11 | #define USBD0_DEV_DESC_BCDDEVICE 0x0100 12 | 13 | // Maximum packet size for Endpoint 0 (bMaxPacketSize0). 14 | #define USBD0_MAX_PACKET0 64 15 | 16 | // If disabled Serial Number String will not be assigned to USB Device. 17 | #define USBD0_STR_DESC_SER_EN 1 18 | 19 | // bmAttributes 20 | #define USBD0_CFG_DESC_BMATTRIBUTES 0x80 21 | 22 | // bMaxPower 23 | #define USBD0_CFG_DESC_BMAXPOWER 250 24 | 25 | // Interface Number 26 | #define USBD_CUSTOM_CLASS0_IF0_NUM 0 27 | 28 | // Alternate Setting 29 | #define USBD_CUSTOM_CLASS0_IF0_ALT 0 30 | 31 | // Class Code 32 | #if (USE_WINUSB == 1) 33 | #define USBD_CUSTOM_CLASS0_IF0_CLASS 0xFF // 0xFF: Vendor Specific 34 | #else 35 | #define USBD_CUSTOM_CLASS0_IF0_CLASS 0x03 // 0x03: HID class 36 | #endif 37 | 38 | // Subclass Code 39 | #define USBD_CUSTOM_CLASS0_IF0_SUBCLASS 0x00 40 | 41 | // Protocol Code 42 | #define USBD_CUSTOM_CLASS0_IF0_PROTOCOL 0x00 43 | 44 | ///////////////////////////////////////////// 45 | 46 | // common part 47 | extern const uint8_t kUSBd0DeviceDescriptor[0x12]; 48 | extern const uint8_t kLangDescriptor[0x04]; 49 | extern const uint8_t kManufacturerString[0x28]; 50 | extern const uint8_t kProductString[0x18]; 51 | extern const uint8_t kSerialNumberString[0x1A]; 52 | 53 | #if (USE_WINUSB == 1) 54 | extern const uint8_t kUSBd0InterfaceDescriptor[0x30]; 55 | extern const uint8_t kUSBd0ConfigDescriptor[0x09]; 56 | extern const uint8_t kInterfaceString[0x2C]; 57 | 58 | #else 59 | extern const uint8_t kUSBd0InterfaceDescriptor[0x20]; 60 | extern const uint8_t kUSBd0ConfigDescriptor[0x09]; 61 | extern const uint8_t kInterfaceString[0x2C]; 62 | extern const uint8_t kHidReportDescriptor[0x21]; 63 | 64 | #endif 65 | 66 | #endif -------------------------------------------------------------------------------- /components/USBIP/USB_handle.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file USB_handle.c 3 | * @brief Handle all Standard Device Requests on endpoint 0 4 | * @version 0.1 5 | * @date 2020-01-23 6 | * 7 | * @copyright Copyright (c) 2020 8 | * 9 | */ 10 | #include 11 | #include 12 | 13 | #include "lwip/err.h" 14 | #include "lwip/sockets.h" 15 | #include "lwip/sys.h" 16 | #include 17 | 18 | #include "components/USBIP/USB_handle.h" 19 | #include "components/USBIP/USB_descriptor.h" 20 | #include "components/USBIP/MSOS20_descriptor.h" 21 | 22 | #include "main/usbip_server.h" 23 | 24 | 25 | 26 | const char *strings_list[] = { 27 | 0, // reserved: available languages -> iInterface 28 | "windowsair", 29 | "esp32 CMSIS-DAP", 30 | "1234", 31 | }; 32 | // handle functions 33 | static void handleGetDescriptor(usbip_stage2_header *header); 34 | 35 | ////TODO: may be ok 36 | void handleUSBControlRequest(usbip_stage2_header *header) 37 | { 38 | // Table 9-3. Standard Device Requests 39 | 40 | switch (header->u.cmd_submit.request.bmRequestType) 41 | { 42 | case 0x00: // ignore.. 43 | switch (header->u.cmd_submit.request.bRequest) 44 | { 45 | case USB_REQ_CLEAR_FEATURE: 46 | printf("* CLEAR FEATURE\r\n"); 47 | send_stage2_submit_data(header, 0, 0, 0); 48 | break; 49 | case USB_REQ_SET_FEATURE: 50 | printf("* SET FEATURE\r\n"); 51 | send_stage2_submit_data(header, 0, 0, 0); 52 | break; 53 | case USB_REQ_SET_ADDRESS: 54 | printf("* SET ADDRESS\r\n"); 55 | send_stage2_submit_data(header, 0, 0, 0); 56 | break; 57 | case USB_REQ_SET_DESCRIPTOR: 58 | printf("* SET DESCRIPTOR\r\n"); 59 | send_stage2_submit_data(header, 0, 0, 0); 60 | break; 61 | case USB_REQ_SET_CONFIGURATION: 62 | printf("* SET CONFIGURATION\r\n"); 63 | send_stage2_submit_data(header, 0, 0, 0); 64 | break; 65 | default: 66 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 67 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 68 | break; 69 | } 70 | break; 71 | case 0x01: // ignore... 72 | switch (header->u.cmd_submit.request.bRequest) 73 | { 74 | case USB_REQ_CLEAR_FEATURE: 75 | printf("* CLEAR FEATURE\r\n"); 76 | send_stage2_submit_data(header, 0, 0, 0); 77 | break; 78 | case USB_REQ_SET_FEATURE: 79 | printf("* SET FEATURE\r\n"); 80 | send_stage2_submit_data(header, 0, 0, 0); 81 | break; 82 | case USB_REQ_SET_INTERFACE: 83 | printf("* SET INTERFACE\r\n"); 84 | send_stage2_submit_data(header, 0, 0, 0); 85 | break; 86 | 87 | default: 88 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 89 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 90 | break; 91 | } 92 | break; 93 | case 0x02: // ignore.. 94 | switch (header->u.cmd_submit.request.bRequest) 95 | { 96 | case USB_REQ_CLEAR_FEATURE: 97 | printf("* CLEAR FEATURE\r\n"); 98 | send_stage2_submit_data(header, 0, 0, 0); 99 | break; 100 | case USB_REQ_SET_FEATURE: 101 | printf("* SET INTERFACE\r\n"); 102 | send_stage2_submit_data(header, 0, 0, 0); 103 | break; 104 | 105 | default: 106 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 107 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 108 | break; 109 | } 110 | break; 111 | 112 | case 0x80: // *IMPORTANT* 113 | #if (USE_WINUSB == 0) 114 | case 0x81: 115 | #endif 116 | { 117 | switch (header->u.cmd_submit.request.bRequest) 118 | { 119 | case USB_REQ_GET_CONFIGURATION: 120 | printf("* GET CONIFGTRATION\r\n"); 121 | send_stage2_submit_data(header, 0, 0, 0); 122 | break; 123 | case USB_REQ_GET_DESCRIPTOR: 124 | handleGetDescriptor(header); ////TODO: device_qualifier 125 | break; 126 | case USB_REQ_GET_STATUS: 127 | printf("* GET STATUS\r\n"); 128 | send_stage2_submit_data(header, 0, 0, 0); 129 | break; 130 | default: 131 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 132 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 133 | break; 134 | } 135 | break; 136 | } 137 | #if (USE_WINUSB == 1) 138 | case 0x81: // ignore... 139 | switch (header->u.cmd_submit.request.bRequest) 140 | { 141 | case USB_REQ_GET_INTERFACE: 142 | printf("* GET INTERFACE\r\n"); 143 | send_stage2_submit_data(header, 0, 0, 0); 144 | break; 145 | case USB_REQ_SET_SYNCH_FRAME: 146 | printf("* SET SYNCH FRAME\r\n"); 147 | send_stage2_submit_data(header, 0, 0, 0); 148 | break; 149 | case USB_REQ_GET_STATUS: 150 | printf("* GET STATUS\r\n"); 151 | send_stage2_submit_data(header, 0, 0, 0); 152 | break; 153 | 154 | default: 155 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 156 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 157 | break; 158 | } 159 | break; 160 | #endif 161 | case 0x82: // ignore... 162 | switch (header->u.cmd_submit.request.bRequest) 163 | { 164 | case USB_REQ_GET_STATUS: 165 | printf("* GET STATUS\r\n"); 166 | send_stage2_submit_data(header, 0, 0, 0); 167 | break; 168 | 169 | default: 170 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 171 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 172 | break; 173 | } 174 | break; 175 | case 0xC0: // Microsoft OS 2.0 vendor-specific descriptor 176 | { 177 | uint16_t *wIndex = (uint16_t *)(&(header->u.cmd_submit.request.wIndex)); 178 | switch (*wIndex) 179 | { 180 | case MS_OS_20_DESCRIPTOR_INDEX: 181 | printf("* GET MSOS 2.0 vendor-specific descriptor\r\n"); 182 | send_stage2_submit_data(header, 0, msOs20DescriptorSetHeader, sizeof(msOs20DescriptorSetHeader)); 183 | break; 184 | case MS_OS_20_SET_ALT_ENUMERATION: 185 | // set alternate enumeration command 186 | // bAltEnumCode set to 0 187 | printf("Set alternate enumeration.This should not happen.\r\n"); 188 | break; 189 | 190 | default: 191 | printf("USB unknown request, bmRequestType:%d,bRequest:%d,wIndex:%d\r\n", 192 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest, *wIndex); 193 | break; 194 | } 195 | break; 196 | } 197 | case 0x21: // Set_Idle for HID 198 | switch (header->u.cmd_submit.request.bRequest) 199 | { 200 | case USB_REQ_SET_IDLE: 201 | printf("* SET IDLE\r\n"); 202 | send_stage2_submit(header, 0, 0); 203 | break; 204 | 205 | default: 206 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 207 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 208 | break; 209 | } 210 | break; 211 | default: 212 | printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", 213 | header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); 214 | break; 215 | } 216 | } 217 | 218 | static void handleGetDescriptor(usbip_stage2_header *header) 219 | { 220 | // 9.4.3 Get Descriptor 221 | switch (header->u.cmd_submit.request.wValue.u8hi) 222 | { 223 | case USB_DT_DEVICE: // get device descriptor 224 | printf("* GET 0x01 DEVICE DESCRIPTOR\r\n"); 225 | send_stage2_submit_data(header, 0, &kUSBd0DeviceDescriptor[0], sizeof(kUSBd0DeviceDescriptor)); 226 | break; 227 | 228 | case USB_DT_CONFIGURATION: // get configuration descriptor 229 | printf("* GET 0x02 CONFIGURATION DESCRIPTOR\r\n"); 230 | ////TODO: ? 231 | if (header->u.cmd_submit.data_length == USB_DT_CONFIGURATION_SIZE) 232 | { 233 | printf("Sending only first part of CONFIG\r\n"); 234 | 235 | send_stage2_submit(header, 0, header->u.cmd_submit.data_length); 236 | send(kSock, kUSBd0ConfigDescriptor, sizeof(kUSBd0ConfigDescriptor), 0); 237 | } 238 | else 239 | { 240 | printf("Sending ALL CONFIG\r\n"); 241 | send_stage2_submit(header, 0, sizeof(kUSBd0ConfigDescriptor) + sizeof(kUSBd0InterfaceDescriptor)); 242 | send(kSock, kUSBd0ConfigDescriptor, sizeof(kUSBd0ConfigDescriptor), 0); 243 | send(kSock, kUSBd0InterfaceDescriptor, sizeof(kUSBd0InterfaceDescriptor), 0); 244 | } 245 | break; 246 | 247 | case USB_DT_STRING: 248 | //printf("* GET 0x03 STRING DESCRIPTOR\r\n"); 249 | 250 | if (header->u.cmd_submit.request.wValue.u8lo == 0) 251 | { 252 | printf("** REQUESTED list of supported languages\r\n"); 253 | send_stage2_submit_data(header, 0, kLangDescriptor, sizeof(kLangDescriptor)); 254 | } 255 | else if (header->u.cmd_submit.request.wValue.u8lo != 0xee) 256 | { 257 | //printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); 258 | //printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); 259 | int slen = strlen(strings_list[header->u.cmd_submit.request.wValue.u8lo]); 260 | int wslen = slen * 2; 261 | int buff_len = sizeof(usb_string_descriptor) + wslen; 262 | char temp_buff[64]; 263 | usb_string_descriptor *desc = (usb_string_descriptor *)temp_buff; 264 | desc->bLength = buff_len; 265 | desc->bDescriptorType = USB_DT_STRING; 266 | for (int i = 0; i < slen; i++) 267 | { 268 | desc->wData[i] = strings_list[header->u.cmd_submit.request.wValue.u8lo][i]; 269 | 270 | } 271 | send_stage2_submit_data(header, 0, (uint8_t *)temp_buff, buff_len); 272 | } 273 | else 274 | { 275 | printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); 276 | printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); 277 | printf("***Unsupported String descriptor***\r\n"); 278 | send_stage2_submit(header, 0, 0); 279 | } 280 | break; 281 | 282 | case USB_DT_INTERFACE: 283 | printf("* GET 0x04 INTERFACE DESCRIPTOR (UNIMPLEMENTED)\r\n"); 284 | ////TODO:UNIMPLEMENTED 285 | send_stage2_submit(header, 0, 0); 286 | break; 287 | 288 | case USB_DT_ENDPOINT: 289 | printf("* GET 0x05 ENDPOINT DESCRIPTOR (UNIMPLEMENTED)\r\n"); 290 | ////TODO:UNIMPLEMENTED 291 | send_stage2_submit(header, 0, 0); 292 | break; 293 | 294 | case USB_DT_DEVICE_QUALIFIER: 295 | printf("* GET 0x06 DEVICE QUALIFIER DESCRIPTOR\r\n"); 296 | 297 | usb_device_qualifier_descriptor desc; 298 | 299 | memset(&desc, 0, sizeof(usb_device_qualifier_descriptor)); 300 | 301 | send_stage2_submit_data(header, 0, &desc, sizeof(usb_device_qualifier_descriptor)); 302 | break; 303 | 304 | case USB_DT_OTHER_SPEED_CONFIGURATION: 305 | printf("GET 0x07 [UNIMPLEMENTED] USB_DT_OTHER_SPEED_CONFIGURATION\r\n"); 306 | ////TODO:UNIMPLEMENTED 307 | send_stage2_submit(header, 0, 0); 308 | break; 309 | 310 | case USB_DT_INTERFACE_POWER: 311 | printf("GET 0x08 [UNIMPLEMENTED] USB_DT_INTERFACE_POWER\r\n"); 312 | ////TODO:UNIMPLEMENTED 313 | send_stage2_submit(header, 0, 0); 314 | break; 315 | #if (USE_WINUSB == 1) 316 | case USB_DT_BOS: 317 | printf("* GET 0x0F BOS DESCRIPTOR\r\n"); 318 | send_stage2_submit_data(header, 0, bosDescriptor, sizeof(bosDescriptor)); 319 | break; 320 | #else 321 | case USB_DT_HID_REPORT: 322 | printf("* GET 0x22 HID REPORT DESCRIPTOR\r\n"); 323 | send_stage2_submit_data(header, 0, (void *)kHidReportDescriptor, sizeof(kHidReportDescriptor)); 324 | break; 325 | #endif 326 | default: 327 | //// TODO: ms os 1.0 descriptor 328 | printf("USB unknown Get Descriptor requested:%d\r\n", header->u.cmd_submit.request.wValue.u8lo); 329 | printf("low bit :%d\r\n",header->u.cmd_submit.request.wValue.u8lo); 330 | printf("high bit :%d\r\n",header->u.cmd_submit.request.wValue.u8hi); 331 | break; 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /components/USBIP/USB_handle.h: -------------------------------------------------------------------------------- 1 | #ifndef __USB_HANDLE_H__ 2 | #define __USB_HANDLE_H__ 3 | 4 | #include "components/USBIP/USBIP_defs.h" 5 | 6 | void handleUSBControlRequest(usbip_stage2_header *header); 7 | 8 | #endif -------------------------------------------------------------------------------- /main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_ADD_INCLUDEDIRS "${PROJECT_PATH}") 2 | set(COMPONENT_SRCS "main.c wifi_connect.c tcp_server.c usbip_server.c dap_handle.c my_task.c") 3 | 4 | register_component() -------------------------------------------------------------------------------- /main/dap_configuration.h: -------------------------------------------------------------------------------- 1 | #ifndef __DAP_CONFIGURATION_H__ 2 | #define __DAP_CONFIGURATION_H__ 3 | 4 | /** 5 | * @brief Specify the use of WINUSB 6 | * 7 | */ 8 | #define USE_WINUSB 1 9 | 10 | /// Maximum Package Size for Command and Response data. 11 | /// This configuration settings is used to optimize the communication performance with the 12 | /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, 13 | /// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. 14 | 15 | #if (USE_WINUSB == 1) 16 | #define DAP_PACKET_SIZE 1024U // 512 for WinUSB. 17 | #else 18 | #define DAP_PACKET_SIZE 255U // 255 for USB HID 19 | #endif 20 | 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /main/dap_handle.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file DAP_handle.c 3 | * @brief Handle DAP packets and transaction push 4 | * @version 0.4 5 | * @change: 2020.02.04 first version 6 | * 2020.11.11 support WinUSB mode 7 | * 2021.02.17 support SWO 8 | * 9 | * @copyright Copyright (c) 2021 10 | * 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #include "main/usbip_server.h" 17 | #include "main/DAP_handle.h" 18 | #include "main/dap_configuration.h" 19 | 20 | #include "components/USBIP/USB_descriptor.h" 21 | #include "components/DAP/include/DAP.h" 22 | //#include "swo.h" 23 | 24 | #include "freertos/FreeRTOS.h" 25 | #include "freertos/task.h" 26 | #include "freertos/ringbuf.h" 27 | #include "freertos/semphr.h" 28 | 29 | #include "lwip/err.h" 30 | #include "lwip/sockets.h" 31 | #include "lwip/sys.h" 32 | #include 33 | 34 | extern int kSock; 35 | extern TaskHandle_t kDAPTaskHandle; 36 | 37 | static portMUX_TYPE my_mutex; 38 | 39 | int kRestartDAPHandle = 0; 40 | 41 | 42 | #if (USE_WINUSB == 1) 43 | typedef struct 44 | { 45 | uint32_t length; 46 | uint8_t buf[DAP_PACKET_SIZE]; 47 | } DAPPacetDataType; 48 | #else 49 | typedef struct 50 | { 51 | uint8_t buf[DAP_PACKET_SIZE]; 52 | } DAPPacetDataType; 53 | #endif 54 | 55 | 56 | #define DAP_HANDLE_SIZE (sizeof(DAPPacetDataType)) 57 | 58 | static DAPPacetDataType DAPDataProcessed; 59 | static _Atomic int dap_respond = 0; 60 | 61 | 62 | // SWO Trace 63 | static uint8_t *swo_data_to_send = NULL; 64 | static uint32_t swo_data_num; 65 | 66 | 67 | 68 | // DAP handle 69 | static RingbufHandle_t dap_dataIN_handle = NULL; 70 | static RingbufHandle_t dap_dataOUT_handle = NULL; 71 | static SemaphoreHandle_t data_response_mux = NULL; 72 | 73 | static void unpack(void *data, int size); 74 | 75 | void handle_dap_data_request(usbip_stage2_header *header, uint32_t length) 76 | { 77 | uint8_t *data_in = (uint8_t *)header; 78 | data_in = &(data_in[sizeof(usbip_stage2_header)]); 79 | // Point to the beginning of the URB packet 80 | 81 | #if (USE_WINUSB == 1) 82 | send_stage2_submit(header, 0, 0); 83 | 84 | // always send constant size buf -> cuz we don't care about the IN packet size 85 | // and to unify the style, we set aside the length of the section 86 | xRingbufferSend(dap_dataIN_handle, data_in - sizeof(uint32_t), DAP_HANDLE_SIZE, portMAX_DELAY); 87 | xTaskNotifyGive(kDAPTaskHandle); 88 | 89 | #else 90 | send_stage2_submit(header, 0, 0); 91 | 92 | xRingbufferSend(dap_dataIN_handle, data_in, DAP_HANDLE_SIZE, portMAX_DELAY); 93 | xTaskNotifyGive(kDAPTaskHandle); 94 | 95 | #endif 96 | 97 | // dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); 98 | // //handle_dap_data_response(header); 99 | // send_stage2_submit(header, 0, 0); 100 | } 101 | 102 | void handle_dap_data_response(usbip_stage2_header *header) 103 | { 104 | return; 105 | // int resLength = dap_respond & 0xFFFF; 106 | // if (resLength) 107 | // { 108 | 109 | // send_stage2_submit_data(header, 0, (void *)DAPDataProcessed.buf, resLength); 110 | // dap_respond = 0; 111 | // } 112 | // else 113 | // { 114 | // send_stage2_submit(header, 0, 0); 115 | // } 116 | } 117 | 118 | void handle_swo_trace_response(usbip_stage2_header *header) 119 | { 120 | #if (SWO_FUNCTION_ENABLE == 1) 121 | if (kSwoTransferBusy) 122 | { 123 | // busy indicates that there is data to be send 124 | printf("swo use data\r\n"); 125 | send_stage2_submit_data(header, 0, (void *)swo_data_to_send, swo_data_num); 126 | SWO_TransferComplete(); 127 | } 128 | else 129 | { 130 | // nothing to send. 131 | send_stage2_submit(header, 0, 0); 132 | } 133 | #else 134 | send_stage2_submit(header, 0, 0); 135 | #endif 136 | } 137 | 138 | // SWO Data Queue Transfer 139 | // buf: pointer to buffer with data 140 | // num: number of bytes to transfer 141 | void SWO_QueueTransfer(uint8_t *buf, uint32_t num) 142 | { 143 | swo_data_to_send = buf; 144 | swo_data_num = num; 145 | } 146 | 147 | IRAM_ATTR void DAP_Thread(void *argument) 148 | { 149 | // vPortCPUInitializeMutex(&my_mutex); 150 | // portENTER_CRITICAL(&my_mutex); 151 | //portDISABLE_INTERRUPTS(); 152 | 153 | dap_dataIN_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF); 154 | dap_dataOUT_handle = xRingbufferCreate(368 * 20, RINGBUF_TYPE_BYTEBUF); 155 | data_response_mux = xSemaphoreCreateMutex(); 156 | size_t packetSize; 157 | int resLength; 158 | DAPPacetDataType *item; 159 | 160 | if (dap_dataIN_handle == NULL || dap_dataIN_handle == NULL || 161 | data_response_mux == NULL) 162 | { 163 | printf("Can not create DAP ringbuf/mux!\r\n"); 164 | vTaskDelete(NULL); 165 | } 166 | 167 | ulTaskNotifyTake(pdFALSE, portMAX_DELAY); 168 | vPortCPUInitializeMutex(&my_mutex); 169 | portENTER_CRITICAL(&my_mutex); 170 | goto start; 171 | for (;;) 172 | { 173 | 174 | while (1) 175 | { 176 | if (kRestartDAPHandle) 177 | { 178 | vRingbufferDelete(dap_dataIN_handle); 179 | vRingbufferDelete(dap_dataOUT_handle); 180 | dap_dataIN_handle = dap_dataOUT_handle = NULL; 181 | 182 | dap_dataIN_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF); 183 | dap_dataOUT_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF); 184 | if (dap_dataIN_handle == NULL || dap_dataIN_handle == NULL) 185 | { 186 | printf("Can not create DAP ringbuf/mux!\r\n"); 187 | vTaskDelete(NULL); 188 | } 189 | kRestartDAPHandle = 0; 190 | } 191 | 192 | ulTaskNotifyTake(pdFALSE, portMAX_DELAY); 193 | start: 194 | packetSize = 0; 195 | item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize, 196 | 0, DAP_HANDLE_SIZE); 197 | if (packetSize == 0) 198 | { 199 | break; 200 | } 201 | 202 | 203 | if (item->buf[0] == ID_DAP_QueueCommands) 204 | { 205 | item->buf[0] = ID_DAP_ExecuteCommands; 206 | } 207 | 208 | resLength = DAP_ProcessCommand((uint8_t *)item->buf, (uint8_t *)DAPDataProcessed.buf); // use first 4 byte to save length 209 | resLength &= 0xFFFF; // res length in lower 16 bits 210 | 211 | vRingbufferReturnItem(dap_dataIN_handle, (void *)item); // process done. 212 | 213 | // now prepare to reply 214 | #if (USE_WINUSB == 1) 215 | DAPDataProcessed.length = resLength; 216 | #endif 217 | xRingbufferSend(dap_dataOUT_handle, (void *)&DAPDataProcessed, 368, portMAX_DELAY); 218 | 219 | // if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) 220 | // { 221 | ++dap_respond; 222 | // xSemaphoreGive(data_response_mux); 223 | // } 224 | } 225 | } 226 | } 227 | 228 | int fast_reply(uint8_t *buf, uint32_t length) 229 | { 230 | if (length == 48 && buf[3] == 1 && buf[15] == 1 && buf[19] == 1) 231 | { 232 | if (dap_respond > 0) 233 | { 234 | DAPPacetDataType *item; 235 | size_t packetSize = 0; 236 | item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataOUT_handle, &packetSize, 237 | (10 / portTICK_RATE_MS), 368); 238 | if (packetSize == 368) 239 | { 240 | unpack((uint32_t *)buf, sizeof(usbip_stage2_header)); 241 | 242 | #if (USE_WINUSB == 1) 243 | uint32_t resLength = item->length; 244 | send_stage2_submit_data_fast((usbip_stage2_header *)buf, 0, item->buf, resLength); 245 | #else 246 | send_stage2_submit_data_fast((usbip_stage2_header *)buf, 0, item->buf, DAP_HANDLE_SIZE); 247 | #endif 248 | 249 | 250 | // if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) 251 | // { 252 | --dap_respond; 253 | // xSemaphoreGive(data_response_mux); 254 | // } 255 | 256 | vRingbufferReturnItem(dap_dataOUT_handle, (void *)item); 257 | return 1; 258 | } 259 | else if (packetSize > 0) 260 | { 261 | printf("Wrong data out packet size:%d!\r\n", packetSize); 262 | } 263 | ////TODO: fast reply 264 | } 265 | else 266 | { 267 | //// TODO: ep0 dir 0 ? 268 | buf[0x3] = 0x3; // command 269 | buf[0xF] = 0; // direction 270 | buf[0x16] = 0; 271 | buf[0x17] = 0; 272 | buf[27] = 0; 273 | buf[39] = 0; 274 | send(kSock, buf, 48, 0); 275 | return 1; 276 | } 277 | } 278 | return 0; 279 | } 280 | 281 | static void unpack(void *data, int size) 282 | { 283 | // Ignore the setup field 284 | int sz = (size / sizeof(uint32_t)) - 2; 285 | uint32_t *ptr = (uint32_t *)data; 286 | 287 | for (int i = 0; i < sz; i++) 288 | { 289 | ptr[i] = ntohl(ptr[i]); 290 | } 291 | } -------------------------------------------------------------------------------- /main/dap_handle.h: -------------------------------------------------------------------------------- 1 | #ifndef __DAP_HANDLE_H__ 2 | #define __DAP_HANDLE_H__ 3 | 4 | #include "components/USBIP/USBIP_defs.h" 5 | 6 | void handle_dap_data_request(usbip_stage2_header *header, uint32_t length); 7 | void handle_dap_data_response(usbip_stage2_header *header); 8 | void handle_swo_trace_response(usbip_stage2_header *header); 9 | 10 | int fast_reply(uint8_t *buf, uint32_t length); 11 | 12 | #endif -------------------------------------------------------------------------------- /main/main.c: -------------------------------------------------------------------------------- 1 | /* BSD Socket API Example 2 | 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | 5 | Unless required by applicable law or agreed to in writing, this 6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 | CONDITIONS OF ANY KIND, either express or implied. 8 | */ 9 | #include 10 | #include 11 | 12 | #include "freertos/FreeRTOS.h" 13 | #include "freertos/task.h" 14 | #include "esp_system.h" 15 | #include "esp_wifi.h" 16 | #include "esp_event.h" 17 | #include "esp_log.h" 18 | #include "nvs_flash.h" 19 | #include "esp_netif.h" 20 | 21 | #include "lwip/err.h" 22 | #include "lwip/sockets.h" 23 | #include "lwip/sys.h" 24 | #include 25 | 26 | #include "main/wifi_connect.h" 27 | #include "main/wifi_configuration.h" 28 | #include "main/tcp_server.h" 29 | 30 | extern void DAP_Setup(void); 31 | extern void DAP_Thread(void *argument); 32 | extern void SWO_Thread(); 33 | 34 | extern void my_task(); 35 | 36 | TaskHandle_t kDAPTaskHandle = NULL; 37 | 38 | void app_main(void) 39 | { 40 | ESP_ERROR_CHECK(nvs_flash_init()); 41 | ESP_ERROR_CHECK(esp_netif_init()); 42 | ESP_ERROR_CHECK(esp_event_loop_create_default()); 43 | ESP_ERROR_CHECK(wifi_connect()); 44 | 45 | DAP_Setup(); 46 | 47 | 48 | xTaskCreatePinnedToCore(tcp_server_task, "tcp_server", 4096, NULL, 14, NULL, 0); 49 | xTaskCreatePinnedToCore(DAP_Thread, "DAP_Task", 2048, NULL, 10, &kDAPTaskHandle, 1); 50 | } 51 | -------------------------------------------------------------------------------- /main/my_task.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "freertos/FreeRTOS.h" 4 | #include "freertos/task.h" 5 | 6 | 7 | #include "components/DAP/config/DAP_config.h" 8 | 9 | #include "driver/gpio.h" 10 | 11 | void DAP_SPI_Deinit(); 12 | static portMUX_TYPE my_mutex; 13 | static volatile int a = 0; 14 | void my_task() 15 | { 16 | vPortCPUInitializeMutex(&my_mutex); 17 | portENTER_CRITICAL(&my_mutex); 18 | // portDISABLE_INTERRUPTS(); 19 | 20 | DAP_SPI_Deinit(); 21 | for(;;){ 22 | //a++; 23 | //if(a%20000 == 0) 24 | ulTaskNotifyTake(pdFALSE, portMAX_DELAY); 25 | { 26 | PIN_SWCLK_TCK_SET(); 27 | PIN_SWCLK_TCK_CLR(); 28 | PIN_SWCLK_TCK_SET(); 29 | PIN_SWCLK_TCK_CLR(); 30 | PIN_SWCLK_TCK_SET(); 31 | PIN_SWCLK_TCK_CLR(); 32 | PIN_SWCLK_TCK_SET(); 33 | PIN_SWCLK_TCK_CLR(); 34 | PIN_SWCLK_TCK_SET(); 35 | PIN_SWCLK_TCK_CLR(); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /main/tcp_server.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tcp_server.c 3 | * @brief Handle main tcp tasks 4 | * @version 0.1 5 | * @date 2020-01-22 6 | * 7 | * @copyright Copyright (c) 2020 8 | * 9 | */ 10 | #include "tcp_server.h" 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "freertos/FreeRTOS.h" 17 | #include "freertos/task.h" 18 | #include "freertos/event_groups.h" 19 | 20 | 21 | #include "lwip/err.h" 22 | #include "lwip/sockets.h" 23 | #include "lwip/sys.h" 24 | #include 25 | 26 | #include "main/wifi_configuration.h" 27 | #include "main/usbip_server.h" 28 | 29 | extern TaskHandle_t kDAPTaskHandle; 30 | extern int kRestartDAPHandle; 31 | 32 | 33 | 34 | uint8_t kState = ACCEPTING; 35 | int kSock = -1; 36 | 37 | 38 | static uint8_t tcp_rx_buffer[2048]; 39 | static char addr_str[128]; 40 | 41 | void tcp_server_task() 42 | { 43 | 44 | int addr_family; 45 | int ip_protocol; 46 | 47 | int on = 1; 48 | while (1) 49 | { 50 | 51 | #ifdef CONFIG_EXAMPLE_IPV4 52 | struct sockaddr_in destAddr; 53 | destAddr.sin_addr.s_addr = htonl(INADDR_ANY); 54 | destAddr.sin_family = AF_INET; 55 | destAddr.sin_port = htons(PORT); 56 | addr_family = AF_INET; 57 | ip_protocol = IPPROTO_IP; 58 | inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); 59 | #else // IPV6 60 | struct sockaddr_in6 destAddr; 61 | bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un)); 62 | destAddr.sin6_family = AF_INET6; 63 | destAddr.sin6_port = htons(PORT); 64 | addr_family = AF_INET6; 65 | ip_protocol = IPPROTO_IPV6; 66 | inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); 67 | #endif 68 | 69 | int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); 70 | if (listen_sock < 0) 71 | { 72 | printf("Unable to create socket: errno %d\r\n", errno); 73 | break; 74 | } 75 | printf("Socket created\r\n"); 76 | 77 | setsockopt(listen_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); 78 | setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)); 79 | 80 | int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); 81 | if (err != 0) 82 | { 83 | printf("Socket unable to bind: errno %d\r\n", errno); 84 | break; 85 | } 86 | printf("Socket binded\r\n"); 87 | 88 | err = listen(listen_sock, 1); 89 | if (err != 0) 90 | { 91 | printf("Error occured during listen: errno %d\r\n", errno); 92 | break; 93 | } 94 | printf("Socket listening\r\n"); 95 | 96 | #ifdef CONFIG_EXAMPLE_IPV6 97 | struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 98 | #else 99 | struct sockaddr_in sourceAddr; 100 | #endif 101 | uint32_t addrLen = sizeof(sourceAddr); 102 | while (1) 103 | { 104 | kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); 105 | if (kSock < 0) 106 | { 107 | printf("Unable to accept connection: errno %d\r\n", errno); 108 | break; 109 | } 110 | setsockopt(kSock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); 111 | setsockopt(kSock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)); 112 | printf("Socket accepted\r\n"); 113 | 114 | while (1) 115 | { 116 | int len = recv(kSock, tcp_rx_buffer, sizeof(tcp_rx_buffer), 0); 117 | // Error occured during receiving 118 | if (len < 0) 119 | { 120 | printf("recv failed: errno %d\r\n", errno); 121 | break; 122 | } 123 | // Connection closed 124 | else if (len == 0) 125 | { 126 | printf("Connection closed\r\n"); 127 | break; 128 | } 129 | // Data received 130 | else 131 | { 132 | // #ifdef CONFIG_EXAMPLE_IPV6 133 | // // Get the sender's ip address as string 134 | // if (sourceAddr.sin6_family == PF_INET) 135 | // { 136 | // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); 137 | // } 138 | // else if (sourceAddr.sin6_family == PF_INET6) 139 | // { 140 | // inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); 141 | // } 142 | // #else 143 | // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); 144 | // #endif 145 | 146 | switch (kState) 147 | { 148 | case ACCEPTING: 149 | kState = ATTACHING; 150 | 151 | case ATTACHING: 152 | attach(tcp_rx_buffer, len); 153 | break; 154 | 155 | case EMULATING: 156 | emulate(tcp_rx_buffer, len); 157 | break; 158 | default: 159 | printf("unkonw kstate!\r\n"); 160 | } 161 | } 162 | } 163 | // kState = ACCEPTING; 164 | if (kSock != -1) 165 | { 166 | printf("Shutting down socket and restarting...\r\n"); 167 | //shutdown(kSock, 0); 168 | close(kSock); 169 | if (kState == EMULATING) 170 | kState = ACCEPTING; 171 | 172 | // Restart DAP Handle 173 | kRestartDAPHandle = 1; 174 | xTaskNotifyGive(kDAPTaskHandle); 175 | 176 | //shutdown(listen_sock, 0); 177 | //close(listen_sock); 178 | //vTaskDelay(5); 179 | } 180 | } 181 | } 182 | vTaskDelete(NULL); 183 | } -------------------------------------------------------------------------------- /main/tcp_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __TCP_SERVER_H__ 2 | #define __TCP_SERVER_H__ 3 | 4 | void tcp_server_task(); 5 | 6 | #endif -------------------------------------------------------------------------------- /main/usbip_server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "lwip/err.h" 5 | #include "lwip/sockets.h" 6 | #include "lwip/sys.h" 7 | #include 8 | 9 | #include "components/USBIP/USB_handle.h" 10 | #include "components/USBIP/USB_descriptor.h" 11 | 12 | #include "main/usbip_server.h" 13 | #include "main/dap_handle.h" 14 | 15 | 16 | // attach helper function 17 | static int read_stage1_command(uint8_t *buffer, uint32_t length); 18 | static void handle_device_list(uint8_t *buffer, uint32_t length); 19 | static void handle_device_attach(uint8_t *buffer, uint32_t length); 20 | static void send_stage1_header(uint16_t command, uint32_t status); 21 | static void send_device_list(); 22 | static void send_device_info(); 23 | static void send_interface_info(); 24 | 25 | // emulate helper function 26 | static void pack(void *data, int size); 27 | static void unpack(void *data, int size); 28 | static int handle_submit(usbip_stage2_header *header, uint32_t length); 29 | static int read_stage2_command(usbip_stage2_header *header, uint32_t length); 30 | 31 | static void handle_unlink(usbip_stage2_header *header); 32 | // unlink helper function 33 | static void send_stage2_unlink(usbip_stage2_header *req_header); 34 | 35 | 36 | 37 | int attach(uint8_t *buffer, uint32_t length) 38 | { 39 | int command = read_stage1_command(buffer, length); 40 | if (command < 0) 41 | { 42 | return -1; 43 | } 44 | 45 | switch (command) 46 | { 47 | case USBIP_STAGE1_CMD_DEVICE_LIST: // OP_REQ_DEVLIST 48 | handle_device_list(buffer, length); 49 | break; 50 | 51 | case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT 52 | handle_device_attach(buffer, length); 53 | break; 54 | 55 | default: 56 | printf("attach Unknown command: %d\r\n", command); 57 | break; 58 | } 59 | return 0; 60 | } 61 | 62 | static int read_stage1_command(uint8_t *buffer, uint32_t length) 63 | { 64 | if (length < sizeof(usbip_stage1_header)) 65 | { 66 | return -1; 67 | } 68 | usbip_stage1_header *req = (usbip_stage1_header *)buffer; 69 | return (ntohs(req->command) & 0xFF); // 0x80xx low bit 70 | } 71 | 72 | static void handle_device_list(uint8_t *buffer, uint32_t length) 73 | { 74 | printf("Handling dev list request...\r\n"); 75 | send_stage1_header(USBIP_STAGE1_CMD_DEVICE_LIST, 0); 76 | send_device_list(); 77 | } 78 | 79 | static void handle_device_attach(uint8_t *buffer, uint32_t length) 80 | { 81 | printf("Handling dev attach request...\r\n"); 82 | 83 | //char bus[USBIP_BUSID_SIZE]; 84 | if (length < sizeof(USBIP_BUSID_SIZE)) 85 | { 86 | printf("handle device attach failed!\r\n"); 87 | return; 88 | } 89 | //client.readBytes((uint8_t *)bus, USBIP_BUSID_SIZE); 90 | 91 | send_stage1_header(USBIP_STAGE1_CMD_DEVICE_ATTACH, 0); 92 | 93 | send_device_info(); 94 | 95 | kState = EMULATING; 96 | } 97 | 98 | static void send_stage1_header(uint16_t command, uint32_t status) 99 | { 100 | printf("Sending header...\r\n"); 101 | usbip_stage1_header header; 102 | header.version = htons(273); ////TODO: 273??? 103 | // may be : https://github.com/Oxalin/usbip_windows/issues/4 104 | 105 | header.command = htons(command); 106 | header.status = htonl(status); 107 | 108 | send(kSock, (uint8_t *)&header, sizeof(usbip_stage1_header), 0); 109 | } 110 | 111 | static void send_device_list() 112 | { 113 | printf("Sending device list...\r\n"); 114 | 115 | // send device list size: 116 | printf("Sending device list size...\r\n"); 117 | usbip_stage1_response_devlist response_devlist; 118 | 119 | // we have only 1 device, so: 120 | response_devlist.list_size = htonl(1); 121 | 122 | send(kSock, (uint8_t *)&response_devlist, sizeof(usbip_stage1_response_devlist), 0); 123 | 124 | // may be foreach: 125 | 126 | { 127 | // send device info: 128 | send_device_info(); 129 | // send device interfaces: // (1) 130 | send_interface_info(); 131 | } 132 | } 133 | 134 | static void send_device_info() 135 | { 136 | printf("Sending device info...\r\n"); 137 | usbip_stage1_usb_device device; 138 | 139 | strcpy(device.path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1"); 140 | strcpy(device.busid, "1-1"); 141 | 142 | device.busnum = htonl(1); 143 | device.devnum = htonl(1); 144 | device.speed = htonl(3); // See usb_device_speed enum 145 | 146 | device.idVendor = htons(USBD0_DEV_DESC_IDVENDOR); 147 | device.idProduct = htons(USBD0_DEV_DESC_IDPRODUCT); 148 | device.bcdDevice = htons(USBD0_DEV_DESC_BCDDEVICE); 149 | 150 | device.bDeviceClass = 0x00; // We need to use a device other than the USB-IF standard, set to 0x00 151 | device.bDeviceSubClass = 0x00; 152 | device.bDeviceProtocol = 0x00; 153 | 154 | device.bConfigurationValue = 1; 155 | device.bNumConfigurations = 1; 156 | device.bNumInterfaces = 1; 157 | 158 | send(kSock, (uint8_t *)&device, sizeof(usbip_stage1_usb_device), 0); 159 | } 160 | 161 | static void send_interface_info() 162 | { 163 | printf("Sending interface info...\r\n"); 164 | usbip_stage1_usb_interface interface; 165 | interface.bInterfaceClass = USBD_CUSTOM_CLASS0_IF0_CLASS; 166 | interface.bInterfaceSubClass = USBD_CUSTOM_CLASS0_IF0_SUBCLASS; 167 | interface.bInterfaceProtocol = USBD_CUSTOM_CLASS0_IF0_PROTOCOL; 168 | interface.padding = 0; // shall be set to zero 169 | 170 | send(kSock, (uint8_t *)&interface, sizeof(usbip_stage1_usb_interface), 0); 171 | } 172 | 173 | /////////////////////////////////////////////////////////////////////////// 174 | /////////////////////////////////////////////////////////////////////////// 175 | /////////////////////////////////////////////////////////////////////////// 176 | /////////////////////////////////////////////////////////////////////////// 177 | /////////////////////////////////////////////////////////////////////////// 178 | /////////////////////////////////////////////////////////////////////////// 179 | /////////////////////////////////////////////////////////////////////////// 180 | /////////////////////////////////////////////////////////////////////////// 181 | 182 | int emulate(uint8_t *buffer, uint32_t length) 183 | { 184 | if (length < 48) 185 | { 186 | for (int i = 0; i < 100; i++) 187 | { 188 | printf("TCP issue!\r\n"); 189 | } 190 | } 191 | 192 | if(fast_reply(buffer, length)) 193 | { 194 | return 0; 195 | } 196 | 197 | int command = read_stage2_command((usbip_stage2_header *)buffer, length); 198 | if (command < 0) 199 | { 200 | return -1; 201 | } 202 | 203 | switch (command) 204 | { 205 | case USBIP_STAGE2_REQ_SUBMIT: 206 | handle_submit((usbip_stage2_header *)buffer , length); 207 | break; 208 | 209 | case USBIP_STAGE2_REQ_UNLINK: 210 | handle_unlink((usbip_stage2_header *)buffer); 211 | break; 212 | 213 | default: 214 | printf("emulate unknown command:%d\r\n", command); 215 | //handle_submit((usbip_stage2_header *)buffer, length); 216 | return -1; 217 | } 218 | return 0; 219 | } 220 | 221 | static int read_stage2_command(usbip_stage2_header *header, uint32_t length) 222 | { 223 | if (length < sizeof(usbip_stage2_header)) 224 | { 225 | return -1; 226 | } 227 | 228 | //client.readBytes((uint8_t *)&header, sizeof(usbip_stage2_header)); 229 | unpack((uint32_t *)header, sizeof(usbip_stage2_header)); 230 | return header->base.command; 231 | } 232 | 233 | /** 234 | * @brief Pack the following packets(Offset 0x00 - 0x28): 235 | * - cmd_submit 236 | * - ret_submit 237 | * - cmd_unlink 238 | * - ret_unlink 239 | * 240 | * @param data Point to packets header 241 | * @param size Packets header size 242 | */ 243 | static void pack(void *data, int size) 244 | { 245 | 246 | // Ignore the setup field 247 | int sz = (size / sizeof(uint32_t)) - 2; 248 | uint32_t *ptr = (uint32_t *)data; 249 | 250 | for (int i = 0; i < sz; i++) 251 | { 252 | 253 | ptr[i] = htonl(ptr[i]); 254 | } 255 | } 256 | 257 | /** 258 | * @brief Unack the following packets(Offset 0x00 - 0x28): 259 | * - cmd_submit 260 | * - ret_submit 261 | * - cmd_unlink 262 | * - ret_unlink 263 | * 264 | * @param data Point to packets header 265 | * @param size packets header size 266 | */ 267 | static void unpack(void *data, int size) 268 | { 269 | 270 | // Ignore the setup field 271 | int sz = (size / sizeof(uint32_t)) - 2; 272 | uint32_t *ptr = (uint32_t *)data; 273 | 274 | for (int i = 0; i < sz; i++) 275 | { 276 | ptr[i] = ntohl(ptr[i]); 277 | } 278 | } 279 | 280 | /** 281 | * @brief USB transaction processing 282 | * 283 | */ 284 | static int handle_submit(usbip_stage2_header *header, uint32_t length) 285 | { 286 | switch (header->base.ep) 287 | { 288 | // control endpoint(endpoint 0) 289 | case 0x00: 290 | //// TODO: judge usb setup 8 byte? 291 | handleUSBControlRequest(header); 292 | break; 293 | 294 | // endpoint 1 data receicve and response 295 | case 0x01: 296 | if (header->base.direction == 0) 297 | { 298 | //printf("EP 01 DATA FROM HOST"); 299 | handle_dap_data_request(header ,length); 300 | } 301 | else 302 | { 303 | // printf("EP 01 DATA TO HOST\r\n"); 304 | handle_dap_data_response(header); 305 | } 306 | break; 307 | // endpoint 2 for SWO trace 308 | case 0x02: 309 | if (header->base.direction == 0) 310 | { 311 | // printf("EP 02 DATA FROM HOST"); 312 | send_stage2_submit(header, 0, 0); 313 | } 314 | else 315 | { 316 | // printf("EP 02 DATA TO HOST"); 317 | //// FIXME: esp32 318 | handle_swo_trace_response(header); 319 | } 320 | break; 321 | // request to save data to device 322 | case 0x81: 323 | if (header->base.direction == 0) 324 | { 325 | printf("*** WARN! EP 81 DATA TX"); 326 | } 327 | else 328 | { 329 | printf("*** WARN! EP 81 DATA RX"); 330 | } 331 | return -1; 332 | 333 | default: 334 | printf("*** WARN ! UNKNOWN ENDPOINT: %d\r\n", (int)header->base.ep); 335 | return -1; 336 | } 337 | return 0; 338 | } 339 | 340 | void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length) 341 | { 342 | 343 | req_header->base.command = USBIP_STAGE2_RSP_SUBMIT; 344 | req_header->base.direction = !(req_header->base.direction); 345 | 346 | memset(&(req_header->u.ret_submit), 0, sizeof(usbip_stage2_header_ret_submit)); 347 | 348 | req_header->u.ret_submit.status = status; 349 | req_header->u.ret_submit.data_length = data_length; 350 | 351 | pack(req_header, sizeof(usbip_stage2_header)); 352 | send(kSock, req_header, sizeof(usbip_stage2_header), 0); 353 | } 354 | 355 | void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length) 356 | { 357 | 358 | send_stage2_submit(req_header, status, data_length); 359 | 360 | if (data_length) 361 | { 362 | send(kSock, data, data_length, 0); 363 | } 364 | } 365 | 366 | void send_stage2_submit_data_fast(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length) 367 | { 368 | const uint8_t * send_buf = (uint8_t *)req_header; 369 | 370 | req_header->base.command = USBIP_STAGE2_RSP_SUBMIT; 371 | req_header->base.direction = !(req_header->base.direction); 372 | 373 | memset(&(req_header->u.ret_submit), 0, sizeof(usbip_stage2_header_ret_submit)); 374 | 375 | req_header->u.ret_submit.status = status; 376 | req_header->u.ret_submit.data_length = data_length; 377 | 378 | pack(req_header, sizeof(usbip_stage2_header)); 379 | 380 | // payload 381 | memcpy(&send_buf[sizeof(usbip_stage2_header)], data, data_length); 382 | send(kSock, send_buf, sizeof(usbip_stage2_header) + data_length, 0); 383 | } 384 | 385 | static void handle_unlink(usbip_stage2_header *header) 386 | { 387 | printf("s2 handling cmd unlink...\r\n"); 388 | send_stage2_unlink(header); 389 | } 390 | static void send_stage2_unlink(usbip_stage2_header *req_header) 391 | { 392 | 393 | req_header->base.command = USBIP_STAGE2_RSP_UNLINK; 394 | req_header->base.direction = USBIP_DIR_OUT; 395 | 396 | memset(&(req_header->u.ret_unlink), 0, sizeof(usbip_stage2_header_ret_unlink)); 397 | 398 | // req_header.u.ret_unlink.status = 0; 399 | 400 | pack(req_header, sizeof(usbip_stage2_header)); 401 | 402 | send(kSock, req_header, sizeof(usbip_stage2_header), 0); 403 | } -------------------------------------------------------------------------------- /main/usbip_server.h: -------------------------------------------------------------------------------- 1 | #ifndef __USBIP_SERVER_H__ 2 | #define __USBIP_SERVER_H__ 3 | 4 | #include 5 | 6 | #include "components/USBIP/USBIP_defs.h" 7 | 8 | 9 | enum state_t 10 | { 11 | ACCEPTING, 12 | ATTACHING, 13 | EMULATING 14 | }; 15 | extern uint8_t kState; 16 | extern int kSock; 17 | 18 | int attach(uint8_t *buffer, uint32_t length); 19 | int emulate(uint8_t *buffer, uint32_t length); 20 | void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void * const data, int32_t data_length); 21 | void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length); 22 | void send_stage2_submit_data_fast(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length); 23 | 24 | 25 | #endif -------------------------------------------------------------------------------- /main/wifi_configuration.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file wifi_configuration.h 3 | * @brief Fill in your wifi configuration information here. 4 | * @version 0.1 5 | * @date 2020-01-22 6 | * 7 | * @copyright Copyright (c) 2020 8 | * 9 | */ 10 | #ifndef __WIFI_CONFIGURATION__ 11 | #define __WIFI_CONFIGURATION__ 12 | 13 | #define WIFI_SSID "DAP" 14 | #define WIFI_PASS "12345678" 15 | 16 | #define PORT 3240 17 | 18 | #define CONFIG_EXAMPLE_IPV4 1 19 | 20 | #endif -------------------------------------------------------------------------------- /main/wifi_connect.c: -------------------------------------------------------------------------------- 1 | /* Common functions for protocol examples, to establish Wi-Fi or Ethernet connection. 2 | 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | 5 | Unless required by applicable law or agreed to in writing, this 6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 | CONDITIONS OF ANY KIND, either express or implied. 8 | */ 9 | 10 | #include 11 | 12 | #include "esp_event.h" 13 | #include "esp_wifi.h" 14 | #include "esp_wifi_default.h" 15 | 16 | #include "esp_log.h" 17 | #include "esp_netif.h" 18 | #include "driver/gpio.h" 19 | #include "freertos/FreeRTOS.h" 20 | #include "freertos/task.h" 21 | #include "freertos/event_groups.h" 22 | #include "lwip/err.h" 23 | #include "lwip/sys.h" 24 | 25 | #include "main/wifi_connect.h" 26 | #include "main/wifi_configuration.h" 27 | 28 | #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 29 | #define MAX_IP6_ADDRS_PER_NETIF (5) 30 | #define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces*2) 31 | 32 | #if defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_LOCAL_LINK) 33 | #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_LINK_LOCAL 34 | #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_GLOBAL) 35 | #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_GLOBAL 36 | #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_SITE_LOCAL) 37 | #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_SITE_LOCAL 38 | #elif defined(CONFIG_EXAMPLE_CONNECT_IPV6_PREF_UNIQUE_LOCAL) 39 | #define EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE ESP_IP6_ADDR_IS_UNIQUE_LOCAL 40 | #endif // if-elif CONFIG_EXAMPLE_CONNECT_IPV6_PREF_... 41 | 42 | #else 43 | #define NR_OF_IP_ADDRESSES_TO_WAIT_FOR (s_active_interfaces) 44 | #endif 45 | 46 | static int s_active_interfaces = 0; 47 | static xSemaphoreHandle s_semph_get_ip_addrs; 48 | static esp_ip4_addr_t s_ip_addr; 49 | static esp_netif_t *s_example_esp_netif = NULL; 50 | 51 | #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 52 | static esp_ip6_addr_t s_ipv6_addr; 53 | 54 | /* types of ipv6 addresses to be displayed on ipv6 events */ 55 | static const char *s_ipv6_addr_types[] = { 56 | "ESP_IP6_ADDR_IS_UNKNOWN", 57 | "ESP_IP6_ADDR_IS_GLOBAL", 58 | "ESP_IP6_ADDR_IS_LINK_LOCAL", 59 | "ESP_IP6_ADDR_IS_SITE_LOCAL", 60 | "ESP_IP6_ADDR_IS_UNIQUE_LOCAL", 61 | "ESP_IP6_ADDR_IS_IPV4_MAPPED_IPV6" 62 | }; 63 | #endif 64 | 65 | static const char *TAG = "wifi_connect"; 66 | 67 | 68 | static esp_netif_t* wifi_start(void); 69 | static void wifi_stop(void); 70 | 71 | 72 | 73 | 74 | /** 75 | * @brief Checks the netif description if it contains specified prefix. 76 | * All netifs created withing common connect component are prefixed with the module TAG, 77 | * so it returns true if the specified netif is owned by this module 78 | */ 79 | static bool is_our_netif(const char *prefix, esp_netif_t *netif) 80 | { 81 | return strncmp(prefix, esp_netif_get_desc(netif), strlen(prefix)-1) == 0; 82 | } 83 | 84 | /* set up connection, Wi-Fi and/or Ethernet */ 85 | static void start(void) 86 | { 87 | s_example_esp_netif = wifi_start(); 88 | s_active_interfaces++; 89 | 90 | s_semph_get_ip_addrs = xSemaphoreCreateCounting(NR_OF_IP_ADDRESSES_TO_WAIT_FOR, 0); 91 | } 92 | 93 | /* tear down connection, release resources */ 94 | static void stop(void) 95 | { 96 | wifi_stop(); 97 | s_active_interfaces--; 98 | } 99 | 100 | static void on_got_ip(void *arg, esp_event_base_t event_base, 101 | int32_t event_id, void *event_data) 102 | { 103 | ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; 104 | if (!is_our_netif(TAG, event->esp_netif)) { 105 | ESP_LOGW(TAG, "Got IPv4 from another interface \"%s\": ignored", esp_netif_get_desc(event->esp_netif)); 106 | return; 107 | } 108 | ESP_LOGI(TAG, "Got IPv4 event: Interface \"%s\" address: " IPSTR, esp_netif_get_desc(event->esp_netif), IP2STR(&event->ip_info.ip)); 109 | memcpy(&s_ip_addr, &event->ip_info.ip, sizeof(s_ip_addr)); 110 | xSemaphoreGive(s_semph_get_ip_addrs); 111 | } 112 | 113 | #ifdef CONFIG_EXAMPLE_CONNECT_IPV6 114 | 115 | static void on_got_ipv6(void *arg, esp_event_base_t event_base, 116 | int32_t event_id, void *event_data) 117 | { 118 | ip_event_got_ip6_t *event = (ip_event_got_ip6_t *)event_data; 119 | if (!is_our_netif(TAG, event->esp_netif)) { 120 | ESP_LOGW(TAG, "Got IPv6 from another netif: ignored"); 121 | return; 122 | } 123 | esp_ip6_addr_type_t ipv6_type = esp_netif_ip6_get_addr_type(&event->ip6_info.ip); 124 | ESP_LOGI(TAG, "Got IPv6 event: Interface \"%s\" address: " IPV6STR ", type: %s", esp_netif_get_desc(event->esp_netif), 125 | IPV62STR(event->ip6_info.ip), s_ipv6_addr_types[ipv6_type]); 126 | if (ipv6_type == EXAMPLE_CONNECT_PREFERRED_IPV6_TYPE) { 127 | memcpy(&s_ipv6_addr, &event->ip6_info.ip, sizeof(s_ipv6_addr)); 128 | xSemaphoreGive(s_semph_get_ip_addrs); 129 | } 130 | } 131 | 132 | #endif // CONFIG_EXAMPLE_CONNECT_IPV6 133 | 134 | esp_err_t wifi_connect(void) 135 | { 136 | if (s_semph_get_ip_addrs != NULL) { 137 | return ESP_ERR_INVALID_STATE; 138 | } 139 | start(); 140 | ESP_ERROR_CHECK(esp_register_shutdown_handler(&stop)); 141 | ESP_LOGI(TAG, "Waiting for IP(s)"); 142 | for (int i=0; i