From 2c09346169d11c4f40f4c7000f02b91c5955182d Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 21 Jan 2020 22:03:05 +0800 Subject: [PATCH 01/21] feat: Mainly improve DAP configuration: 1. improve DAP configuration independent of specific hardware 2. add hardware timer 3. cmake configuration file simple modification 4. add some to-do items --- .gitignore | 1 + components/CMakeLists.txt | 0 components/DAP/config/DAP_config.h | 665 +++++++++++ components/DAP/include/DAP.h | 325 +++++ components/DAP/source/DAP.c | 1769 ++++++++++++++++++++++++++++ components/DAP/source/DAP_vendor.c | 100 ++ components/DAP/source/JTAG_DP.c | 370 ++++++ components/DAP/source/SWO.c | 800 +++++++++++++ components/DAP/source/SW_DP.c | 286 +++++ components/README.md | 3 + main/CMakeLists.txt | 2 +- main/tcp_server.c | 25 +- 12 files changed, 4343 insertions(+), 3 deletions(-) create mode 100644 components/CMakeLists.txt create mode 100644 components/DAP/config/DAP_config.h create mode 100644 components/DAP/include/DAP.h create mode 100644 components/DAP/source/DAP.c create mode 100644 components/DAP/source/DAP_vendor.c create mode 100644 components/DAP/source/JTAG_DP.c create mode 100644 components/DAP/source/SWO.c create mode 100644 components/DAP/source/SW_DP.c create mode 100644 components/README.md diff --git a/.gitignore b/.gitignore index 1d74e21..e524d79 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .vscode/ +build/ diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt new file mode 100644 index 0000000..e69de29 diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h new file mode 100644 index 0000000..048d766 --- /dev/null +++ b/components/DAP/config/DAP_config.h @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Configuration + * Title: DAP_config.h CMSIS-DAP Configuration File (Template) + * + *---------------------------------------------------------------------------*/ + +#ifndef __DAP_CONFIG_H__ +#define __DAP_CONFIG_H__ + +#include "gpio.h" +#include "gpio_struct.h" +#include "timer_struct.h" + +//************************************************************************************************** +/** +\defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information +\ingroup DAP_ConfigIO_gr +@{ +Provides definitions about the hardware and configuration of the Debug Unit. + +This information includes: + - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. + - Debug Unit Identification strings (Vendor, Product, Serial Number). + - Debug Unit communication packet size. + - Debug Access Port supported modes and settings (JTAG/SWD and SWO). + - Optional information about a connected Target Device (for Evaluation Boards). +*/ + +//#ifdef _RTE_ +//#include "RTE_Components.h" +//#include CMSIS_device_header +//#else +//#include "device.h" // Debug Unit Cortex-M Processor Header File +//#endif + +/// Processor Clock of the Cortex-M MCU used in the Debug Unit. +/// This value is used to calculate the SWD/JTAG clock speed. +#define CPU_CLOCK 160000000U ///< Specifies the CPU Clock in Hz. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz + +/// Number of processor cycles for I/O Port write operations. +/// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O +/// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors +/// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses +/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be +/// required. +#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. + +/// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. + +/// Indicate that JTAG communication mode is available at the Debug Port. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. + +/// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. +/// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. +#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. + +/// Default communication mode on the Debug Access Port. +/// Used for the command \ref DAP_Connect when Port Default mode is selected. +#define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. + +/// Default communication speed on the Debug Access Port for SWD and JTAG mode. +/// Used to initialize the default SWD/JTAG clock frequency. +/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. +#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<1MHz + +/// Maximum Package Size for Command and Response data. +/// This configuration settings is used to optimize the communication performance with the +/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, +/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. +#define DAP_PACKET_SIZE 512U ///< Specifies Packet Size in bytes. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 512 for High-speed USB WinUSB. + +/// Maximum Package Buffers for Command and Response data. +/// This configuration settings is used to optimize the communication performance with the +/// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the +/// setting can be reduced (valid range is 1 .. 255). +#define DAP_PACKET_COUNT 8U ///< Specifies number of packets buffered. + +/// Indicate that UART Serial Wire Output (SWO) trace is available. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define SWO_UART 1 ///< SWO UART: 1 = available, 0 = not available. + +/// Maximum SWO UART Baudrate. +#define SWO_UART_MAX_BAUDRATE 50000000U ///< SWO UART Maximum Baudrate in Hz. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz +// TODO: uncertain value + +/// Indicate that Manchester Serial Wire Output (SWO) trace is available. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define SWO_MANCHESTER 1 ///< SWO Manchester: 1 = available, 0 = not available. + +/// SWO Trace Buffer Size. +#define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). + +/// SWO Streaming Trace. +#define SWO_STREAM 1 ///< SWO Streaming Trace: 1 = available, 0 = not available. + +/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. +#define TIMESTAMP_CLOCK 5000000U ///< Timestamp clock in Hz (0 = timestamps not supported). +// <<<<<<<<<<<<<<<<<<<<<5MHz + +/// Debug Unit is connected to fixed Target Device. +/// The Debug Unit may be part of an evaluation board and always connected to a fixed +/// known device. In this case a Device Vendor and Device Name string is stored which +/// may be used by the debugger or IDE to configure device parameters. +#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; + +#if TARGET_DEVICE_FIXED +#define TARGET_DEVICE_VENDOR "ARM" ///< String indicating the Silicon Vendor +#define TARGET_DEVICE_NAME "Cortex-M4" ///< String indicating the Target Device +#endif + +/** + * @brief Get Vendor ID string. + * + * @param str Pointer to buffer to store the string. + * @return String length. + */ +__STATIC_INLINE uint8_t DAP_GetVendorString(char *str) +{ + //TODO: fill this + // In fact, Keil can get the corresponding information through USB + // without filling in this information. + (void)str; + return (0U); +} + +/** + * @brief Get Product ID string. + * + * @param str Pointer to buffer to store the string. + * @return String length. + */ +__STATIC_INLINE uint8_t DAP_GetProductString(char *str) +{ + (void)str; + return (0U); +} + +/** + * @brief Get Serial Number string. + * + * @param str Pointer to buffer to store the string. + * @return String length. + */ +__STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) +{ + (void)str; + return (0U); +} + +///@} + +// Modify your pins here + +// ATTENTION: DO NOT USE RTC GPIO16 +#define PIN_SWDIO 2 +#define PIN_SWCLK 0 +#define PIN_TDO 4 +#define PIN_TDI 5 +#define PIN_nTRST 1 // optional +#define PIN_nRESET 16 +// LED_BUILTIN +#define PIN_LED_CONNECTED 13 +// LED_BUILTIN +#define PIN_LED_RUNNING 15 + +//************************************************************************************************** +/** +\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access +\ingroup DAP_ConfigIO_gr +@{ + +Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode +and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug +interface of a device. The following I/O Pins are provided: + +JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode +---------------------------- | -------------------- | --------------------------------------------- +TCK: Test Clock | SWCLK: Clock | Output Push/Pull +TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) +TDI: Test Data Input | | Output Push/Pull +TDO: Test Data Output | | Input +nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor +nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor + + +DAP Hardware I/O Pin Access Functions +------------------------------------- +The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to +these I/O Pins. + +For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. +This functions are provided to achieve faster I/O that is possible with some advanced GPIO +peripherals that can independently write/read a single I/O pin without affecting any other pins +of the same I/O port. The following SWDIO I/O Pin functions are provided: + - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. + - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. + - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. + - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. +*/ + +/** + * @brief Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. + * Configures the DAP Hardware I/O pins for JTAG mode: + * - TCK, TMS, TDI, nTRST, nRESET to ***output*** mode and set to high level. + * - TDO to ***input*** mode. + * + */ +__STATIC_INLINE void PORT_JTAG_SETUP(void) +{ + gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); + gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); + + gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); + gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); + + gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); + gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); + gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); + gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); +} + +/** + * @brief Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. + * Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: + * - SWCLK, SWDIO, nRESET to output mode and set to default high level. + * - TDI, nTRST to HighZ mode (pins are unused in SWD mode). + * + */ +__STATIC_INLINE void PORT_SWD_SETUP(void) +{ + gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); + gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); + + gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); + gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); + + gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); + gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); + gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); + gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); +} + +/** + * @brief Disable JTAG/SWD I/O Pins. + * Disables the DAP Hardware I/O pins which configures: + * - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. + * + */ +__STATIC_INLINE void PORT_OFF(void) +{ + // Will be called when the DAP disconnected + gpio_set_direction(PIN_SWCLK, GPIO_MODE_DEF_DISABLE); + gpio_set_direction(PIN_SWDIO, GPIO_MODE_DEF_DISABLE); + + gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_DISABLE); + gpio_set_direction(PIN_TDI, GPIO_MODE_DEF_DISABLE); + + gpio_set_direction(PIN_nTRST, GPIO_MODE_DEF_DISABLE); + gpio_set_direction(PIN_nRESET, GPIO_MODE_DEF_DISABLE); +} + +// SWCLK/TCK I/O pin ------------------------------------- + +/** + * @brief SWCLK/TCK I/O pin: Get Input. + * + * @return Current status of the SWCLK/TCK DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) +{ + // TODO : can we set to 0? + return ((GPIO.in >> PIN_SWCLK) & 0x1); +} + +/** + * @brief SWCLK/TCK I/O pin: Set Output to High. + * + * Set the SWCLK/TCK DAP hardware I/O pin to high level. + */ +__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET(void) +{ + GPIO.out_w1ts |= (0x1 << PIN_SWCLK); +} + +/** + * @brief SWCLK/TCK I/O pin: Set Output to Low. + * + * Set the SWCLK/TCK DAP hardware I/O pin to low level. + */ +__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) +{ + GPIO.out_w1tc |= (0x1 << PIN_SWCLK); +} + +// SWDIO/TMS Pin I/O -------------------------------------- + +/** + * @brief SWDIO/TMS I/O pin: Get Input. + * + * @return Current status of the SWDIO/TMS DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) +{ + return ((GPIO.in >> PIN_SWDIO) & 0x1); +} + +/** + * @brief SWDIO/TMS I/O pin: Set Output to High. + * + * Set the SWDIO/TMS DAP hardware I/O pin to high level. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void) +{ + GPIO.out_w1ts |= (0x1 << PIN_SWDIO); +} + +/** + * @brief SWDIO/TMS I/O pin: Set Output to Low. + * + * Set the SWDIO/TMS DAP hardware I/O pin to low level. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) +{ + GPIO.out_w1tc |= (0x1 << PIN_SWDIO); +} + +/** + * @brief SWDIO I/O pin: Get Input (used in SWD mode only). + * + * @return Current status of the SWDIO DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) +{ + return ((GPIO.in >> PIN_SWDIO) & 0x1); +} + +/** + * @brief SWDIO I/O pin: Set Output (used in SWD mode only). + * + * @param bit Output value for the SWDIO DAP hardware I/O pin. + * + */ +__STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) +{ + /** + * Important: Use only one bit (bit0) of param! + * Sometimes the func "SWD_TransferFunction" of SW_DP.c will + * issue "2" as param instead of "0". Zach Lee + */ + if ((bit & 1U) == 1) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_SWDIO); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_SWDIO); + } +} + +/** + * @brief SWDIO I/O pin: Switch to Output mode (used in SWD mode only). + * Configure the SWDIO DAP hardware I/O pin to output mode. This function is + * called prior \ref PIN_SWDIO_OUT function calls. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) +{ + // Need fast response + + // set \ref gpio_set_direction -> OUTPUT + GPIO.enable_w1ts |= (0x1 << PIN_SWDIO); +} + +/** + * @brief SWDIO I/O pin: Switch to Input mode (used in SWD mode only). + * Configure the SWDIO DAP hardware I/O pin to input mode. This function is + * called prior \ref PIN_SWDIO_IN function calls. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) +{ + // Need fast response + // set \ref gpio_set_dircetion -> INPUT + // esp8266 input is always connected + GPIO.enable_w1tc |= (0x1 << PIN_SWDIO); +} + +// TDI Pin I/O --------------------------------------------- + +/** + * @brief TDI I/O pin: Get Input. + * + * @return Current status of the TDI DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) +{ + return ((GPIO.in >> PIN_TDI) & 0x1); +} + +/** + * @brief TDI I/O pin: Set Output. + * + * @param bit Output value for the TDI DAP hardware I/O pin. + * + */ +__STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) +{ + if ((bit & 1U) == 1) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_TDI); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_TDI); + } +} + +// TDO Pin I/O --------------------------------------------- + +/** + * @brief TDO I/O pin: Get Input. + * + * @return Current status of the TDO DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) +{ + return ((GPIO.in >> PIN_TDO_IN) & 0x1); +} + +// nTRST Pin I/O ------------------------------------------- + +/** + * @brief nTRST I/O pin: Get Input. + * + * @return Current status of the nTRST DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) +{ + return ((GPIO.in >> PIN_nTRST) & 0x1); +} + +/** + * @brief nTRST I/O pin: Set Output. + * + * @param bit JTAG TRST Test Reset pin status: + * - 0: issue a JTAG TRST Test Reset. + - 1: release JTAG TRST Test Reset. + */ +__STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) +{ + //TODO : What does this mean? ? ? + if ((bit & 1U) == 1) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_nTRST); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_nTRST); + } +} + +// nRESET Pin I/O------------------------------------------ + +/** + * @brief nRESET I/O pin: Get Input. + * + * @return Current status of the nRESET DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) +{ + return ((GPIO.in >> PIN_nRESET) & 0x1); +} + +/** + * @brief nRESET I/O pin: Set Output. + * + * @param bit target device hardware reset pin status: + * - 0: issue a device hardware reset. + * - 1: release device hardware reset. + */ +__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) +{ + //TODO : What does this mean? ? ? + if ((bit & 1U) == 1) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_nRESET); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_nRESET); + } +} + +///@} + +//************************************************************************************************** +/** +\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs +\ingroup DAP_ConfigIO_gr +@{ + +CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. + +It is recommended to provide the following LEDs for status indication: + - Connect LED: is active when the DAP hardware is connected to a debugger. + - Running LED: is active when the debugger has put the target device into running state. +*/ + +/** Debug Unit: Set status of Connected LED. +\param bit status of the Connect LED. + - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. + - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. +*/ + +/** + * @brief Debug Unit: Set status of Connected LED. + * + * @param bit status of the Connect LED. + * - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. + * - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. + */ +__STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit) +{ + if (bit) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_LED_CONNECTED); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_LED_CONNECTED); + } +} + +/** + * @brief Debug Unit: Set status Target Running LED. + * + * @param bit status of the Target Running LED. + * - 1: Target Running LED ON: program execution in target started. + * - 0: Target Running LED OFF: program execution in target stopped. + */ +__STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit) +{ + if (bit) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_LED_RUNNING); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_LED_RUNNING); + } +} + +///@} + +//************************************************************************************************** +/** +\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp +\ingroup DAP_ConfigIO_gr +@{ +Access function for Test Domain Timer. + +The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By +default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. + +*/ + +/** + * @brief Get timestamp of Test Domain Timer. + * + * @return Current timestamp value. + */ +__STATIC_INLINE uint32_t TIMESTAMP_GET(void) +{ + // FRC1 is a 24-bit countdown timer + return (0x1000000U - 1U - (frc1.count.data)); +} + +///@} + +//************************************************************************************************** +/** +\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization +\ingroup DAP_ConfigIO_gr +@{ + +CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. +*/ + +/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). +This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the +Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: + - I/O clock system enabled. + - all I/O pins: input buffer enabled, output pins are set to HighZ mode. + - for nTRST, nRESET a weak pull-up (if available) is enabled. + - LED output pins are enabled and LEDs are turned off. +*/ +__STATIC_INLINE void DAP_SETUP(void) +{ + // This function maybe unnecessary... + gpio_set_direction(PIN_SWCLK, GPIO_MODE_DEF_INPUT); + gpio_set_direction(PIN_SWDIO, GPIO_MODE_DEF_INPUT); // + gpio_set_direction(PIN_nRESET, GPIO_MODE_DEF_INPUT); // + gpio_set_direction(PIN_TDI, GPIO_MODE_DEF_INPUT); + gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); + + // Configure: LED as output (turned off) + gpio_set_direction(PIN_LED_CONNECTED, GPIO_MODE_DEF_OUTPUT); + LED_CONNECTED_OUT(0); + gpio_set_direction(PIN_LED_RUNNING, GPIO_MODE_DEF_OUTPUT); + LED_RUNNING_OUT(0); +} + +/** Reset Target Device with custom specific I/O pin or command sequence. +This function allows the optional implementation of a device specific reset sequence. +It is called when the command \ref DAP_ResetTarget and is for example required +when a device needs a time-critical unlock sequence that enables the debug port. +\return 0 = no device specific reset sequence is implemented.\n + 1 = a device specific reset sequence is implemented. +*/ +__STATIC_INLINE uint8_t RESET_TARGET(void) +{ + return (0U); // not available +} + +///@} + +#endif /* __DAP_CONFIG_H__ */ diff --git a/components/DAP/include/DAP.h b/components/DAP/include/DAP.h new file mode 100644 index 0000000..4194005 --- /dev/null +++ b/components/DAP/include/DAP.h @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2013-2019 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 26. November 2019 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Include + * Title: DAP.h Definitions + * + *---------------------------------------------------------------------------*/ + +#ifndef __DAP_H__ +#define __DAP_H__ + + +// DAP Firmware Version +#ifdef DAP_FW_V1 +#define DAP_FW_VER "1.2.0" +#else +#define DAP_FW_VER "2.0.0" +#endif + +// DAP Command IDs +#define ID_DAP_Info 0x00U +#define ID_DAP_HostStatus 0x01U +#define ID_DAP_Connect 0x02U +#define ID_DAP_Disconnect 0x03U +#define ID_DAP_TransferConfigure 0x04U +#define ID_DAP_Transfer 0x05U +#define ID_DAP_TransferBlock 0x06U +#define ID_DAP_TransferAbort 0x07U +#define ID_DAP_WriteABORT 0x08U +#define ID_DAP_Delay 0x09U +#define ID_DAP_ResetTarget 0x0AU +#define ID_DAP_SWJ_Pins 0x10U +#define ID_DAP_SWJ_Clock 0x11U +#define ID_DAP_SWJ_Sequence 0x12U +#define ID_DAP_SWD_Configure 0x13U +#define ID_DAP_SWD_Sequence 0x1DU +#define ID_DAP_JTAG_Sequence 0x14U +#define ID_DAP_JTAG_Configure 0x15U +#define ID_DAP_JTAG_IDCODE 0x16U +#define ID_DAP_SWO_Transport 0x17U +#define ID_DAP_SWO_Mode 0x18U +#define ID_DAP_SWO_Baudrate 0x19U +#define ID_DAP_SWO_Control 0x1AU +#define ID_DAP_SWO_Status 0x1BU +#define ID_DAP_SWO_ExtendedStatus 0x1EU +#define ID_DAP_SWO_Data 0x1CU + +#define ID_DAP_QueueCommands 0x7EU +#define ID_DAP_ExecuteCommands 0x7FU + +// DAP Vendor Command IDs +#define ID_DAP_Vendor0 0x80U +#define ID_DAP_Vendor1 0x81U +#define ID_DAP_Vendor2 0x82U +#define ID_DAP_Vendor3 0x83U +#define ID_DAP_Vendor4 0x84U +#define ID_DAP_Vendor5 0x85U +#define ID_DAP_Vendor6 0x86U +#define ID_DAP_Vendor7 0x87U +#define ID_DAP_Vendor8 0x88U +#define ID_DAP_Vendor9 0x89U +#define ID_DAP_Vendor10 0x8AU +#define ID_DAP_Vendor11 0x8BU +#define ID_DAP_Vendor12 0x8CU +#define ID_DAP_Vendor13 0x8DU +#define ID_DAP_Vendor14 0x8EU +#define ID_DAP_Vendor15 0x8FU +#define ID_DAP_Vendor16 0x90U +#define ID_DAP_Vendor17 0x91U +#define ID_DAP_Vendor18 0x92U +#define ID_DAP_Vendor19 0x93U +#define ID_DAP_Vendor20 0x94U +#define ID_DAP_Vendor21 0x95U +#define ID_DAP_Vendor22 0x96U +#define ID_DAP_Vendor23 0x97U +#define ID_DAP_Vendor24 0x98U +#define ID_DAP_Vendor25 0x99U +#define ID_DAP_Vendor26 0x9AU +#define ID_DAP_Vendor27 0x9BU +#define ID_DAP_Vendor28 0x9CU +#define ID_DAP_Vendor29 0x9DU +#define ID_DAP_Vendor30 0x9EU +#define ID_DAP_Vendor31 0x9FU + +#define ID_DAP_Invalid 0xFFU + +// DAP Status Code +#define DAP_OK 0U +#define DAP_ERROR 0xFFU + +// DAP ID +#define DAP_ID_VENDOR 1U +#define DAP_ID_PRODUCT 2U +#define DAP_ID_SER_NUM 3U +#define DAP_ID_FW_VER 4U +#define DAP_ID_DEVICE_VENDOR 5U +#define DAP_ID_DEVICE_NAME 6U +#define DAP_ID_CAPABILITIES 0xF0U +#define DAP_ID_TIMESTAMP_CLOCK 0xF1U +#define DAP_ID_SWO_BUFFER_SIZE 0xFDU +#define DAP_ID_PACKET_COUNT 0xFEU +#define DAP_ID_PACKET_SIZE 0xFFU + +// DAP Host Status +#define DAP_DEBUGGER_CONNECTED 0U +#define DAP_TARGET_RUNNING 1U + +// DAP Port +#define DAP_PORT_AUTODETECT 0U // Autodetect Port +#define DAP_PORT_DISABLED 0U // Port Disabled (I/O pins in High-Z) +#define DAP_PORT_SWD 1U // SWD Port (SWCLK, SWDIO) + nRESET +#define DAP_PORT_JTAG 2U // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET + +// DAP SWJ Pins +#define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK +#define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS +#define DAP_SWJ_TDI 2 // TDI +#define DAP_SWJ_TDO 3 // TDO +#define DAP_SWJ_nTRST 5 // nTRST +#define DAP_SWJ_nRESET 7 // nRESET + +// DAP Transfer Request +#define DAP_TRANSFER_APnDP (1U<<0) +#define DAP_TRANSFER_RnW (1U<<1) +#define DAP_TRANSFER_A2 (1U<<2) +#define DAP_TRANSFER_A3 (1U<<3) +#define DAP_TRANSFER_MATCH_VALUE (1U<<4) +#define DAP_TRANSFER_MATCH_MASK (1U<<5) +#define DAP_TRANSFER_TIMESTAMP (1U<<7) + +// DAP Transfer Response +#define DAP_TRANSFER_OK (1U<<0) +#define DAP_TRANSFER_WAIT (1U<<1) +#define DAP_TRANSFER_FAULT (1U<<2) +#define DAP_TRANSFER_ERROR (1U<<3) +#define DAP_TRANSFER_MISMATCH (1U<<4) + +// DAP SWO Trace Mode +#define DAP_SWO_OFF 0U +#define DAP_SWO_UART 1U +#define DAP_SWO_MANCHESTER 2U + +// DAP SWO Trace Status +#define DAP_SWO_CAPTURE_ACTIVE (1U<<0) +#define DAP_SWO_CAPTURE_PAUSED (1U<<1) +#define DAP_SWO_STREAM_ERROR (1U<<6) +#define DAP_SWO_BUFFER_OVERRUN (1U<<7) + + +// Debug Port Register Addresses +#define DP_IDCODE 0x00U // IDCODE Register (SW Read only) +#define DP_ABORT 0x00U // Abort Register (SW Write only) +#define DP_CTRL_STAT 0x04U // Control & Status +#define DP_WCR 0x04U // Wire Control Register (SW Only) +#define DP_SELECT 0x08U // Select Register (JTAG R/W & SW W) +#define DP_RESEND 0x08U // Resend (SW Read Only) +#define DP_RDBUFF 0x0CU // Read Buffer (Read Only) + +// JTAG IR Codes +#define JTAG_ABORT 0x08U +#define JTAG_DPACC 0x0AU +#define JTAG_APACC 0x0BU +#define JTAG_IDCODE 0x0EU +#define JTAG_BYPASS 0x0FU + +// JTAG Sequence Info +#define JTAG_SEQUENCE_TCK 0x3FU // TCK count +#define JTAG_SEQUENCE_TMS 0x40U // TMS value +#define JTAG_SEQUENCE_TDO 0x80U // TDO capture + +// SWD Sequence Info +#define SWD_SEQUENCE_CLK 0x3FU // SWCLK count +#define SWD_SEQUENCE_DIN 0x80U // SWDIO capture + + +#include +#include +#include "cmsis_compiler.h" + +// DAP Data structure +typedef struct { + uint8_t debug_port; // Debug Port + uint8_t fast_clock; // Fast Clock Flag + uint8_t padding[2]; + uint32_t clock_delay; // Clock Delay + uint32_t timestamp; // Last captured Timestamp + struct { // Transfer Configuration + uint8_t idle_cycles; // Idle cycles after transfer + uint8_t padding[3]; + uint16_t retry_count; // Number of retries after WAIT response + uint16_t match_retry; // Number of retries if read value does not match + uint32_t match_mask; // Match Mask + } transfer; +#if (DAP_SWD != 0) + struct { // SWD Configuration + uint8_t turnaround; // Turnaround period + uint8_t data_phase; // Always generate Data Phase + } swd_conf; +#endif +#if (DAP_JTAG != 0) + struct { // JTAG Device Chain + uint8_t count; // Number of devices + uint8_t index; // Device index (device at TDO has index 0) +#if (DAP_JTAG_DEV_CNT != 0) + uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits + uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR + uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR +#endif + } jtag_dev; +#endif +} DAP_Data_t; + +extern DAP_Data_t DAP_Data; // DAP Data +extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag + + +#ifdef __cplusplus +extern "C" +{ +#endif + +// Functions +extern void SWJ_Sequence (uint32_t count, const uint8_t *data); +extern void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi); +extern void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo); +extern void JTAG_IR (uint32_t ir); +extern uint32_t JTAG_ReadIDCode (void); +extern void JTAG_WriteAbort (uint32_t data); +extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data); +extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); + +extern void Delayms (uint32_t delay); + +extern uint32_t SWO_Transport (const uint8_t *request, uint8_t *response); +extern uint32_t SWO_Mode (const uint8_t *request, uint8_t *response); +extern uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response); +extern uint32_t SWO_Control (const uint8_t *request, uint8_t *response); +extern uint32_t SWO_Status (uint8_t *response); +extern uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response); +extern uint32_t SWO_Data (const uint8_t *request, uint8_t *response); + +extern void SWO_QueueTransfer (uint8_t *buf, uint32_t num); +extern void SWO_AbortTransfer (void); +extern void SWO_TransferComplete (void); + +extern uint32_t UART_SWO_Mode (uint32_t enable); +extern uint32_t UART_SWO_Baudrate (uint32_t baudrate); +extern uint32_t UART_SWO_Control (uint32_t active); +extern void UART_SWO_Capture (uint8_t *buf, uint32_t num); +extern uint32_t UART_SWO_GetCount (void); + +extern uint32_t Manchester_SWO_Mode (uint32_t enable); +extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate); +extern uint32_t Manchester_SWO_Control (uint32_t active); +extern void Manchester_SWO_Capture (uint8_t *buf, uint32_t num); +extern uint32_t Manchester_SWO_GetCount (void); + +extern uint32_t DAP_ProcessVendorCommand (const uint8_t *request, uint8_t *response); +extern uint32_t DAP_ProcessCommand (const uint8_t *request, uint8_t *response); +extern uint32_t DAP_ExecuteCommand (const uint8_t *request, uint8_t *response); + +extern void DAP_Setup (void); + +// Configurable delay for clock generation +#ifndef DELAY_SLOW_CYCLES +#define DELAY_SLOW_CYCLES 3U // Number of cycles for one iteration +#endif +#if defined(__CC_ARM) +__STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) { + uint32_t count = delay; + while (--count); +} +#else +__STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) { + __ASM volatile ( + ".syntax unified\n" + "0:\n\t" + "subs %0,%0,#1\n\t" + "bne 0b\n" + : "+l" (delay) : : "cc" + ); +} +#endif + +// Fixed delay for fast clock generation +#ifndef DELAY_FAST_CYCLES +#define DELAY_FAST_CYCLES 0U // Number of cycles: 0..3 +#endif +__STATIC_FORCEINLINE void PIN_DELAY_FAST (void) { +#if (DELAY_FAST_CYCLES >= 1U) + __NOP(); +#endif +#if (DELAY_FAST_CYCLES >= 2U) + __NOP(); +#endif +#if (DELAY_FAST_CYCLES >= 3U) + __NOP(); +#endif +} + +#ifdef __cplusplus +} +#endif + + +#endif /* __DAP_H__ */ diff --git a/components/DAP/source/DAP.c b/components/DAP/source/DAP.c new file mode 100644 index 0000000..9e1f620 --- /dev/null +++ b/components/DAP/source/DAP.c @@ -0,0 +1,1769 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Source + * Title: DAP.c CMSIS-DAP Commands + * + *---------------------------------------------------------------------------*/ + +#include +#include "DAP_config.h" +#include "DAP.h" + + +#if (DAP_PACKET_SIZE < 64U) +#error "Minimum Packet Size is 64!" +#endif +#if (DAP_PACKET_SIZE > 32768U) +#error "Maximum Packet Size is 32768!" +#endif +#if (DAP_PACKET_COUNT < 1U) +#error "Minimum Packet Count is 1!" +#endif +#if (DAP_PACKET_COUNT > 255U) +#error "Maximum Packet Count is 255!" +#endif + + +// Clock Macros + +#define MAX_SWJ_CLOCK(delay_cycles) \ + ((CPU_CLOCK/2U) / (IO_PORT_WRITE_CYCLES + delay_cycles)) + +#define CLOCK_DELAY(swj_clock) \ + (((CPU_CLOCK/2U) / swj_clock) - IO_PORT_WRITE_CYCLES) + + + DAP_Data_t DAP_Data; // DAP Data +volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag + + +static const char DAP_FW_Ver [] = DAP_FW_VER; + +#if TARGET_DEVICE_FIXED +static const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR; +static const char TargetDeviceName [] = TARGET_DEVICE_NAME; +#endif + + +// Get DAP Information +// id: info identifier +// info: pointer to info data +// return: number of bytes in info data +static uint8_t DAP_Info(uint8_t id, uint8_t *info) { + uint8_t length = 0U; + + switch (id) { + case DAP_ID_VENDOR: + length = DAP_GetVendorString((char *)info); + break; + case DAP_ID_PRODUCT: + length = DAP_GetProductString((char *)info); + break; + case DAP_ID_SER_NUM: + length = DAP_GetSerNumString((char *)info); + break; + case DAP_ID_FW_VER: + length = (uint8_t)sizeof(DAP_FW_Ver); + memcpy(info, DAP_FW_Ver, length); + break; + case DAP_ID_DEVICE_VENDOR: +#if TARGET_DEVICE_FIXED + length = (uint8_t)sizeof(TargetDeviceVendor); + memcpy(info, TargetDeviceVendor, length); +#endif + break; + case DAP_ID_DEVICE_NAME: +#if TARGET_DEVICE_FIXED + length = (uint8_t)sizeof(TargetDeviceName); + memcpy(info, TargetDeviceName, length); +#endif + break; + case DAP_ID_CAPABILITIES: + info[0] = ((DAP_SWD != 0) ? (1U << 0) : 0U) | + ((DAP_JTAG != 0) ? (1U << 1) : 0U) | + ((SWO_UART != 0) ? (1U << 2) : 0U) | + ((SWO_MANCHESTER != 0) ? (1U << 3) : 0U) | + /* Atomic Commands */ (1U << 4) | + ((TIMESTAMP_CLOCK != 0U) ? (1U << 5) : 0U) | + ((SWO_STREAM != 0U) ? (1U << 6) : 0U); + length = 1U; + break; + case DAP_ID_TIMESTAMP_CLOCK: +#if (TIMESTAMP_CLOCK != 0U) + info[0] = (uint8_t)(TIMESTAMP_CLOCK >> 0); + info[1] = (uint8_t)(TIMESTAMP_CLOCK >> 8); + info[2] = (uint8_t)(TIMESTAMP_CLOCK >> 16); + info[3] = (uint8_t)(TIMESTAMP_CLOCK >> 24); + length = 4U; +#endif + break; + case DAP_ID_SWO_BUFFER_SIZE: +#if ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) + info[0] = (uint8_t)(SWO_BUFFER_SIZE >> 0); + info[1] = (uint8_t)(SWO_BUFFER_SIZE >> 8); + info[2] = (uint8_t)(SWO_BUFFER_SIZE >> 16); + info[3] = (uint8_t)(SWO_BUFFER_SIZE >> 24); + length = 4U; +#endif + break; + case DAP_ID_PACKET_SIZE: + info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0); + info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8); + length = 2U; + break; + case DAP_ID_PACKET_COUNT: + info[0] = DAP_PACKET_COUNT; + length = 1U; + break; + default: + break; + } + + return (length); +} + + +// Delay for specified time +// delay: delay time in ms +void Delayms(uint32_t delay) { + delay *= ((CPU_CLOCK/1000U) + (DELAY_SLOW_CYCLES-1U)) / DELAY_SLOW_CYCLES; + PIN_DELAY_SLOW(delay); +} + + +// Process Delay command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_Delay(const uint8_t *request, uint8_t *response) { + uint32_t delay; + + delay = (uint32_t)(*(request+0)) | + (uint32_t)(*(request+1) << 8); + delay *= ((CPU_CLOCK/1000000U) + (DELAY_SLOW_CYCLES-1U)) / DELAY_SLOW_CYCLES; + + PIN_DELAY_SLOW(delay); + + *response = DAP_OK; + return ((2U << 16) | 1U); +} + + +// Process Host Status command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_HostStatus(const uint8_t *request, uint8_t *response) { + + switch (*request) { + case DAP_DEBUGGER_CONNECTED: + LED_CONNECTED_OUT((*(request+1) & 1U)); + break; + case DAP_TARGET_RUNNING: + LED_RUNNING_OUT((*(request+1) & 1U)); + break; + default: + *response = DAP_ERROR; + return ((2U << 16) | 1U); + } + + *response = DAP_OK; + return ((2U << 16) | 1U); +} + + +// Process Connect command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_Connect(const uint8_t *request, uint8_t *response) { + uint32_t port; + + if (*request == DAP_PORT_AUTODETECT) { + port = DAP_DEFAULT_PORT; + } else { + port = *request; + } + + switch (port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + DAP_Data.debug_port = DAP_PORT_SWD; + PORT_SWD_SETUP(); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + DAP_Data.debug_port = DAP_PORT_JTAG; + PORT_JTAG_SETUP(); + break; +#endif + default: + port = DAP_PORT_DISABLED; + break; + } + + *response = (uint8_t)port; + return ((1U << 16) | 1U); +} + + +// Process Disconnect command and prepare response +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_Disconnect(uint8_t *response) { + + DAP_Data.debug_port = DAP_PORT_DISABLED; + PORT_OFF(); + + *response = DAP_OK; + return (1U); +} + + +// Process Reset Target command and prepare response +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_ResetTarget(uint8_t *response) { + + *(response+1) = RESET_TARGET(); + *(response+0) = DAP_OK; + return (2U); +} + + +// Process SWJ Pins command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) { +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) + uint32_t value; + uint32_t select; + uint32_t wait; + uint32_t timestamp; + + value = (uint32_t) *(request+0); + select = (uint32_t) *(request+1); + wait = (uint32_t)(*(request+2) << 0) | + (uint32_t)(*(request+3) << 8) | + (uint32_t)(*(request+4) << 16) | + (uint32_t)(*(request+5) << 24); + + if ((select & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) { + if ((value & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) { + PIN_SWCLK_TCK_SET(); + } else { + PIN_SWCLK_TCK_CLR(); + } + } + if ((select & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) { + if ((value & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) { + PIN_SWDIO_TMS_SET(); + } else { + PIN_SWDIO_TMS_CLR(); + } + } + if ((select & (1U << DAP_SWJ_TDI)) != 0U) { + PIN_TDI_OUT(value >> DAP_SWJ_TDI); + } + if ((select & (1U << DAP_SWJ_nTRST)) != 0U) { + PIN_nTRST_OUT(value >> DAP_SWJ_nTRST); + } + if ((select & (1U << DAP_SWJ_nRESET)) != 0U){ + PIN_nRESET_OUT(value >> DAP_SWJ_nRESET); + } + + if (wait != 0U) { +#if (TIMESTAMP_CLOCK != 0U) + if (wait > 3000000U) { + wait = 3000000U; + } +#if (TIMESTAMP_CLOCK >= 1000000U) + wait *= TIMESTAMP_CLOCK / 1000000U; +#else + wait /= 1000000U / TIMESTAMP_CLOCK; +#endif +#else + wait = 1U; +#endif + timestamp = TIMESTAMP_GET(); + do { + if ((select & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) { + if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) { + continue; + } + } + if ((select & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) { + if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) { + continue; + } + } + if ((select & (1U << DAP_SWJ_TDI)) != 0U) { + if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) { + continue; + } + } + if ((select & (1U << DAP_SWJ_nTRST)) != 0U) { + if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) { + continue; + } + } + if ((select & (1U << DAP_SWJ_nRESET)) != 0U) { + if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) { + continue; + } + } + break; + } while ((TIMESTAMP_GET() - timestamp) < wait); + } + + value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) | + (PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) | + (PIN_TDI_IN() << DAP_SWJ_TDI) | + (PIN_TDO_IN() << DAP_SWJ_TDO) | + (PIN_nTRST_IN() << DAP_SWJ_nTRST) | + (PIN_nRESET_IN() << DAP_SWJ_nRESET); + + *response = (uint8_t)value; +#else + *response = 0U; +#endif + + return ((6U << 16) | 1U); +} + + +// Process SWJ Clock command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_SWJ_Clock(const uint8_t *request, uint8_t *response) { +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) + uint32_t clock; + uint32_t delay; + + clock = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + + if (clock == 0U) { + *response = DAP_ERROR; + return ((4U << 16) | 1U); + } + + if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { + DAP_Data.fast_clock = 1U; + DAP_Data.clock_delay = 1U; + } else { + DAP_Data.fast_clock = 0U; + + delay = ((CPU_CLOCK/2U) + (clock - 1U)) / clock; + if (delay > IO_PORT_WRITE_CYCLES) { + delay -= IO_PORT_WRITE_CYCLES; + delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES; + } else { + delay = 1U; + } + + DAP_Data.clock_delay = delay; + } + + *response = DAP_OK; +#else + *response = DAP_ERROR; +#endif + + return ((4U << 16) | 1U); +} + + +// Process SWJ Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_SWJ_Sequence(const uint8_t *request, uint8_t *response) { + uint32_t count; + + count = *request++; + if (count == 0U) { + count = 256U; + } + +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) + SWJ_Sequence(count, request); + *response = DAP_OK; +#else + *response = DAP_ERROR; +#endif + + count = (count + 7U) >> 3; + + return (((count + 1U) << 16) | 1U); +} + + +// Process SWD Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_SWD_Configure(const uint8_t *request, uint8_t *response) { +#if (DAP_SWD != 0) + uint8_t value; + + value = *request; + DAP_Data.swd_conf.turnaround = (value & 0x03U) + 1U; + DAP_Data.swd_conf.data_phase = (value & 0x04U) ? 1U : 0U; + + *response = DAP_OK; +#else + *response = DAP_ERROR; +#endif + + return ((1U << 16) | 1U); +} + + +// Process SWD Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_SWD_Sequence(const uint8_t *request, uint8_t *response) { + uint32_t sequence_info; + uint32_t sequence_count; + uint32_t request_count; + uint32_t response_count; + uint32_t count; + +#if (DAP_SWD != 0) + *response++ = DAP_OK; +#else + *response++ = DAP_ERROR; +#endif + request_count = 1U; + response_count = 1U; + + sequence_count = *request++; + while (sequence_count--) { + sequence_info = *request++; + count = sequence_info & SWD_SEQUENCE_CLK; + if (count == 0U) { + count = 64U; + } + count = (count + 7U) / 8U; +#if (DAP_SWD != 0) + if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) { + PIN_SWDIO_OUT_DISABLE(); + } else { + PIN_SWDIO_OUT_ENABLE(); + } + SWD_Sequence(sequence_info, request, response); + if (sequence_count == 0U) { + PIN_SWDIO_OUT_ENABLE(); + } +#endif + if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) { + request_count++; +#if (DAP_SWD != 0) + response += count; + response_count += count; +#endif + } else { + request += count; + request_count += count + 1U; + } + } + + return ((request_count << 16) | response_count); +} + + +// Process JTAG Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_JTAG_Sequence(const uint8_t *request, uint8_t *response) { + uint32_t sequence_info; + uint32_t sequence_count; + uint32_t request_count; + uint32_t response_count; + uint32_t count; + +#if (DAP_JTAG != 0) + *response++ = DAP_OK; +#else + *response++ = DAP_ERROR; +#endif + request_count = 1U; + response_count = 1U; + + sequence_count = *request++; + while (sequence_count--) { + sequence_info = *request++; + count = sequence_info & JTAG_SEQUENCE_TCK; + if (count == 0U) { + count = 64U; + } + count = (count + 7U) / 8U; +#if (DAP_JTAG != 0) + JTAG_Sequence(sequence_info, request, response); +#endif + request += count; + request_count += count + 1U; +#if (DAP_JTAG != 0) + if ((sequence_info & JTAG_SEQUENCE_TDO) != 0U) { + response += count; + response_count += count; + } +#endif + } + + return ((request_count << 16) | response_count); +} + + +// Process JTAG Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_JTAG_Configure(const uint8_t *request, uint8_t *response) { + uint32_t count; +#if (DAP_JTAG != 0) + uint32_t length; + uint32_t bits; + uint32_t n; + + count = *request++; + DAP_Data.jtag_dev.count = (uint8_t)count; + + bits = 0U; + for (n = 0U; n < count; n++) { + length = *request++; + DAP_Data.jtag_dev.ir_length[n] = (uint8_t)length; + DAP_Data.jtag_dev.ir_before[n] = (uint16_t)bits; + bits += length; + } + for (n = 0U; n < count; n++) { + bits -= DAP_Data.jtag_dev.ir_length[n]; + DAP_Data.jtag_dev.ir_after[n] = (uint16_t)bits; + } + + *response = DAP_OK; +#else + count = *request; + *response = DAP_ERROR; +#endif + + return (((count + 1U) << 16) | 1U); +} + + +// Process JTAG IDCODE command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_JTAG_IDCode(const uint8_t *request, uint8_t *response) { +#if (DAP_JTAG != 0) + uint32_t data; + + if (DAP_Data.debug_port != DAP_PORT_JTAG) { + goto id_error; + } + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { + goto id_error; + } + + // Select JTAG chain + JTAG_IR(JTAG_IDCODE); + + // Read IDCODE register + data = JTAG_ReadIDCode(); + + // Store Data + *(response+0) = DAP_OK; + *(response+1) = (uint8_t)(data >> 0); + *(response+2) = (uint8_t)(data >> 8); + *(response+3) = (uint8_t)(data >> 16); + *(response+4) = (uint8_t)(data >> 24); + + return ((1U << 16) | 5U); + +id_error: +#endif + *response = DAP_ERROR; + return ((1U << 16) | 1U); +} + + +// Process Transfer Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_TransferConfigure(const uint8_t *request, uint8_t *response) { + + DAP_Data.transfer.idle_cycles = *(request+0); + DAP_Data.transfer.retry_count = (uint16_t) *(request+1) | + (uint16_t)(*(request+2) << 8); + DAP_Data.transfer.match_retry = (uint16_t) *(request+3) | + (uint16_t)(*(request+4) << 8); + + *response = DAP_OK; + return ((5U << 16) | 1U); +} + + +// Process SWD Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_Transfer(const uint8_t *request, uint8_t *response) { + const + uint8_t *request_head; + uint32_t request_count; + uint32_t request_value; + uint8_t *response_head; + uint32_t response_count; + uint32_t response_value; + uint32_t post_read; + uint32_t check_write; + uint32_t match_value; + uint32_t match_retry; + uint32_t retry; + uint32_t data; +#if (TIMESTAMP_CLOCK != 0U) + uint32_t timestamp; +#endif + + request_head = request; + + response_count = 0U; + response_value = 0U; + response_head = response; + response += 2; + + DAP_TransferAbort = 0U; + + post_read = 0U; + check_write = 0U; + + request++; // Ignore DAP index + + request_count = *request++; + + for (; request_count != 0U; request_count--) { + request_value = *request++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) { + // Read register + if (post_read) { + // Read was posted before + retry = DAP_Data.transfer.retry_count; + if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) { + // Read previous AP data and post next AP read + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } else { + // Read previous AP data + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + post_read = 0U; + } + if (response_value != DAP_TRANSFER_OK) { + break; + } + // Store previous AP data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); +#if (TIMESTAMP_CLOCK != 0U) + if (post_read) { + // Store Timestamp of next AP read + if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { + timestamp = DAP_Data.timestamp; + *response++ = (uint8_t) timestamp; + *response++ = (uint8_t)(timestamp >> 8); + *response++ = (uint8_t)(timestamp >> 16); + *response++ = (uint8_t)(timestamp >> 24); + } + } +#endif + } + if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { + // Read with value match + match_value = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + request += 4; + match_retry = DAP_Data.transfer.match_retry; + if ((request_value & DAP_TRANSFER_APnDP) != 0U) { + // Post AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } + } + do { + // Read register until its value matches or retry counter expires + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } + } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); + if ((data & DAP_Data.transfer.match_mask) != match_value) { + response_value |= DAP_TRANSFER_MISMATCH; + } + if (response_value != DAP_TRANSFER_OK) { + break; + } + } else { + // Normal read + retry = DAP_Data.transfer.retry_count; + if ((request_value & DAP_TRANSFER_APnDP) != 0U) { + // Read AP register + if (post_read == 0U) { + // Post AP read + do { + response_value = SWD_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } +#if (TIMESTAMP_CLOCK != 0U) + // Store Timestamp + if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { + timestamp = DAP_Data.timestamp; + *response++ = (uint8_t) timestamp; + *response++ = (uint8_t)(timestamp >> 8); + *response++ = (uint8_t)(timestamp >> 16); + *response++ = (uint8_t)(timestamp >> 24); + } +#endif + post_read = 1U; + } + } else { + // Read DP register + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } +#if (TIMESTAMP_CLOCK != 0U) + // Store Timestamp + if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { + timestamp = DAP_Data.timestamp; + *response++ = (uint8_t) timestamp; + *response++ = (uint8_t)(timestamp >> 8); + *response++ = (uint8_t)(timestamp >> 16); + *response++ = (uint8_t)(timestamp >> 24); + } +#endif + // Store data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } + } + check_write = 0U; + } else { + // Write register + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + post_read = 0U; + } + // Load data + data = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + request += 4; + if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) { + // Write match mask + DAP_Data.transfer.match_mask = data; + response_value = DAP_TRANSFER_OK; + } else { + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } +#if (TIMESTAMP_CLOCK != 0U) + // Store Timestamp + if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { + timestamp = DAP_Data.timestamp; + *response++ = (uint8_t) timestamp; + *response++ = (uint8_t)(timestamp >> 8); + *response++ = (uint8_t)(timestamp >> 16); + *response++ = (uint8_t)(timestamp >> 24); + } +#endif + check_write = 1U; + } + } + response_count++; + if (DAP_TransferAbort) { + break; + } + } + + for (; request_count != 0U; request_count--) { + // Process canceled requests + request_value = *request++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) { + // Read register + if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { + // Read with value match + request += 4; + } + } else { + // Write register + request += 4; + } + } + + if (response_value == DAP_TRANSFER_OK) { + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } else if (check_write) { + // Check last write + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + } + +end: + *(response_head+0) = (uint8_t)response_count; + *(response_head+1) = (uint8_t)response_value; + + return (((uint32_t)(request - request_head) << 16) | (uint32_t)(response - response_head)); +} +#endif + + +// Process JTAG Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Transfer(const uint8_t *request, uint8_t *response) { + const + uint8_t *request_head; + uint32_t request_count; + uint32_t request_value; + uint32_t request_ir; + uint8_t *response_head; + uint32_t response_count; + uint32_t response_value; + uint32_t post_read; + uint32_t match_value; + uint32_t match_retry; + uint32_t retry; + uint32_t data; + uint32_t ir; +#if (TIMESTAMP_CLOCK != 0U) + uint32_t timestamp; +#endif + + request_head = request; + + response_count = 0U; + response_value = 0U; + response_head = response; + response += 2; + + DAP_TransferAbort = 0U; + + ir = 0U; + post_read = 0U; + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request++; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { + goto end; + } + + request_count = *request++; + + for (; request_count != 0U; request_count--) { + request_value = *request++; + request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; + if ((request_value & DAP_TRANSFER_RnW) != 0U) { + // Read register + if (post_read) { + // Read was posted before + retry = DAP_Data.transfer.retry_count; + if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == 0U)) { + // Read previous data and post next read + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } else { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + // Read previous data + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + post_read = 0U; + } + if (response_value != DAP_TRANSFER_OK) { + break; + } + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); +#if (TIMESTAMP_CLOCK != 0U) + if (post_read) { + // Store Timestamp of next AP read + if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { + timestamp = DAP_Data.timestamp; + *response++ = (uint8_t) timestamp; + *response++ = (uint8_t)(timestamp >> 8); + *response++ = (uint8_t)(timestamp >> 16); + *response++ = (uint8_t)(timestamp >> 24); + } + } +#endif + } + if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { + // Read with value match + match_value = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + request += 4; + match_retry = DAP_Data.transfer.match_retry; + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Post DP/AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } + do { + // Read register until its value matches or retry counter expires + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } + } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); + if ((data & DAP_Data.transfer.match_mask) != match_value) { + response_value |= DAP_TRANSFER_MISMATCH; + } + if (response_value != DAP_TRANSFER_OK) { + break; + } + } else { + // Normal read + if (post_read == 0U) { + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Post DP/AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } +#if (TIMESTAMP_CLOCK != 0U) + // Store Timestamp + if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { + timestamp = DAP_Data.timestamp; + *response++ = (uint8_t) timestamp; + *response++ = (uint8_t)(timestamp >> 8); + *response++ = (uint8_t)(timestamp >> 16); + *response++ = (uint8_t)(timestamp >> 24); + } +#endif + post_read = 1U; + } + } + } else { + // Write register + if (post_read) { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + post_read = 0U; + } + // Load data + data = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + request += 4; + if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) { + // Write match mask + DAP_Data.transfer.match_mask = data; + response_value = DAP_TRANSFER_OK; + } else { + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + break; + } +#if (TIMESTAMP_CLOCK != 0U) + // Store Timestamp + if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { + timestamp = DAP_Data.timestamp; + *response++ = (uint8_t) timestamp; + *response++ = (uint8_t)(timestamp >> 8); + *response++ = (uint8_t)(timestamp >> 16); + *response++ = (uint8_t)(timestamp >> 24); + } +#endif + } + } + response_count++; + if (DAP_TransferAbort) { + break; + } + } + + for (; request_count != 0U; request_count--) { + // Process canceled requests + request_value = *request++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) { + // Read register + if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { + // Read with value match + request += 4; + } + } else { + // Write register + request += 4; + } + } + + if (response_value == DAP_TRANSFER_OK) { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } else { + // Check last write + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + } + +end: + *(response_head+0) = (uint8_t)response_count; + *(response_head+1) = (uint8_t)response_value; + + return (((uint32_t)(request - request_head) << 16) | (uint32_t)(response - response_head)); +} +#endif + + +// Process Dummy Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_Dummy_Transfer(const uint8_t *request, uint8_t *response) { + const + uint8_t *request_head; + uint32_t request_count; + uint32_t request_value; + + request_head = request; + + request++; // Ignore DAP index + + request_count = *request++; + + for (; request_count != 0U; request_count--) { + // Process dummy requests + request_value = *request++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) { + // Read register + if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { + // Read with value match + request += 4; + } + } else { + // Write register + request += 4; + } + } + + *(response+0) = 0U; // Response count + *(response+1) = 0U; // Response value + + return (((uint32_t)(request - request_head) << 16) | 2U); +} + + +// Process Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_Transfer(const uint8_t *request, uint8_t *response) { + uint32_t num; + + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_Transfer(request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_Transfer(request, response); + break; +#endif + default: + num = DAP_Dummy_Transfer(request, response); + break; + } + + return (num); +} + + +// Process SWD Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_TransferBlock(const uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t retry; + uint32_t data; + + response_count = 0U; + response_value = 0U; + response_head = response; + response += 3; + + DAP_TransferAbort = 0U; + + request++; // Ignore DAP index + + request_count = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8); + request += 2; + if (request_count == 0U) { + goto end; + } + + request_value = *request++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) { + // Read register block + if ((request_value & DAP_TRANSFER_APnDP) != 0U) { + // Post AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + } + while (request_count--) { + // Read DP/AP register + if ((request_count == 0U) && ((request_value & DAP_TRANSFER_APnDP) != 0U)) { + // Last AP read + request_value = DP_RDBUFF | DAP_TRANSFER_RnW; + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + // Store data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + response_count++; + } + } else { + // Write register block + while (request_count--) { + // Load data + data = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + request += 4; + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + response_count++; + } + // Check last write + retry = DAP_Data.transfer.retry_count; + do { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + +end: + *(response_head+0) = (uint8_t)(response_count >> 0); + *(response_head+1) = (uint8_t)(response_count >> 8); + *(response_head+2) = (uint8_t) response_value; + + return ((uint32_t)(response - response_head)); +} +#endif + + +// Process JTAG Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_TransferBlock(const uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t retry; + uint32_t data; + uint32_t ir; + + response_count = 0U; + response_value = 0U; + response_head = response; + response += 3; + + DAP_TransferAbort = 0U; + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request++; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { + goto end; + } + + request_count = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8); + request += 2; + if (request_count == 0U) { + goto end; + } + + request_value = *request++; + + // Select JTAG chain + ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; + JTAG_IR(ir); + + if ((request_value & DAP_TRANSFER_RnW) != 0U) { + // Post read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + // Read register block + while (request_count--) { + // Read DP/AP register + if (request_count == 0U) { + // Last read + if (ir != JTAG_DPACC) { + JTAG_IR(JTAG_DPACC); + } + request_value = DP_RDBUFF | DAP_TRANSFER_RnW; + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + // Store data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + response_count++; + } + } else { + // Write register block + while (request_count--) { + // Load data + data = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + request += 4; + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) { + goto end; + } + response_count++; + } + // Check last write + if (ir != JTAG_DPACC) { + JTAG_IR(JTAG_DPACC); + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + +end: + *(response_head+0) = (uint8_t)(response_count >> 0); + *(response_head+1) = (uint8_t)(response_count >> 8); + *(response_head+2) = (uint8_t) response_value; + + return ((uint32_t)(response - response_head)); +} +#endif + + +// Process Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_TransferBlock(const uint8_t *request, uint8_t *response) { + uint32_t num; + + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_TransferBlock (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_TransferBlock(request, response); + break; +#endif + default: + *(response+0) = 0U; // Response count [7:0] + *(response+1) = 0U; // Response count[15:8] + *(response+2) = 0U; // Response value + num = 3U; + break; + } + + if ((*(request+3) & DAP_TRANSFER_RnW) != 0U) { + // Read register block + num |= 4U << 16; + } else { + // Write register block + num |= (4U + (((uint32_t)(*(request+1)) | (uint32_t)(*(request+2) << 8)) * 4)) << 16; + } + + return (num); +} + + +// Process SWD Write ABORT command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_WriteAbort(const uint8_t *request, uint8_t *response) { + uint32_t data; + + // Load data (Ignore DAP index) + data = (uint32_t)(*(request+1) << 0) | + (uint32_t)(*(request+2) << 8) | + (uint32_t)(*(request+3) << 16) | + (uint32_t)(*(request+4) << 24); + + // Write Abort register + SWD_Transfer(DP_ABORT, &data); + + *response = DAP_OK; + return (1U); +} +#endif + + +// Process JTAG Write ABORT command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) { + uint32_t data; + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { + *response = DAP_ERROR; + return (1U); + } + + // Select JTAG chain + JTAG_IR(JTAG_ABORT); + + // Load data + data = (uint32_t)(*(request+1) << 0) | + (uint32_t)(*(request+2) << 8) | + (uint32_t)(*(request+3) << 16) | + (uint32_t)(*(request+4) << 24); + + // Write Abort register + JTAG_WriteAbort(data); + + *response = DAP_OK; + return (1U); +} +#endif + + +// Process Write ABORT command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint32_t DAP_WriteAbort(const uint8_t *request, uint8_t *response) { + uint32_t num; + + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_WriteAbort (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_WriteAbort(request, response); + break; +#endif + default: + *response = DAP_ERROR; + num = 1U; + break; + } + return ((5U << 16) | num); +} + + +// Process DAP Vendor command request and prepare response +// Default function (can be overridden) +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +__WEAK uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) { + (void)request; + *response = ID_DAP_Invalid; + return ((1U << 16) | 1U); +} + + +// Process DAP command request and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t DAP_ProcessCommand(const uint8_t *request, uint8_t *response) { + uint32_t num; + + if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) { + return DAP_ProcessVendorCommand(request, response); + } + + *response++ = *request; + + switch (*request++) { + case ID_DAP_Info: + num = DAP_Info(*request, response+1); + *response = (uint8_t)num; + return ((2U << 16) + 2U + num); + + case ID_DAP_HostStatus: + num = DAP_HostStatus(request, response); + break; + + case ID_DAP_Connect: + num = DAP_Connect(request, response); + break; + case ID_DAP_Disconnect: + num = DAP_Disconnect(response); + break; + + case ID_DAP_Delay: + num = DAP_Delay(request, response); + break; + + case ID_DAP_ResetTarget: + num = DAP_ResetTarget(response); + break; + + case ID_DAP_SWJ_Pins: + num = DAP_SWJ_Pins(request, response); + break; + case ID_DAP_SWJ_Clock: + num = DAP_SWJ_Clock(request, response); + break; + case ID_DAP_SWJ_Sequence: + num = DAP_SWJ_Sequence(request, response); + break; + + case ID_DAP_SWD_Configure: + num = DAP_SWD_Configure(request, response); + break; + case ID_DAP_SWD_Sequence: + num = DAP_SWD_Sequence(request, response); + break; + + case ID_DAP_JTAG_Sequence: + num = DAP_JTAG_Sequence(request, response); + break; + case ID_DAP_JTAG_Configure: + num = DAP_JTAG_Configure(request, response); + break; + case ID_DAP_JTAG_IDCODE: + num = DAP_JTAG_IDCode(request, response); + break; + + case ID_DAP_TransferConfigure: + num = DAP_TransferConfigure(request, response); + break; + case ID_DAP_Transfer: + num = DAP_Transfer(request, response); + break; + case ID_DAP_TransferBlock: + num = DAP_TransferBlock(request, response); + break; + + case ID_DAP_WriteABORT: + num = DAP_WriteAbort(request, response); + break; + +#if ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) + case ID_DAP_SWO_Transport: + num = SWO_Transport(request, response); + break; + case ID_DAP_SWO_Mode: + num = SWO_Mode(request, response); + break; + case ID_DAP_SWO_Baudrate: + num = SWO_Baudrate(request, response); + break; + case ID_DAP_SWO_Control: + num = SWO_Control(request, response); + break; + case ID_DAP_SWO_Status: + num = SWO_Status(response); + break; + case ID_DAP_SWO_ExtendedStatus: + num = SWO_ExtendedStatus(request, response); + break; + case ID_DAP_SWO_Data: + num = SWO_Data(request, response); + break; +#endif + + default: + *(response-1) = ID_DAP_Invalid; + return ((1U << 16) | 1U); + } + + return ((1U << 16) + 1U + num); +} + + +// Execute DAP command (process request and prepare response) +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t DAP_ExecuteCommand(const uint8_t *request, uint8_t *response) { + uint32_t cnt, num, n; + + if (*request == ID_DAP_ExecuteCommands) { + *response++ = *request++; + cnt = *request++; + *response++ = (uint8_t)cnt; + num = (2U << 16) | 2U; + while (cnt--) { + n = DAP_ProcessCommand(request, response); + num += n; + request += (uint16_t)(n >> 16); + response += (uint16_t) n; + } + return (num); + } + + return DAP_ProcessCommand(request, response); +} + + +// Setup DAP +void DAP_Setup(void) { + + // Default settings + DAP_Data.debug_port = 0U; + DAP_Data.fast_clock = 0U; + DAP_Data.clock_delay = CLOCK_DELAY(DAP_DEFAULT_SWJ_CLOCK); + DAP_Data.transfer.idle_cycles = 0U; + DAP_Data.transfer.retry_count = 100U; + DAP_Data.transfer.match_retry = 0U; + DAP_Data.transfer.match_mask = 0x00000000U; +#if (DAP_SWD != 0) + DAP_Data.swd_conf.turnaround = 1U; + DAP_Data.swd_conf.data_phase = 0U; +#endif +#if (DAP_JTAG != 0) + DAP_Data.jtag_dev.count = 0U; +#endif + + DAP_SETUP(); // Device specific setup +} diff --git a/components/DAP/source/DAP_vendor.c b/components/DAP/source/DAP_vendor.c new file mode 100644 index 0000000..a4ae496 --- /dev/null +++ b/components/DAP/source/DAP_vendor.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Source + * Title: DAP_vendor.c CMSIS-DAP Vendor Commands + * + *---------------------------------------------------------------------------*/ + +#include "DAP_config.h" +#include "DAP.h" + +//************************************************************************************************** +/** +\defgroup DAP_Vendor_Adapt_gr Adapt Vendor Commands +\ingroup DAP_Vendor_gr +@{ + +The file DAP_vendor.c provides template source code for extension of a Debug Unit with +Vendor Commands. Copy this file to the project folder of the Debug Unit and add the +file to the MDK-ARM project under the file group Configuration. +*/ + +/** Process DAP Vendor Command and prepare Response Data +\param request pointer to request data +\param response pointer to response data +\return number of bytes in response (lower 16 bits) + number of bytes in request (upper 16 bits) +*/ +uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) { + uint32_t num = (1U << 16) | 1U; + + *response++ = *request; // copy Command ID + + switch (*request++) { // first byte in request is Command ID + case ID_DAP_Vendor0: +#if 0 // example user command + num += 1U << 16; // increment request count + if (*request == 1U) { // when first command data byte is 1 + *response++ = 'X'; // send 'X' as response + num++; // increment response count + } +#endif + break; + + case ID_DAP_Vendor1: break; + case ID_DAP_Vendor2: break; + case ID_DAP_Vendor3: break; + case ID_DAP_Vendor4: break; + case ID_DAP_Vendor5: break; + case ID_DAP_Vendor6: break; + case ID_DAP_Vendor7: break; + case ID_DAP_Vendor8: break; + case ID_DAP_Vendor9: break; + case ID_DAP_Vendor10: break; + case ID_DAP_Vendor11: break; + case ID_DAP_Vendor12: break; + case ID_DAP_Vendor13: break; + case ID_DAP_Vendor14: break; + case ID_DAP_Vendor15: break; + case ID_DAP_Vendor16: break; + case ID_DAP_Vendor17: break; + case ID_DAP_Vendor18: break; + case ID_DAP_Vendor19: break; + case ID_DAP_Vendor20: break; + case ID_DAP_Vendor21: break; + case ID_DAP_Vendor22: break; + case ID_DAP_Vendor23: break; + case ID_DAP_Vendor24: break; + case ID_DAP_Vendor25: break; + case ID_DAP_Vendor26: break; + case ID_DAP_Vendor27: break; + case ID_DAP_Vendor28: break; + case ID_DAP_Vendor29: break; + case ID_DAP_Vendor30: break; + case ID_DAP_Vendor31: break; + } + + return (num); +} + +///@} diff --git a/components/DAP/source/JTAG_DP.c b/components/DAP/source/JTAG_DP.c new file mode 100644 index 0000000..24b1f3f --- /dev/null +++ b/components/DAP/source/JTAG_DP.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Source + * Title: JTAG_DP.c CMSIS-DAP JTAG DP I/O + * + *---------------------------------------------------------------------------*/ + +#include "DAP_config.h" +#include "DAP.h" + + +// JTAG Macros + +#define PIN_TCK_SET PIN_SWCLK_TCK_SET +#define PIN_TCK_CLR PIN_SWCLK_TCK_CLR +#define PIN_TMS_SET PIN_SWDIO_TMS_SET +#define PIN_TMS_CLR PIN_SWDIO_TMS_CLR + +#define JTAG_CYCLE_TCK() \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDI(tdi) \ + PIN_TDI_OUT(tdi); \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDO(tdo) \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + tdo = PIN_TDO_IN(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDIO(tdi,tdo) \ + PIN_TDI_OUT(tdi); \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + tdo = PIN_TDO_IN(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) + + +#if (DAP_JTAG != 0) + + +// Generate JTAG Sequence +// info: sequence information +// tdi: pointer to TDI generated data +// tdo: pointer to TDO captured data +// return: none +void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo) { + uint32_t i_val; + uint32_t o_val; + uint32_t bit; + uint32_t n, k; + + n = info & JTAG_SEQUENCE_TCK; + if (n == 0U) { + n = 64U; + } + + if (info & JTAG_SEQUENCE_TMS) { + PIN_TMS_SET(); + } else { + PIN_TMS_CLR(); + } + + while (n) { + i_val = *tdi++; + o_val = 0U; + for (k = 8U; k && n; k--, n--) { + JTAG_CYCLE_TDIO(i_val, bit); + i_val >>= 1; + o_val >>= 1; + o_val |= bit << 7; + } + o_val >>= k; + if (info & JTAG_SEQUENCE_TDO) { + *tdo++ = (uint8_t)o_val; + } + } +} + + +// JTAG Set IR +// ir: IR value +// return: none +#define JTAG_IR_Function(speed) /**/ \ +static void JTAG_IR_##speed (uint32_t ir) { \ + uint32_t n; \ + \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ + JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Capture-IR */ \ + JTAG_CYCLE_TCK(); /* Shift-IR */ \ + \ + PIN_TDI_OUT(1U); \ + for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass before data */ \ + } \ + for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1U; n; n--) { \ + JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \ + ir >>= 1; \ + } \ + n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \ + if (n) { \ + JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \ + PIN_TDI_OUT(1U); \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \ + } \ + \ + JTAG_CYCLE_TCK(); /* Update-IR */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Idle */ \ + PIN_TDI_OUT(1U); \ +} + + +// JTAG Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +#define JTAG_TransferFunction(speed) /**/ \ +static uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \ + uint32_t ack; \ + uint32_t bit; \ + uint32_t val; \ + uint32_t n; \ + \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Capture-DR */ \ + JTAG_CYCLE_TCK(); /* Shift-DR */ \ + \ + for (n = DAP_Data.jtag_dev.index; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass before data */ \ + } \ + \ + JTAG_CYCLE_TDIO(request >> 1, bit); /* Set RnW, Get ACK.0 */ \ + ack = bit << 1; \ + JTAG_CYCLE_TDIO(request >> 2, bit); /* Set A2, Get ACK.1 */ \ + ack |= bit << 0; \ + JTAG_CYCLE_TDIO(request >> 3, bit); /* Set A3, Get ACK.2 */ \ + ack |= bit << 2; \ + \ + if (ack != DAP_TRANSFER_OK) { \ + /* Exit on error */ \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Exit1-DR */ \ + goto exit; \ + } \ + \ + if (request & DAP_TRANSFER_RnW) { \ + /* Read Transfer */ \ + val = 0U; \ + for (n = 31U; n; n--) { \ + JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \ + val |= bit << 31; \ + val >>= 1; \ + } \ + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \ + if (n) { \ + JTAG_CYCLE_TDO(bit); /* Get D31 */ \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \ + } \ + val |= bit << 31; \ + if (data) { *data = val; } \ + } else { \ + /* Write Transfer */ \ + val = *data; \ + for (n = 31U; n; n--) { \ + JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \ + val >>= 1; \ + } \ + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \ + if (n) { \ + JTAG_CYCLE_TDI(val); /* Set D31 */ \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \ + } \ + } \ + \ +exit: \ + JTAG_CYCLE_TCK(); /* Update-DR */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Idle */ \ + PIN_TDI_OUT(1U); \ + \ + /* Capture Timestamp */ \ + if (request & DAP_TRANSFER_TIMESTAMP) { \ + DAP_Data.timestamp = TIMESTAMP_GET(); \ + } \ + \ + /* Idle cycles */ \ + n = DAP_Data.transfer.idle_cycles; \ + while (n--) { \ + JTAG_CYCLE_TCK(); /* Idle */ \ + } \ + \ + return ((uint8_t)ack); \ +} + + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_FAST() +JTAG_IR_Function(Fast) +JTAG_TransferFunction(Fast) + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) +JTAG_IR_Function(Slow) +JTAG_TransferFunction(Slow) + + +// JTAG Read IDCODE register +// return: value read +uint32_t JTAG_ReadIDCode (void) { + uint32_t bit; + uint32_t val; + uint32_t n; + + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Capture-DR */ + JTAG_CYCLE_TCK(); /* Shift-DR */ + + for (n = DAP_Data.jtag_dev.index; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass before data */ + } + + val = 0U; + for (n = 31U; n; n--) { + JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ + val |= bit << 31; + val >>= 1; + } + PIN_TMS_SET(); + JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ + val |= bit << 31; + + JTAG_CYCLE_TCK(); /* Update-DR */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Idle */ + + return (val); +} + + +// JTAG Write ABORT register +// data: value to write +// return: none +void JTAG_WriteAbort (uint32_t data) { + uint32_t n; + + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Capture-DR */ + JTAG_CYCLE_TCK(); /* Shift-DR */ + + for (n = DAP_Data.jtag_dev.index; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass before data */ + } + + PIN_TDI_OUT(0U); + JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */ + JTAG_CYCLE_TCK(); /* Set A2=0 */ + JTAG_CYCLE_TCK(); /* Set A3=0 */ + + for (n = 31U; n; n--) { + JTAG_CYCLE_TDI(data); /* Set D0..D30 */ + data >>= 1; + } + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; + if (n) { + JTAG_CYCLE_TDI(data); /* Set D31 */ + for (--n; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass after data */ + } + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ + } else { + PIN_TMS_SET(); + JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */ + } + + JTAG_CYCLE_TCK(); /* Update-DR */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Idle */ + PIN_TDI_OUT(1U); +} + + +// JTAG Set IR +// ir: IR value +// return: none +void JTAG_IR (uint32_t ir) { + if (DAP_Data.fast_clock) { + JTAG_IR_Fast(ir); + } else { + JTAG_IR_Slow(ir); + } +} + + +// JTAG Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) { + if (DAP_Data.fast_clock) { + return JTAG_TransferFast(request, data); + } else { + return JTAG_TransferSlow(request, data); + } +} + + +#endif /* (DAP_JTAG != 0) */ diff --git a/components/DAP/source/SWO.c b/components/DAP/source/SWO.c new file mode 100644 index 0000000..1093bfb --- /dev/null +++ b/components/DAP/source/SWO.c @@ -0,0 +1,800 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Source + * Title: SWO.c CMSIS-DAP SWO I/O + * + *---------------------------------------------------------------------------*/ + +#include "DAP_config.h" +#include "DAP.h" +#if (SWO_UART != 0) +#include "Driver_USART.h" +#endif +#if (SWO_STREAM != 0) +#include "cmsis_os2.h" +#endif + +#if (SWO_STREAM != 0) +#ifdef DAP_FW_V1 +#error "SWO Streaming Trace not supported in DAP V1!" +#endif +#endif + +#if (SWO_UART != 0) + +#ifndef USART_PORT +#define USART_PORT 0 /* USART Port Number */ +#endif + +// USART Driver +#define _USART_Driver_(n) Driver_USART##n +#define USART_Driver_(n) _USART_Driver_(n) +extern ARM_DRIVER_USART USART_Driver_(USART_PORT); +#define pUSART (&USART_Driver_(USART_PORT)) + +static uint8_t USART_Ready = 0U; + +#endif /* (SWO_UART != 0) */ + + +#if ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) + + +#define SWO_STREAM_TIMEOUT 50U /* Stream timeout in ms */ + +#define USB_BLOCK_SIZE 512U /* USB Block Size */ +#define TRACE_BLOCK_SIZE 64U /* Trace Block Size (2^n: 32...512) */ + +// Trace State +static uint8_t TraceTransport = 0U; /* Trace Transport */ +static uint8_t TraceMode = 0U; /* Trace Mode */ +static uint8_t TraceStatus = 0U; /* Trace Status without Errors */ +static uint8_t TraceError[2] = {0U, 0U}; /* Trace Error flags (banked) */ +static uint8_t TraceError_n = 0U; /* Active Trace Error bank */ + +// Trace Buffer +static uint8_t TraceBuf[SWO_BUFFER_SIZE]; /* Trace Buffer (must be 2^n) */ +static volatile uint32_t TraceIndexI = 0U; /* Incoming Trace Index */ +static volatile uint32_t TraceIndexO = 0U; /* Outgoing Trace Index */ +static volatile uint8_t TraceUpdate; /* Trace Update Flag */ +static uint32_t TraceBlockSize; /* Current Trace Block Size */ + +#if (TIMESTAMP_CLOCK != 0U) +// Trace Timestamp +static volatile struct { + uint32_t index; + uint32_t tick; +} TraceTimestamp; +#endif + +// Trace Helper functions +static void ClearTrace (void); +static void ResumeTrace (void); +static uint32_t GetTraceCount (void); +static uint8_t GetTraceStatus (void); +static void SetTraceError (uint8_t flag); + +#if (SWO_STREAM != 0) +extern osThreadId_t SWO_ThreadId; +static volatile uint8_t TransferBusy = 0U; /* Transfer Busy Flag */ +static uint32_t TransferSize; /* Current Transfer Size */ +#endif + + +#if (SWO_UART != 0) + +// USART Driver Callback function +// event: event mask +static void USART_Callback (uint32_t event) { + uint32_t index_i; + uint32_t index_o; + uint32_t count; + uint32_t num; + + if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) { +#if (TIMESTAMP_CLOCK != 0U) + TraceTimestamp.tick = TIMESTAMP_GET(); +#endif + index_o = TraceIndexO; + index_i = TraceIndexI; + index_i += TraceBlockSize; + TraceIndexI = index_i; +#if (TIMESTAMP_CLOCK != 0U) + TraceTimestamp.index = index_i; +#endif + num = TRACE_BLOCK_SIZE - (index_i & (TRACE_BLOCK_SIZE - 1U)); + count = index_i - index_o; + if (count <= (SWO_BUFFER_SIZE - num)) { + index_i &= SWO_BUFFER_SIZE - 1U; + TraceBlockSize = num; + pUSART->Receive(&TraceBuf[index_i], num); + } else { + TraceStatus = DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED; + } + TraceUpdate = 1U; +#if (SWO_STREAM != 0) + if (TraceTransport == 2U) { + if (count >= (USB_BLOCK_SIZE - (index_o & (USB_BLOCK_SIZE - 1U)))) { + osThreadFlagsSet(SWO_ThreadId, 1U); + } + } +#endif + } + if (event & ARM_USART_EVENT_RX_OVERFLOW) { + SetTraceError(DAP_SWO_BUFFER_OVERRUN); + } + if (event & (ARM_USART_EVENT_RX_BREAK | + ARM_USART_EVENT_RX_FRAMING_ERROR | + ARM_USART_EVENT_RX_PARITY_ERROR)) { + SetTraceError(DAP_SWO_STREAM_ERROR); + } +} + +// Enable or disable UART SWO Mode +// enable: enable flag +// return: 1 - Success, 0 - Error +__WEAK uint32_t UART_SWO_Mode (uint32_t enable) { + int32_t status; + + USART_Ready = 0U; + + if (enable != 0U) { + status = pUSART->Initialize(USART_Callback); + if (status != ARM_DRIVER_OK) { + return (0U); + } + status = pUSART->PowerControl(ARM_POWER_FULL); + if (status != ARM_DRIVER_OK) { + pUSART->Uninitialize(); + return (0U); + } + } else { + pUSART->Control(ARM_USART_CONTROL_RX, 0U); + pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); + pUSART->PowerControl(ARM_POWER_OFF); + pUSART->Uninitialize(); + } + return (1U); +} + +// Configure UART SWO Baudrate +// baudrate: requested baudrate +// return: actual baudrate or 0 when not configured +__WEAK uint32_t UART_SWO_Baudrate (uint32_t baudrate) { + int32_t status; + uint32_t index; + uint32_t num; + + if (baudrate > SWO_UART_MAX_BAUDRATE) { + baudrate = SWO_UART_MAX_BAUDRATE; + } + + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { + pUSART->Control(ARM_USART_CONTROL_RX, 0U); + if (pUSART->GetStatus().rx_busy) { + TraceIndexI += pUSART->GetRxCount(); + pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); + } + } + + status = pUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | + ARM_USART_DATA_BITS_8 | + ARM_USART_PARITY_NONE | + ARM_USART_STOP_BITS_1, + baudrate); + + if (status == ARM_DRIVER_OK) { + USART_Ready = 1U; + } else { + USART_Ready = 0U; + return (0U); + } + + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { + if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 0U) { + index = TraceIndexI & (SWO_BUFFER_SIZE - 1U); + num = TRACE_BLOCK_SIZE - (index & (TRACE_BLOCK_SIZE - 1U)); + TraceBlockSize = num; + pUSART->Receive(&TraceBuf[index], num); + } + pUSART->Control(ARM_USART_CONTROL_RX, 1U); + } + + return (baudrate); +} + +// Control UART SWO Capture +// active: active flag +// return: 1 - Success, 0 - Error +__WEAK uint32_t UART_SWO_Control (uint32_t active) { + int32_t status; + + if (active) { + if (!USART_Ready) { + return (0U); + } + TraceBlockSize = 1U; + status = pUSART->Receive(&TraceBuf[0], 1U); + if (status != ARM_DRIVER_OK) { + return (0U); + } + status = pUSART->Control(ARM_USART_CONTROL_RX, 1U); + if (status != ARM_DRIVER_OK) { + return (0U); + } + } else { + pUSART->Control(ARM_USART_CONTROL_RX, 0U); + if (pUSART->GetStatus().rx_busy) { + TraceIndexI += pUSART->GetRxCount(); + pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); + } + } + return (1U); +} + +// Start UART SWO Capture +// buf: pointer to buffer for capturing +// num: number of bytes to capture +__WEAK void UART_SWO_Capture (uint8_t *buf, uint32_t num) { + TraceBlockSize = num; + pUSART->Receive(buf, num); +} + +// Get UART SWO Pending Trace Count +// return: number of pending trace data bytes +__WEAK uint32_t UART_SWO_GetCount (void) { + uint32_t count; + + if (pUSART->GetStatus().rx_busy) { + count = pUSART->GetRxCount(); + } else { + count = 0U; + } + return (count); +} + +#endif /* (SWO_UART != 0) */ + + +#if (SWO_MANCHESTER != 0) + +// Enable or disable Manchester SWO Mode +// enable: enable flag +// return: 1 - Success, 0 - Error +__WEAK uint32_t Manchester_SWO_Mode (uint32_t enable) { + return (0U); +} + +// Configure Manchester SWO Baudrate +// baudrate: requested baudrate +// return: actual baudrate or 0 when not configured +__WEAK uint32_t Manchester_SWO_Baudrate (uint32_t baudrate) { + return (0U); +} + +// Control Manchester SWO Capture +// active: active flag +// return: 1 - Success, 0 - Error +__WEAK uint32_t Manchester_SWO_Control (uint32_t active) { + return (0U); +} + +// Start Manchester SWO Capture +// buf: pointer to buffer for capturing +// num: number of bytes to capture +__WEAK void Manchester_SWO_Capture (uint8_t *buf, uint32_t num) { +} + +// Get Manchester SWO Pending Trace Count +// return: number of pending trace data bytes +__WEAK uint32_t Manchester_SWO_GetCount (void) { +} + +#endif /* (SWO_MANCHESTER != 0) */ + + +// Clear Trace Errors and Data +static void ClearTrace (void) { + +#if (SWO_STREAM != 0) + if (TraceTransport == 2U) { + if (TransferBusy != 0U) { + SWO_AbortTransfer(); + TransferBusy = 0U; + } + } +#endif + + TraceError[0] = 0U; + TraceError[1] = 0U; + TraceError_n = 0U; + TraceIndexI = 0U; + TraceIndexO = 0U; + +#if (TIMESTAMP_CLOCK != 0U) + TraceTimestamp.index = 0U; + TraceTimestamp.tick = 0U; +#endif +} + +// Resume Trace Capture +static void ResumeTrace (void) { + uint32_t index_i; + uint32_t index_o; + + if (TraceStatus == (DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED)) { + index_i = TraceIndexI; + index_o = TraceIndexO; + if ((index_i - index_o) < SWO_BUFFER_SIZE) { + index_i &= SWO_BUFFER_SIZE - 1U; + switch (TraceMode) { +#if (SWO_UART != 0) + case DAP_SWO_UART: + TraceStatus = DAP_SWO_CAPTURE_ACTIVE; + UART_SWO_Capture(&TraceBuf[index_i], 1U); + break; +#endif +#if (SWO_MANCHESTER != 0) + case DAP_SWO_MANCHESTER: + TraceStatus = DAP_SWO_CAPTURE_ACTIVE; + Manchester_SWO_Capture(&TraceBuf[index_i], 1U); + break; +#endif + default: + break; + } + } + } +} + +// Get Trace Count +// return: number of available data bytes in trace buffer +static uint32_t GetTraceCount (void) { + uint32_t count; + + if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) { + do { + TraceUpdate = 0U; + count = TraceIndexI - TraceIndexO; + switch (TraceMode) { +#if (SWO_UART != 0) + case DAP_SWO_UART: + count += UART_SWO_GetCount(); + break; +#endif +#if (SWO_MANCHESTER != 0) + case DAP_SWO_MANCHESTER: + count += Manchester_SWO_GetCount(); + break; +#endif + default: + break; + } + } while (TraceUpdate != 0U); + } else { + count = TraceIndexI - TraceIndexO; + } + + return (count); +} + +// Get Trace Status (clear Error flags) +// return: Trace Status (Active flag and Error flags) +static uint8_t GetTraceStatus (void) { + uint8_t status; + uint32_t n; + + n = TraceError_n; + TraceError_n ^= 1U; + status = TraceStatus | TraceError[n]; + TraceError[n] = 0U; + + return (status); +} + +// Set Trace Error flag(s) +// flag: error flag(s) to set +static void SetTraceError (uint8_t flag) { + TraceError[TraceError_n] |= flag; +} + + +// Process SWO Transport command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t SWO_Transport (const uint8_t *request, uint8_t *response) { + uint8_t transport; + uint32_t result; + + if ((TraceStatus & DAP_SWO_CAPTURE_ACTIVE) == 0U) { + transport = *request; + switch (transport) { + case 0U: + case 1U: +#if (SWO_STREAM != 0) + case 2U: +#endif + TraceTransport = transport; + result = 1U; + break; + default: + result = 0U; + break; + } + } else { + result = 0U; + } + + if (result != 0U) { + *response = DAP_OK; + } else { + *response = DAP_ERROR; + } + + return ((1U << 16) | 1U); +} + + +// Process SWO Mode command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t SWO_Mode (const uint8_t *request, uint8_t *response) { + uint8_t mode; + uint32_t result; + + mode = *request; + + switch (TraceMode) { +#if (SWO_UART != 0) + case DAP_SWO_UART: + UART_SWO_Mode(0U); + break; +#endif +#if (SWO_MANCHESTER != 0) + case DAP_SWO_MANCHESTER: + Manchester_SWO_Mode(0U); + break; +#endif + default: + break; + } + + switch (mode) { + case DAP_SWO_OFF: + result = 1U; + break; +#if (SWO_UART != 0) + case DAP_SWO_UART: + result = UART_SWO_Mode(1U); + break; +#endif +#if (SWO_MANCHESTER != 0) + case DAP_SWO_MANCHESTER: + result = Manchester_SWO_Mode(1U); + break; +#endif + default: + result = 0U; + break; + } + if (result != 0U) { + TraceMode = mode; + } else { + TraceMode = DAP_SWO_OFF; + } + + TraceStatus = 0U; + + if (result != 0U) { + *response = DAP_OK; + } else { + *response = DAP_ERROR; + } + + return ((1U << 16) | 1U); +} + + +// Process SWO Baudrate command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response) { + uint32_t baudrate; + + baudrate = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8) | + (uint32_t)(*(request+2) << 16) | + (uint32_t)(*(request+3) << 24); + + switch (TraceMode) { +#if (SWO_UART != 0) + case DAP_SWO_UART: + baudrate = UART_SWO_Baudrate(baudrate); + break; +#endif +#if (SWO_MANCHESTER != 0) + case DAP_SWO_MANCHESTER: + baudrate = Manchester_SWO_Baudrate(baudrate); + break; +#endif + default: + baudrate = 0U; + break; + } + + if (baudrate == 0U) { + TraceStatus = 0U; + } + + *response++ = (uint8_t)(baudrate >> 0); + *response++ = (uint8_t)(baudrate >> 8); + *response++ = (uint8_t)(baudrate >> 16); + *response = (uint8_t)(baudrate >> 24); + + return ((4U << 16) | 4U); +} + + +// Process SWO Control command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t SWO_Control (const uint8_t *request, uint8_t *response) { + uint8_t active; + uint32_t result; + + active = *request & DAP_SWO_CAPTURE_ACTIVE; + + if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) { + if (active) { + ClearTrace(); + } + switch (TraceMode) { +#if (SWO_UART != 0) + case DAP_SWO_UART: + result = UART_SWO_Control(active); + break; +#endif +#if (SWO_MANCHESTER != 0) + case DAP_SWO_MANCHESTER: + result = Manchester_SWO_Control(active); + break; +#endif + default: + result = 0U; + break; + } + if (result != 0U) { + TraceStatus = active; +#if (SWO_STREAM != 0) + if (TraceTransport == 2U) { + osThreadFlagsSet(SWO_ThreadId, 1U); + } +#endif + } + } else { + result = 1U; + } + + if (result != 0U) { + *response = DAP_OK; + } else { + *response = DAP_ERROR; + } + + return ((1U << 16) | 1U); +} + + +// Process SWO Status command and prepare response +// response: pointer to response data +// return: number of bytes in response +uint32_t SWO_Status (uint8_t *response) { + uint8_t status; + uint32_t count; + + status = GetTraceStatus(); + count = GetTraceCount(); + + *response++ = status; + *response++ = (uint8_t)(count >> 0); + *response++ = (uint8_t)(count >> 8); + *response++ = (uint8_t)(count >> 16); + *response = (uint8_t)(count >> 24); + + return (5U); +} + + +// Process SWO Extended Status command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response) { + uint8_t cmd; + uint8_t status; + uint32_t count; +#if (TIMESTAMP_CLOCK != 0U) + uint32_t index; + uint32_t tick; +#endif + uint32_t num; + + num = 0U; + cmd = *request; + + if (cmd & 0x01U) { + status = GetTraceStatus(); + *response++ = status; + num += 1U; + } + + if (cmd & 0x02U) { + count = GetTraceCount(); + *response++ = (uint8_t)(count >> 0); + *response++ = (uint8_t)(count >> 8); + *response++ = (uint8_t)(count >> 16); + *response++ = (uint8_t)(count >> 24); + num += 4U; + } + +#if (TIMESTAMP_CLOCK != 0U) + if (cmd & 0x04U) { + do { + TraceUpdate = 0U; + index = TraceTimestamp.index; + tick = TraceTimestamp.tick; + } while (TraceUpdate != 0U); + *response++ = (uint8_t)(index >> 0); + *response++ = (uint8_t)(index >> 8); + *response++ = (uint8_t)(index >> 16); + *response++ = (uint8_t)(index >> 24); + *response++ = (uint8_t)(tick >> 0); + *response++ = (uint8_t)(tick >> 8); + *response++ = (uint8_t)(tick >> 16); + *response++ = (uint8_t)(tick >> 24); + num += 4U; + } +#endif + + return ((1U << 16) | num); +} + + +// Process SWO Data command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +uint32_t SWO_Data (const uint8_t *request, uint8_t *response) { + uint8_t status; + uint32_t count; + uint32_t index; + uint32_t n, i; + + status = GetTraceStatus(); + count = GetTraceCount(); + + if (TraceTransport == 1U) { + n = (uint32_t)(*(request+0) << 0) | + (uint32_t)(*(request+1) << 8); + if (n > (DAP_PACKET_SIZE - 4U)) { + n = DAP_PACKET_SIZE - 4U; + } + if (count > n) { + count = n; + } + } else { + count = 0U; + } + + *response++ = status; + *response++ = (uint8_t)(count >> 0); + *response++ = (uint8_t)(count >> 8); + + if (TraceTransport == 1U) { + index = TraceIndexO; + for (i = index, n = count; n; n--) { + i &= SWO_BUFFER_SIZE - 1U; + *response++ = TraceBuf[i++]; + } + TraceIndexO = index + count; + ResumeTrace(); + } + + return ((2U << 16) | (3U + count)); +} + + +#if (SWO_STREAM != 0) + +// SWO Data Transfer complete callback +void SWO_TransferComplete (void) { + TraceIndexO += TransferSize; + TransferBusy = 0U; + ResumeTrace(); + osThreadFlagsSet(SWO_ThreadId, 1U); +} + +// SWO Thread +__NO_RETURN void SWO_Thread (void *argument) { + uint32_t timeout; + uint32_t flags; + uint32_t count; + uint32_t index; + uint32_t i, n; + (void) argument; + + timeout = osWaitForever; + + for (;;) { + flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout); + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { + timeout = SWO_STREAM_TIMEOUT; + } else { + timeout = osWaitForever; + flags = osFlagsErrorTimeout; + } + if (TransferBusy == 0U) { + count = GetTraceCount(); + if (count != 0U) { + index = TraceIndexO & (SWO_BUFFER_SIZE - 1U); + n = SWO_BUFFER_SIZE - index; + if (count > n) { + count = n; + } + if (flags != osFlagsErrorTimeout) { + i = index & (USB_BLOCK_SIZE - 1U); + if (i == 0U) { + count &= ~(USB_BLOCK_SIZE - 1U); + } else { + n = USB_BLOCK_SIZE - i; + if (count >= n) { + count = n; + } else { + count = 0U; + } + } + } + if (count != 0U) { + TransferSize = count; + TransferBusy = 1U; + SWO_QueueTransfer(&TraceBuf[index], count); + } + } + } + } +} + +#endif /* (SWO_STREAM != 0) */ + + +#endif /* ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) */ diff --git a/components/DAP/source/SW_DP.c b/components/DAP/source/SW_DP.c new file mode 100644 index 0000000..803cf42 --- /dev/null +++ b/components/DAP/source/SW_DP.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Source + * Title: SW_DP.c CMSIS-DAP SW DP I/O + * + *---------------------------------------------------------------------------*/ + +#include "DAP_config.h" +#include "DAP.h" + + +// SW Macros + +#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET +#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR + +#define SW_CLOCK_CYCLE() \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define SW_WRITE_BIT(bit) \ + PIN_SWDIO_OUT(bit); \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define SW_READ_BIT(bit) \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + bit = PIN_SWDIO_IN(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) + + +// Generate SWJ Sequence +// count: sequence bit count +// data: pointer to sequence bit data +// return: none +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +void SWJ_Sequence (uint32_t count, const uint8_t *data) { + uint32_t val; + uint32_t n; + + val = 0U; + n = 0U; + while (count--) { + if (n == 0U) { + val = *data++; + n = 8U; + } + if (val & 1U) { + PIN_SWDIO_TMS_SET(); + } else { + PIN_SWDIO_TMS_CLR(); + } + SW_CLOCK_CYCLE(); + val >>= 1; + n--; + } +} +#endif + + +// Generate SWD Sequence +// info: sequence information +// swdo: pointer to SWDIO generated data +// swdi: pointer to SWDIO captured data +// return: none +#if (DAP_SWD != 0) +void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { + uint32_t val; + uint32_t bit; + uint32_t n, k; + + n = info & SWD_SEQUENCE_CLK; + if (n == 0U) { + n = 64U; + } + + if (info & SWD_SEQUENCE_DIN) { + while (n) { + val = 0U; + for (k = 8U; k && n; k--, n--) { + SW_READ_BIT(bit); + val >>= 1; + val |= bit << 7; + } + val >>= k; + *swdi++ = (uint8_t)val; + } + } else { + while (n) { + val = *swdo++; + for (k = 8U; k && n; k--, n--) { + SW_WRITE_BIT(val); + val >>= 1; + } + } + } +} +#endif + + +#if (DAP_SWD != 0) + + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +#define SWD_TransferFunction(speed) /**/ \ +static uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \ + uint32_t ack; \ + uint32_t bit; \ + uint32_t val; \ + uint32_t parity; \ + \ + uint32_t n; \ + \ + /* Packet Request */ \ + parity = 0U; \ + SW_WRITE_BIT(1U); /* Start Bit */ \ + bit = request >> 0; \ + SW_WRITE_BIT(bit); /* APnDP Bit */ \ + parity += bit; \ + bit = request >> 1; \ + SW_WRITE_BIT(bit); /* RnW Bit */ \ + parity += bit; \ + bit = request >> 2; \ + SW_WRITE_BIT(bit); /* A2 Bit */ \ + parity += bit; \ + bit = request >> 3; \ + SW_WRITE_BIT(bit); /* A3 Bit */ \ + parity += bit; \ + SW_WRITE_BIT(parity); /* Parity Bit */ \ + SW_WRITE_BIT(0U); /* Stop Bit */ \ + SW_WRITE_BIT(1U); /* Park Bit */ \ + \ + /* Turnaround */ \ + PIN_SWDIO_OUT_DISABLE(); \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + \ + /* Acknowledge response */ \ + SW_READ_BIT(bit); \ + ack = bit << 0; \ + SW_READ_BIT(bit); \ + ack |= bit << 1; \ + SW_READ_BIT(bit); \ + ack |= bit << 2; \ + \ + if (ack == DAP_TRANSFER_OK) { /* OK response */ \ + /* Data transfer */ \ + if (request & DAP_TRANSFER_RnW) { \ + /* Read data */ \ + val = 0U; \ + parity = 0U; \ + for (n = 32U; n; n--) { \ + SW_READ_BIT(bit); /* Read RDATA[0:31] */ \ + parity += bit; \ + val >>= 1; \ + val |= bit << 31; \ + } \ + SW_READ_BIT(bit); /* Read Parity */ \ + if ((parity ^ bit) & 1U) { \ + ack = DAP_TRANSFER_ERROR; \ + } \ + if (data) { *data = val; } \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + } else { \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + /* Write data */ \ + val = *data; \ + parity = 0U; \ + for (n = 32U; n; n--) { \ + SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \ + parity += val; \ + val >>= 1; \ + } \ + SW_WRITE_BIT(parity); /* Write Parity Bit */ \ + } \ + /* Capture Timestamp */ \ + if (request & DAP_TRANSFER_TIMESTAMP) { \ + DAP_Data.timestamp = TIMESTAMP_GET(); \ + } \ + /* Idle cycles */ \ + n = DAP_Data.transfer.idle_cycles; \ + if (n) { \ + PIN_SWDIO_OUT(0U); \ + for (; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + } \ + PIN_SWDIO_OUT(1U); \ + return ((uint8_t)ack); \ + } \ + \ + if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \ + /* WAIT or FAULT response */ \ + if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) { \ + for (n = 32U+1U; n; n--) { \ + SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \ + } \ + } \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) { \ + PIN_SWDIO_OUT(0U); \ + for (n = 32U+1U; n; n--) { \ + SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \ + } \ + } \ + PIN_SWDIO_OUT(1U); \ + return ((uint8_t)ack); \ + } \ + \ + /* Protocol error */ \ + for (n = DAP_Data.swd_conf.turnaround + 32U + 1U; n; n--) { \ + SW_CLOCK_CYCLE(); /* Back off data phase */ \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + PIN_SWDIO_OUT(1U); \ + return ((uint8_t)ack); \ +} + + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_FAST() +SWD_TransferFunction(Fast) + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) +SWD_TransferFunction(Slow) + + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +uint8_t SWD_Transfer(uint32_t request, uint32_t *data) { + if (DAP_Data.fast_clock) { + return SWD_TransferFast(request, data); + } else { + return SWD_TransferSlow(request, data); + } +} + + +#endif /* (DAP_SWD != 0) */ diff --git a/components/README.md b/components/README.md new file mode 100644 index 0000000..474ac22 --- /dev/null +++ b/components/README.md @@ -0,0 +1,3 @@ +# TODO +1. adapt to special hardware +2. USB \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 844a715..0671f1b 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,4 +1,4 @@ set(COMPONENT_SRCS "tcp_server.c") -set(COMPONENT_ADD_INCLUDEDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS ". $ENV{IDF_PATH}/components/esp8266/include/esp8266/") register_component() diff --git a/main/tcp_server.c b/main/tcp_server.c index 1930626..ad58f76 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -7,6 +7,7 @@ CONDITIONS OF ANY KIND, either express or implied. */ #include +#include #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -22,6 +23,11 @@ #include "lwip/sys.h" #include +#include "gpio.h" +#include "hw_timer.h" +#include "timer_struct.h" + + /* The examples use simple WiFi configuration that you can set via 'make menuconfig'. If you'd rather not, just change the below entries to strings with @@ -108,6 +114,7 @@ static void initialise_wifi(void) ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); + } static void wait_for_ip() @@ -180,7 +187,7 @@ static void tcp_server_task(void *pvParameters) #else struct sockaddr_in sourceAddr; #endif - uint addrLen = sizeof(sourceAddr); + uint32_t addrLen = sizeof(sourceAddr); int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); if (sock < 0) { @@ -248,11 +255,25 @@ static void tcp_server_task(void *pvParameters) vTaskDelete(NULL); } +void timer_create_task() +{ + // FRC1 frequency 80MHz + vPortEnterCritical(); + frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz + frc1.ctrl.intr_type = TIMER_EDGE_INT; + frc1.ctrl.reload = 0x01; + frc1.load.data = 0x1000000U - 1U; + frc1.ctrl.en = 0x01; + vPortExitCritical(); + vTaskDelete(NULL); +} + void app_main() { ESP_ERROR_CHECK(nvs_flash_init()); initialise_wifi(); wait_for_ip(); - + + xTaskCreate(timer_create_task, "timer_create", 2048, NULL, 10, NULL); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); } From 2037ba6392f359d6f621f0c90befedca0779ae36 Mon Sep 17 00:00:00 2001 From: windowsair Date: Wed, 22 Jan 2020 10:29:15 +0800 Subject: [PATCH 02/21] fix: project name & main.c file --- CMakeLists.txt | 2 +- main/{tcp_server.c => main.c} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename main/{tcp_server.c => main.c} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3514e60..afc306e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.5) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(tcp_server) +project(esp8266_dap) diff --git a/main/tcp_server.c b/main/main.c similarity index 100% rename from main/tcp_server.c rename to main/main.c From a15f87374465c0600af9ebf04f18a8bc552f9186 Mon Sep 17 00:00:00 2001 From: windowsair Date: Wed, 22 Jan 2020 22:06:29 +0800 Subject: [PATCH 03/21] feat: Add USBIP component (partially completed) --- README.md | 5 + components/USBIP/usb_defs.h | 320 ++++++++++++++++++++++++++++++++++ components/USBIP/usbip_defs.h | 223 +++++++++++++++++++++++ main/CMakeLists.txt | 4 +- main/component.mk | 4 - main/main.c | 147 +--------------- main/tcp_server.c | 171 ++++++++++++++++++ main/tcp_server.h | 6 + main/timer.c | 29 +++ main/timer.h | 6 + main/usbip_server.c | 132 ++++++++++++++ main/usbip_server.h | 16 ++ main/wifi_configuration.h | 18 ++ 13 files changed, 932 insertions(+), 149 deletions(-) create mode 100644 components/USBIP/usb_defs.h create mode 100644 components/USBIP/usbip_defs.h delete mode 100644 main/component.mk create mode 100644 main/tcp_server.c create mode 100644 main/tcp_server.h create mode 100644 main/timer.c create mode 100644 main/timer.h create mode 100644 main/usbip_server.c create mode 100644 main/usbip_server.h create mode 100644 main/wifi_configuration.h diff --git a/README.md b/README.md index e69de29..e00d592 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,5 @@ +# Setup +1. DAP_Setup() +2. Server begin + +# Loop \ No newline at end of file diff --git a/components/USBIP/usb_defs.h b/components/USBIP/usb_defs.h new file mode 100644 index 0000000..d75f317 --- /dev/null +++ b/components/USBIP/usb_defs.h @@ -0,0 +1,320 @@ +/** + * @file usb_defs.h + * @brief Modify + * @version 0.1 + * @date 2020-01-22 + * + * @copyright Copyright (c) 2020 + * + */ + +// +// Created by thevoidnn on 10/25/17. +// + +#ifndef __USB_DEFS_H__ +#define __USB_DEFS_H__ + +#include + + +#define USB_CLASS_MISCELLANEOUS_DEVICE 0xef +#define USB_MISC_SUBCLASS_COMMON 0x02 +#define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01 + + + + + + +union word_t { + struct { + uint8_t u8lo; + uint8_t u8hi; + } __attribute__((packed)); + uint16_t u16; +}; + +struct usb_standard_request +{ + uint8_t bmRequestType; + uint8_t bRequest; + word_t wValue; + word_t wIndex; + word_t wLength; +} __attribute__((packed)); + + + + + +//#define USB_CLASS_HID 3 + +#define USB_DT_HID 0x21 +#define USB_DT_REPORT 0x22 + +//struct usb_hid_descriptor { +// uint8_t bLength; +// uint8_t bDescriptorType; +// uint16_t bcdHID; +// uint8_t bCountryCode; +// uint8_t bNumDescriptors; +//} __attribute__((packed)); +//#define USB_DT_HID_SIZE sizeof(struct usb_hid_descriptor) + +//struct usb_hid_report_descriptor { +// uint8_t bDescriptorType; +// uint16_t wReportLength; +//} __attribute__((packed)); + + +#define USB_DT_REPORT_SIZE sizeof(struct usb_hid_report_descriptor) + + +/* Class Definition */ +#define USB_CLASS_VENDOR 0xFF + +/////////////////////////////////////////////////////////////// +/* Table 9-2. Format of Setup Data */ +/* bmRequestType bit definitions */ + +/* bit 7 : Direction */ +#define USB_REQ_TYPE_OUT 0x00 // Host-to-device +#define USB_REQ_TYPE_IN 0x80 // Device-to-host +/* bits 6..5 : Type */ +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_RESERVED 0x60 +/* bits 4..0 : Recipient */ +#define USB_REQ_TYPE_DEVICE 0x00 +#define USB_REQ_TYPE_INTERFACE 0x01 +#define USB_REQ_TYPE_ENDPOINT 0x02 +#define USB_REQ_TYPE_OTHER 0x03 +#define USB_REQ_TYPE_RESERVED 0x1F +/////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////// +/* USB Standard Request Codes - Table 9-4 */ +#define USB_REQ_GET_STATUS 0 +#define USB_REQ_CLEAR_FEATURE 1 +/* Reserved for future use: 2 */ +#define USB_REQ_SET_FEATURE 3 +/* Reserved for future use: 3 */ +#define USB_REQ_SET_ADDRESS 5 +#define USB_REQ_GET_DESCRIPTOR 6 +#define USB_REQ_SET_DESCRIPTOR 7 +#define USB_REQ_GET_CONFIGURATION 8 +#define USB_REQ_SET_CONFIGURATION 9 +#define USB_REQ_GET_INTERFACE 10 +#define USB_REQ_SET_INTERFACE 11 +#define USB_REQ_SET_SYNCH_FRAME 12 +/////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////// +/* USB Descriptor Types - Table 9-5 */ +#define USB_DT_DEVICE 1 +#define USB_DT_CONFIGURATION 2 +#define USB_DT_STRING 3 +#define USB_DT_INTERFACE 4 +#define USB_DT_ENDPOINT 5 +#define USB_DT_DEVICE_QUALIFIER 6 +#define USB_DT_OTHER_SPEED_CONFIGURATION 7 +#define USB_DT_INTERFACE_POWER 8 +/* From ECNs */ +#define USB_DT_OTG 9 +#define USB_DT_DEBUG 10 +#define USB_DT_INTERFACE_ASSOCIATION 11 +/////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////// +/* USB Standard Feature Selectors - Table 9-6 */ +#define USB_FEAT_ENDPOINT_HALT 0 // Recipient: Device +#define USB_FEAT_DEVICE_REMOTE_WAKEUP 1 // Recipient: Endpoint +#define USB_FEAT_TEST_MODE 2 // Recipient: Device + +/* Information Returned by a GetStatus() Request to a Device - Figure 9-4 */ +#define USB_DEV_STATUS_SELF_POWERED 0x01 +#define USB_DEV_STATUS_REMOTE_WAKEUP 0x02 +/////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////// +/* USB Standard Device Descriptor - Table 9-8 */ +struct usb_device_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} __attribute__((packed)); +#define USB_DT_DEVICE_SIZE sizeof(struct usb_device_descriptor) +/////////////////////////////////////////////////////////////// + + + +/////////////////////////////////////////////////////////////// +/* USB Device_Qualifier Descriptor - Table 9-9 + * Not used in this implementation. + */ +struct usb_device_qualifier_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bReserved; +} __attribute__((packed)); +/////////////////////////////////////////////////////////////// + + +/* This is only defined as a top level named struct to improve c++ + * compatibility. You should never need to instance this struct + * in user code! */ +struct usb_interface { + uint8_t *cur_altsetting; + uint8_t num_altsetting; + const struct usb_iface_assoc_descriptor *iface_assoc; + const struct usb_interface_descriptor *altsetting; +}; + + + +/////////////////////////////////////////////////////////////// +/* USB Standard Configuration Descriptor - Table 9-10 */ +struct usb_config_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} __attribute__((packed)); +#define USB_DT_CONFIGURATION_SIZE sizeof(struct usb_config_descriptor) +/////////////////////////////////////////////////////////////// + + + +/* USB Configuration Descriptor *bmAttributes* bit definitions */ +#define USB_CONFIG_ATTR_DEFAULT 0x80 /** always required (USB2.0 table 9-10) */ +#define USB_CONFIG_ATTR_SELF_POWERED 0x40 +#define USB_CONFIG_ATTR_REMOTE_WAKEUP 0x20 + +/* Other Speed Configuration is the same as Configuration Descriptor. + * - Table 9-11 + */ + + +/////////////////////////////////////////////////////////////// +/* USB Standard Interface Descriptor - Table 9-12 */ +struct usb_interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} __attribute__((packed)); +#define USB_DT_INTERFACE_SIZE sizeof(struct usb_interface_descriptor) +/////////////////////////////////////////////////////////////// + + + +/////////////////////////////////////////////////////////////// +/* USB Standard Endpoint Descriptor - Table 9-13 */ +struct usb_endpoint_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} __attribute__((packed)); +#define USB_DT_ENDPOINT_SIZE sizeof(struct usb_endpoint_descriptor) +/////////////////////////////////////////////////////////////// + + +/* USB bEndpointAddress helper macros */ +#define USB_ENDPOINT_ADDR_OUT(x) (x) +#define USB_ENDPOINT_ADDR_IN(x) (0x80 | (x)) + + +/////////////////////////////////////////////////////////////// +/* USB Endpoint Descriptor bmAttributes bit definitions - Table 9-13 */ +/* bits 1..0 : Transfer type */ +#define USB_ENDPOINT_ATTR_CONTROL 0x00 +#define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_ATTR_BULK 0x02 +#define USB_ENDPOINT_ATTR_INTERRUPT 0x03 +#define USB_ENDPOINT_ATTR_TYPE 0x03 +// If not an isochronous endpoint, bits 5..2 are reserved +// and must be set to zero. +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_ENDPOINT_ATTR_NOSYNC 0x00 +#define USB_ENDPOINT_ATTR_ASYNC 0x04 +#define USB_ENDPOINT_ATTR_ADAPTIVE 0x08 +#define USB_ENDPOINT_ATTR_SYNC 0x0C +#define USB_ENDPOINT_ATTR_SYNCTYPE 0x0C +/* bits 5..4 : Usage type (only if ISOCHRONOUS) */ +#define USB_ENDPOINT_ATTR_DATA 0x00 +#define USB_ENDPOINT_ATTR_FEEDBACK 0x10 +#define USB_ENDPOINT_ATTR_IMPLICIT_FEEDBACK_DATA 0x20 +#define USB_ENDPOINT_ATTR_USAGETYPE 0x30 +/////////////////////////////////////////////////////////////// + + + +/////////////////////////////////////////////////////////////// +/* Table 9-15 specifies String Descriptor Zero. + * Table 9-16 specified UNICODE String Descriptor. + */ +struct usb_string_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wData[]; +} __attribute__((packed)); + +/* From ECN: Interface Association Descriptors, Table 9-Z */ +struct usb_iface_assoc_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; +} __attribute__((packed)); +#define USB_DT_INTERFACE_ASSOCIATION_SIZE \ + sizeof(struct usb_iface_assoc_descriptor) + +enum usb_language_id { + USB_LANGID_ENGLISH_US = 0x409, +}; +/////////////////////////////////////////////////////////////// + + + + + +#endif diff --git a/components/USBIP/usbip_defs.h b/components/USBIP/usbip_defs.h new file mode 100644 index 0000000..943989a --- /dev/null +++ b/components/USBIP/usbip_defs.h @@ -0,0 +1,223 @@ +/** + * @file usbip_defs.h + * @brief Simple modification + * @version 0.1 + * @date 2020-01-22 + * + * @copyright Copyright (c) 2020 + * + */ + +// Focus on the following structures in this file: +// usbip_stage2_header +// usbip_stage1_response_devlist + + +// +// Created by thevoidnn on 10/25/17. +// + +#ifndef __USBIP_DEFS_H__ +#define __USBIP_DEFS_H__ + +#include +#include "usb_defs.h" + +#define USBIP_SYSFS_PATH_SIZE 256 +#define USBIP_BUSID_SIZE 32 + +enum usbip_stage1_command { + // Offset 2 + USBIP_STAGE1_CMD_DEVICE_LIST = 0x05, // OP_REQ_DEVLIST + USBIP_STAGE1_CMD_DEVICE_ATTACH = 0x03, // OP_REQ_IMPORT +}; + +enum usbip_stager2_command { ////TODO: change to stage2 + //Offset 0 + USBIP_STAGE2_REQ_SUBMIT = 0x0001, + USBIP_STAGE2_REQ_UNLINK = 0x0002, + USBIP_STAGE2_RSP_SUBMIT = 0x0003, + USBIP_STAGE2_RSP_UNLINK = 0x0004, +}; + +enum usbip_stage2_direction { + USBIP_DIR_OUT = 0x00, + USBIP_DIR_IN = 0x01, +}; + +struct usbip_stage1_header { + uint16_t version; + uint16_t command; + uint32_t status; +} __attribute__ ((__packed__)); +///////////////////////////////////////////////////////////// + + + +// Device description +struct usbip_stage1_usb_device { + char path[USBIP_SYSFS_PATH_SIZE]; + char busid[USBIP_BUSID_SIZE]; + + uint32_t busnum; + uint32_t devnum; + uint32_t speed; + + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + + uint8_t bConfigurationValue; + uint8_t bNumConfigurations; + uint8_t bNumInterfaces; +} __attribute__((packed)); + +// Interface description +struct usbip_stage1_usb_interface { + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t padding; +} __attribute__((packed)); + + + + +struct usbip_stage1_response_devlist_entry { + struct usbip_stage1_usb_device udev; + struct usbip_stage1_usb_interface uinf[]; +} __attribute__((packed)); + +struct usbip_stage1_response_devlist { + uint32_t list_size; + usbip_stage1_response_devlist_entry devices[]; +} __attribute__ ((__packed__)); + + + + + +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////// + + + +/** + * struct usbip_header_basic - data pertinent to every URB request + * RESPONSE & REQUEST + * + * @command: the usbip request type + * @seqnum: sequential number that identifies requests; incremented per + * connection + * @devid: specifies a remote USB device uniquely instead of busnum and devnum; + * in the stub driver, this value is ((busnum << 16) | devnum) + * @direction: direction of the transfer + * @ep: endpoint number + */ +struct usbip_stage2_header_basic { + uint32_t command; + uint32_t seqnum; + uint32_t devid; + uint32_t direction; + uint32_t ep; +} __attribute__((packed)); + +/** + * struct usbip_header_cmd_submit - USBIP_CMD_SUBMIT packet header + * >>>REQUEST + * + * @transfer_flags: URB flags + * @transfer_buffer_length: the data size for (in) or (out) transfer + * @start_frame: initial frame for isochronous or interrupt transfers + * @number_of_packets: number of isochronous packets + * @interval: maximum time for the request on the server-side host controller + * @setup: setup data for a control request + */ +struct usbip_stage2_header_cmd_submit { + uint32_t transfer_flags; + int32_t data_length; + + /* it is difficult for usbip to sync frames (reserved only?) */ + int32_t start_frame; + int32_t number_of_packets; + int32_t interval; + + union { + uint8_t setup[8]; + usb_standard_request request; + }; +} __attribute__((packed)); + +/** + * struct usbip_header_ret_submit - USBIP_RET_SUBMIT packet header + * <<>>REQUEST + * @seqnum: the URB seqnum to unlink + */ +struct usbip_stage2_header_cmd_unlink { + uint32_t seqnum; +} __attribute__((packed)); + +/** + * struct usbip_header_ret_unlink - USBIP_RET_UNLINK packet header + * << -#include "gpio.h" -#include "hw_timer.h" -#include "timer_struct.h" - +#include "tcp_server.h" +#include "timer.h" +#include "wifi_configuration.h" /* The examples use simple WiFi configuration that you can set via 'make menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" */ -#define EXAMPLE_WIFI_SSID "DAP" -#define EXAMPLE_WIFI_PASS "12345678" -#define PORT 22350 /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; @@ -46,7 +42,6 @@ const int IPV4_GOTIP_BIT = BIT0; const int IPV6_GOTIP_BIT = BIT1; #endif -static const char *TAG = "example"; static esp_err_t event_handler(void *ctx, system_event_t *event) { @@ -130,143 +125,9 @@ static void wait_for_ip() os_printf("Connected to AP"); } -static void tcp_server_task(void *pvParameters) -{ - char rx_buffer[2048]; - char addr_str[128]; - int addr_family; - int ip_protocol; - while (1) - { -#ifdef CONFIG_EXAMPLE_IPV4 - struct sockaddr_in destAddr; - destAddr.sin_addr.s_addr = htonl(INADDR_ANY); - destAddr.sin_family = AF_INET; - destAddr.sin_port = htons(PORT); - addr_family = AF_INET; - ip_protocol = IPPROTO_IP; - inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); -#else // IPV6 - struct sockaddr_in6 destAddr; - bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un)); - destAddr.sin6_family = AF_INET6; - destAddr.sin6_port = htons(PORT); - addr_family = AF_INET6; - ip_protocol = IPPROTO_IPV6; - inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); -#endif - int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); - if (listen_sock < 0) - { - os_printf("Unable to create socket: errno %d\r\n", errno); - break; - } - os_printf("Socket created"); - - int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); - if (err != 0) - { - os_printf("Socket unable to bind: errno %d\r\n", errno); - break; - } - os_printf("Socket binded"); - - err = listen(listen_sock, 1); - if (err != 0) - { - os_printf("Error occured during listen: errno %d\r\n", errno); - break; - } - os_printf("Socket listening"); - -#ifdef CONFIG_EXAMPLE_IPV6 - struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 -#else - struct sockaddr_in sourceAddr; -#endif - uint32_t addrLen = sizeof(sourceAddr); - int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); - if (sock < 0) - { - os_printf("Unable to accept connection: errno %d\r\n", errno); - break; - } - os_printf("Socket accepted"); - - while (1) - { - int len = recv(sock, rx_buffer, 2047, 0); - // Error occured during receiving - if (len < 0) - { - os_printf("recv failed: errno %d\r\n", errno); - break; - } - // Connection closed - else if (len == 0) - { - os_printf("Connection closed\r\n"); - break; - } - // Data received - else - { -#ifdef CONFIG_EXAMPLE_IPV6 - // Get the sender's ip address as string - if (sourceAddr.sin6_family == PF_INET) - { - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - } - else if (sourceAddr.sin6_family == PF_INET6) - { - inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); - } -#else - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); -#endif - - rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string - //os_printf("Received %d bytes from %s:\r\n", len, addr_str); - // os_printf("%s", rx_buffer); - - int err = send(sock, rx_buffer, len, 0); - if (err < 0) - { - os_printf("Error occured during sending: errno %d\r\n", errno); - break; - } - } - } - - if (sock != -1) - { - os_printf("Shutting down socket and restarting...\r\n"); - shutdown(sock, 0); - close(sock); - - shutdown(listen_sock, 0); - close(listen_sock); - vTaskDelay(5); - } - } - vTaskDelete(NULL); -} - -void timer_create_task() -{ - // FRC1 frequency 80MHz - vPortEnterCritical(); - frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz - frc1.ctrl.intr_type = TIMER_EDGE_INT; - frc1.ctrl.reload = 0x01; - frc1.load.data = 0x1000000U - 1U; - frc1.ctrl.en = 0x01; - vPortExitCritical(); - vTaskDelete(NULL); -} void app_main() { @@ -274,6 +135,6 @@ void app_main() initialise_wifi(); wait_for_ip(); - xTaskCreate(timer_create_task, "timer_create", 2048, NULL, 10, NULL); + xTaskCreate(timer_create_task, "timer_create", 1024, NULL, 10, NULL); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); } diff --git a/main/tcp_server.c b/main/tcp_server.c new file mode 100644 index 0000000..f28213b --- /dev/null +++ b/main/tcp_server.c @@ -0,0 +1,171 @@ +/** + * @file tcp_server.c + * @brief Handle main tcp tasks + * @version 0.1 + * @date 2020-01-22 + * + * @copyright Copyright (c) 2020 + * + */ +#include "tcp_server.h" + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +#include "wifi_configuration.h" +#include "usbip_server.h" + +uint8_t state = ACCEPTING; +int sock = -1; +void tcp_server_task(void *pvParameters) +{ + char rx_buffer[2048]; + char addr_str[128]; + int addr_family; + int ip_protocol; + + while (1) + { + +#ifdef CONFIG_EXAMPLE_IPV4 + struct sockaddr_in destAddr; + destAddr.sin_addr.s_addr = htonl(INADDR_ANY); + destAddr.sin_family = AF_INET; + destAddr.sin_port = htons(PORT); + addr_family = AF_INET; + ip_protocol = IPPROTO_IP; + inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); +#else // IPV6 + struct sockaddr_in6 destAddr; + bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un)); + destAddr.sin6_family = AF_INET6; + destAddr.sin6_port = htons(PORT); + addr_family = AF_INET6; + ip_protocol = IPPROTO_IPV6; + inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); +#endif + + int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); + if (listen_sock < 0) + { + os_printf("Unable to create socket: errno %d\r\n", errno); + break; + } + os_printf("Socket created"); + + int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); + if (err != 0) + { + os_printf("Socket unable to bind: errno %d\r\n", errno); + break; + } + os_printf("Socket binded"); + + err = listen(listen_sock, 1); + if (err != 0) + { + os_printf("Error occured during listen: errno %d\r\n", errno); + break; + } + os_printf("Socket listening"); + +#ifdef CONFIG_EXAMPLE_IPV6 + struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 +#else + struct sockaddr_in sourceAddr; +#endif + uint32_t addrLen = sizeof(sourceAddr); + sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); + if (sock < 0) + { + os_printf("Unable to accept connection: errno %d\r\n", errno); + break; + } + os_printf("Socket accepted"); + + while (1) + { + int len = recv(sock, rx_buffer, 2047, 0); + // Error occured during receiving + if (len < 0) + { + os_printf("recv failed: errno %d\r\n", errno); + break; + } + // Connection closed + else if (len == 0) + { + os_printf("Connection closed\r\n"); + break; + } + // Data received + else + { +#ifdef CONFIG_EXAMPLE_IPV6 + // Get the sender's ip address as string + if (sourceAddr.sin6_family == PF_INET) + { + inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + } + else if (sourceAddr.sin6_family == PF_INET6) + { + inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + } +#else + inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); +#endif + + rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string + //os_printf("Received %d bytes from %s:\r\n", len, addr_str); + // os_printf("%s", rx_buffer); + switch (state) + { + case ACCEPTING: + state = ATTACHING; + break; + + case ATTACHING: + attach(rx_buffer, len); + break; + + case EMULATING: + emulate(rx_buffer, len); + break; + } + + // int err = send(sock, rx_buffer, len, 0); + // if (err < 0) + // { + // os_printf("Error occured during sending: errno %d\r\n", errno); + // break; + // } + } + } + state = ACCEPTING; + if (sock != -1) + { + os_printf("Shutting down socket and restarting...\r\n"); + shutdown(sock, 0); + close(sock); + + shutdown(listen_sock, 0); + close(listen_sock); + vTaskDelay(5); + } + } + vTaskDelete(NULL); +} \ No newline at end of file diff --git a/main/tcp_server.h b/main/tcp_server.h new file mode 100644 index 0000000..877ab2a --- /dev/null +++ b/main/tcp_server.h @@ -0,0 +1,6 @@ +#ifndef __TCP_SERVER_H__ +#define __TCP_SERVER_H__ + +void tcp_server_task(void *pvParameters); + +#endif \ No newline at end of file diff --git a/main/timer.c b/main/timer.c new file mode 100644 index 0000000..18be76f --- /dev/null +++ b/main/timer.c @@ -0,0 +1,29 @@ +/** + * @file timer.c + * @brief Hardware timer for DAP timestamp + * @version 0.1 + * @date 2020-01-22 + * + * @copyright Copyright (c) 2020 + * + */ +#include +#include +#include "timer.h" +#include "hw_timer.h" +#include "timer_struct.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +void timer_create_task() +{ + // FRC1 frequency 80MHz + vPortEnterCritical(); + frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz + frc1.ctrl.intr_type = TIMER_EDGE_INT; + frc1.ctrl.reload = 0x01; + frc1.load.data = 0x1000000U - 1U; + frc1.ctrl.en = 0x01; + vPortExitCritical(); + vTaskDelete(NULL); +} \ No newline at end of file diff --git a/main/timer.h b/main/timer.h new file mode 100644 index 0000000..bc569a9 --- /dev/null +++ b/main/timer.h @@ -0,0 +1,6 @@ +#ifndef __TIMER_H__ +#define __TIMER_H__ + +void timer_create_task(); + +#endif \ No newline at end of file diff --git a/main/usbip_server.c b/main/usbip_server.c new file mode 100644 index 0000000..56b3b06 --- /dev/null +++ b/main/usbip_server.c @@ -0,0 +1,132 @@ +#include +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +#include "usbip_server.h" +#include "usbip_defs.h" +#include "usb_defs.h" + +static int read_stage1_command(uint8_t *buffer, uint32_t length); +static int handle_device_list(uint8_t *buffer, uint32_t length); +static int handle_device_attach(uint8_t *buffer, uint32_t length); +static void send_stage1_header(uint16_t command, uint32_t status); +static void send_device_list(); +static void send_device_info(); + + + +int attach(uint8_t *buffer, uint32_t length) +{ + uint32_t command = read_stage1_command(buffer, length); + if (command < 0) + { + return -1; + } + + switch (command) + { + case USBIP_STAGE1_CMD_DEVICE_LIST: // OP_REQ_DEVLIST + handle_device_list(buffer, length); + break; + + case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT + handle_device_attach(buffer, length); + break; + + default: + os_printf("s1 unknown command: %d\r\n", command); + break; + } +} + +static int read_stage1_command(uint8_t *buffer, uint32_t length) +{ + if (length < sizeof(usbip_stage1_header)) + { + return -1; + } + usbip_stage1_header *req = (usbip_stage1_header *)buffer; + return ntohs(req->command) & 0xFF; // 0x80xx low bit +} + +static int handle_device_list(uint8_t *buffer, uint32_t length) +{ + os_printf("Handling dev list request...\r\n"); + send_stage1_header(USBIP_STAGE1_CMD_DEVICE_LIST, 0); + send_device_list(); +} + +static int handle_device_attach(uint8_t *buffer, uint32_t length) +{ + int +} + +static void send_stage1_header(uint16_t command, uint32_t status) +{ + os_printf("Sending header...\r\n"); + usbip_stage1_header header; + header.version = htons(273); // 273??? + header.command = htons(command); + header.status = htonl(status); + + send(socket, (uint8_t *)&header, sizeof(usbip_stage1_header), 0); +} + +static void send_device_list() +{ + os_printf("Sending device list...\r\n"); + + // send device list size: + os_printf("Sending device list size...\r\n"); + usbip_stage1_response_devlist response_devlist; + + // we have only 1 device, so: + response_devlist.list_size = htonl(1); + + send(socket, (uint8_t *)&response_devlist, sizeof(usbip_stage1_response_devlist), 0); + + // may be foreach: + + { + // send device info: + send_device_info(); + // send device interfaces: // (1) + send_interface_info(); + } +} + +void send_device_info() +{ + //// TODO:fill this + os_printf("Sending device info..."); + usbip_stage1_usb_device device; + + strcpy(device.path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1"); + strcpy(device.busid, "1-1"); + + device.busnum = htonl(1); + device.devnum = htonl(2); + device.speed = htonl(2); // what is this??? + //// TODO: 0200H for USB2.0 + + //// TODO: fill Vendor Product Device-version + device.idVendor = htons(USB_DEVICE_VENDOR_ID); + device.idProduct = htons(USB_DEVICE_PRODUCT_ID); + device.bcdDevice = htons(USB_DEVICE_VERSION); + + device.bDeviceClass = 0x00; // + device.bDeviceSubClass = 0x00; + device.bDeviceProtocol = 0x00; + + device.bConfigurationValue = 1; + device.bNumConfigurations = 1; + device.bNumInterfaces = 1; + + write(&device, sizeof(usbip_stage1_usb_device)); +} + +int emulate(uint8_t *buffer, uint32_t length) +{ +} \ No newline at end of file diff --git a/main/usbip_server.h b/main/usbip_server.h new file mode 100644 index 0000000..e1c05f3 --- /dev/null +++ b/main/usbip_server.h @@ -0,0 +1,16 @@ +#ifndef __USBIP_SERVER_H__ +#define __USBIP_SERVER_H__ +#include +enum state_t +{ + ACCEPTING, + ATTACHING, + EMULATING +}; +extern uint32_t state; +extern int socket; + +int attach(uint8_t *buffer, uint32_t length); +int emulate(uint8_t *buffer, uint32_t length); + +#endif \ No newline at end of file diff --git a/main/wifi_configuration.h b/main/wifi_configuration.h new file mode 100644 index 0000000..cb2701c --- /dev/null +++ b/main/wifi_configuration.h @@ -0,0 +1,18 @@ +/** + * @file wifi_configuration.h + * @brief Fill in your wifi configuration information here. + * @version 0.1 + * @date 2020-01-22 + * + * @copyright Copyright (c) 2020 + * + */ +#ifndef __WIFI_CONFIGURATION__ +#define __WIFI_CONFIGURATION__ + +#define EXAMPLE_WIFI_SSID "DAP" +#define EXAMPLE_WIFI_PASS "12345678" + +#define PORT 22350 + +#endif \ No newline at end of file From a6a5e6ec0cb2e0833b3de101648702a8b36aef90 Mon Sep 17 00:00:00 2001 From: windowsair Date: Thu, 23 Jan 2020 21:55:51 +0800 Subject: [PATCH 04/21] feat: USBIP & Standard USB Descriptor Definitions 1. Add Standard USB Descriptor Definitions 2. USBIP stage1 completed --- components/README.md | 3 +- components/USBIP/USB_handle.c | 221 +++++++++++++++++++++++++++++++ components/USBIP/USB_handle.h | 5 + components/USBIP/USBd_config.c | 220 +++++++++++++++++++++++++++++++ components/USBIP/USBd_config.h | 41 ++++++ components/USBIP/usb_defs.h | 6 +- components/USBIP/usbip_defs.h | 2 +- main/main.c | 2 +- main/tcp_server.c | 14 +- main/usbip_server.c | 229 ++++++++++++++++++++++++++++++--- main/usbip_server.h | 2 +- 11 files changed, 713 insertions(+), 32 deletions(-) create mode 100644 components/USBIP/USB_handle.c create mode 100644 components/USBIP/USB_handle.h create mode 100644 components/USBIP/USBd_config.c create mode 100644 components/USBIP/USBd_config.h diff --git a/components/README.md b/components/README.md index 474ac22..e52e5e9 100644 --- a/components/README.md +++ b/components/README.md @@ -1,3 +1,4 @@ # TODO 1. adapt to special hardware -2. USB \ No newline at end of file +2. USB +3. Significant Bit is difficult to judge, may need to dive into the details of usbip \ No newline at end of file diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c new file mode 100644 index 0000000..8b0cd44 --- /dev/null +++ b/components/USBIP/USB_handle.c @@ -0,0 +1,221 @@ +/** + * @file USB_handle.c + * @brief Handle all Standard Device Requests + * @version 0.1 + * @date 2020-01-23 + * + * @copyright Copyright (c) 2020 + * + */ +#include +#include "USB_handle.h" + +// handle functions +static void handleGetDescriptor(usbip_stage2_header *header); +static void handle_get_device_descriptor(usbip_stage2_header *header); + +////TODO: fill this +int handleUSBControlRequest(usbip_stage2_header *header) +{ + // Table 9-3. Standard Device Requests + + switch (header->u.cmd_submit.request.bmRequestType) + { + case 0x00: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_CLEAR_FEATURE: + /* code */ + break; + case USB_REQ_SET_FEATURE: + /* code */ + break; + case USB_REQ_SET_ADDRESS: + /* code */ + break; + case USB_REQ_SET_DESCRIPTOR: + /* code */ + break; + case USB_REQ_SET_CONFIGURATION: + /* code */ + break; + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + case 0x01: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_CLEAR_FEATURE: + /* code */ + break; + case USB_REQ_SET_FEATURE: + /* code */ + break; + case USB_REQ_SET_INTERFACE: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + case 0x02: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_CLEAR_FEATURE: + /* code */ + break; + case USB_REQ_SET_FEATURE: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + + case 0x80: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_GET_CONFIGURATION: + handleGetDescriptor(header); + break; + case USB_REQ_GET_DESCRIPTOR: + /* code */ + break; + case USB_REQ_GET_STATUS: + /* code */ + break; + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + case 0x81: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_GET_INTERFACE: + /* code */ + break; + case USB_REQ_SET_SYNCH_FRAME: + /* code */ + break; + case USB_REQ_GET_STATUS: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + + case 0x82: + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_GET_STATUS: + /* code */ + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; + ///////// + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } +} + +////TODO: fill this +static void handleGetDescriptor(usbip_stage2_header *header) +{ + // 9.4.3 Get Descriptor + switch (header->u.cmd_submit.request.wValue.u8hi) + { + case USB_DT_DEVICE: + handleGetDeviceDescriptor(header); + break; + + case USB_DT_CONFIGURATION: + handleGetConfigurationDescriptor(header); + break; + + case USB_DT_STRING: + handleGetStringDescriptor(header); + break; + + case USB_DT_INTERFACE: + handleGetInterfaceDescriptor(header); + break; + + case USB_DT_ENDPOINT: + handleGetEndpointDescriptor(header); + break; + + case USB_DT_DEVICE_QUALIFIER: + handleGetDeviceQualifierDescriptor(header); + break; + + case USB_DT_OTHER_SPEED_CONFIGURATION: + os_printf("GET 0x07 [UNIMPLEMENTED] USB_DT_OTHER_SPEED_CONFIGURATION"); + break; + + case USB_DT_INTERFACE_POWER: + os_printf("GET 0x08 [UNIMPLEMENTED] USB_DT_INTERFACE_POWER"); + break; + + case USB_DT_REPORT: + handle_get_hid_report_descriptor(header); + break; + + default: + os_printf("USB unknown Get Descriptor requested:%d", header->u.cmd_submit.request.wValue.u8lo); + break; + } +} + +static void handle_get_device_descriptor(usbip_stage2_header *header) +{ + os_printf("* GET 0x01 DEVICE DESCRIPTOR\r\n"); + + usb_device_descriptor desc; + + desc.bLength = USB_DT_DEVICE_SIZE; + desc.bDescriptorType = USB_DT_DEVICE; + + desc.bcdUSB = 0x0110; + + // defined at interface level + desc.bDeviceClass = 0x0; + desc.bDeviceSubClass = 0x0; + desc.bDeviceProtocol = 0x0; + + desc.bMaxPacketSize0 = USB_HID_MAX_PACKET_SIZE; + + desc.idVendor = USB_DEVICE_VENDOR_ID; + desc.idProduct = USB_DEVICE_PRODUCT_ID; + desc.bcdDevice = USB_DEVICE_VERSION; + + desc.iManufacturer = STR_IMANUFACTURER; + desc.iProduct = STR_IPRODUCT; + desc.iSerialNumber = STR_ISERIAL; + + desc.bNumConfigurations = 1; + + send_stage2_submit_data(header, 0, &desc, sizeof(usb_device_descriptor)); +} \ No newline at end of file diff --git a/components/USBIP/USB_handle.h b/components/USBIP/USB_handle.h new file mode 100644 index 0000000..d23789d --- /dev/null +++ b/components/USBIP/USB_handle.h @@ -0,0 +1,5 @@ +#ifndef __USB_HANDLE_H__ +#define __USB_HANDLE_H__ +#include "usbip_defs.h" +int handleUSBControlRequest(usbip_stage2_header *header); +#endif \ No newline at end of file diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c new file mode 100644 index 0000000..c857de3 --- /dev/null +++ b/components/USBIP/USBd_config.c @@ -0,0 +1,220 @@ + ////TODO: refactoring into structure +/** + * @file USBd_config.c + * @brief Standard USB Descriptor Definitions + fix bugs 2020-1-23 + * @version 0.2 + * @date 2020-1-23 + * + * + */ +#include +#include +#include "USBd_config.h" +#include "usb_defs.h" +#include "USBd_config_CustomClass_0.h" + +#define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) + + +/** + * @brief step 1. Build Standard Device Descriptor + * + */ + +// Standard Device Descriptor +const uint8_t kUSBd0DeviceDescriptor[0x12] = +{ + 0x12, // bLength + USB_DT_DEVICE, // bDescriptorType (constant) + USBShort(0x0200), // bcdUSB (2.00) + + // We need to use a device other than the USB-IF standard, set to 0x00 + 0x00, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + + USBD0_MAX_PACKET0, // Maximum packet size for default pipe. + USBShort(USBD0_DEV_DESC_IDVENDOR), // Vendor ID (VID). + USBShort(USBD0_DEV_DESC_IDPRODUCT), // Product ID (PID). + USBShort(USBD0_DEV_DESC_BCDDEVICE), // Device Version BCD. + 0x01, // Index of Manufacturer string identifier. + 0x02, // Index of Product string identifier. + 0x03 * USBD0_STR_DESC_SER_EN, // Index of Product serial number. + 0x01 // Number of configurations. +}; + + + + +/** + * @brief step 2. Buid Standard Configuration Descriptor + * + */ + + +// Standard Interface Descriptor +const uint8_t kUSBd0InterfaceDescriptor[]= +{ + 0x09, // bLength + USB_DT_INTERFACE, // bDescriptorType + USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber + USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting + 0x03, // bNumEndpoints(we will use three endpoints) + // + USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass + USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass + USBD_CUSTOM_CLASS0_IF0_PROTOCOL, // bInterfaceProtocol + 0x00, // iInterface + // Index of string descriptor describing this interface + ////TODO: fix this 0x04 ? + + + // Standard Endpoint Descriptor + + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + USBD_CUSTOM_CLASS0_IF0_EP0_BENDPOINTADDRESS, // bEndpointAddress -> set 0x01 for endpoint 0 + USB_EP_ATTR_BULK, // bmAttributes -> Endpoint is a bulk endpoint. + USBShort(USBD_CUSTOM_CLASS0_IF0_EP0_HS_WMAXPACKETSIZE), + // wMaxPacketSize -> The maximum packet size: 512 bytes + // We assume that it always runs in High Speed. + USBD_CUSTOM_CLASS0_IF0_EP0_HS_BINTERVAL, // bInterval + + + // Endpoint 1: Bulk Out – used for commands received from host PC. + // Endpoint 2: Bulk In – used for responses send to host PC. + // Endpoint 3: Bulk In (optional) – used for streaming SWO trace + + // ATTENTION: + // physical endpoint 1 indeed included two "endpoints": Bulk OUT and Bulk IN + // physical endpoint 1 -> Endpoint 1 & Endpoint 2 + // physical endpoint 2 -> Endpoint 3 + + // See also : + // http://www.keil.com/pack/doc/CMSIS/DAP/html/group__DAP__ConfigUSB__gr.html + + /* Pysical endpoint 1 */ + + // "Endpoint 1: Bulk Out – used for commands received from host PC." PC -> Device + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + 0x01, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(USBD_CUSTOM_CLASS0_IF0_EP1_HS_WMAXPACKETSIZE), // wMaxPacketSize + USBD_CUSTOM_CLASS0_IF0_EP1_HS_BINTERVAL, // bInterval + + /* Pysical endpoint 1 */ + + // "Endpoint 2: Bulk In – used for responses send to host PC." Device -> PC + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + 0x81, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(USBD_CUSTOM_CLASS0_IF0_EP2_HS_WMAXPACKETSIZE), // wMaxPacketSize + USBD_CUSTOM_CLASS0_IF0_EP2_HS_BINTERVAL, // bInterval + + /* Pysical endpoint 2 */ + // "Endpoint 3: Bulk In (optional) – used for streaming SWO trace" Device -> PC + 0x07, // bLength + USB_DTYPE_ENDPOINT, // bDescriptorType + 0x82, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(USBD_CUSTOM_CLASS0_IF0_EP3_HS_WMAXPACKETSIZE), // wMaxPacketSize + USBD_CUSTOM_CLASS0_IF0_EP3_HS_BINTERVAL, // bInterval + + +}; + +// Standard Configuration Descriptor +const uint8_t kUSBd0ConfigDescriptor[] = +{ + // Configuration descriptor header. + + 0x09, // bLength -> 0x09?? may be ok... 1-23 + 0x03, // bDescriptorType + // constant, set to 0x03 + + USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (sizeof(kUSBd0ConfigDescriptor))), + // wTotalLength + + 0x01, // bNumInterfaces + // There is only one interface in the CMSIS-DAP project + 0x01, // bConfigurationValue: 0x01 is used to select this configuration */ + 0x00, // iConfiguration: no string to describe this configuration */ + USBD0_CFG_DESC_BMATTRIBUTES, // bmAttributes + + USBD0_CFG_DESC_BMAXPOWER, // bMaxPower +}; + + + +/** + * @brief step 3. Build String Descriptor + * + */ + + +const uint8_t kLangDescriptor[] = +{ + 4, + USB_DT_STRING, + USBShort(USB_LANGID_ENGLISH_US) +}; + + +/** + * @brief We will use these string descriptor: + * 1. Manufacturer string -> "KEIL - Tools By ARM" + * 2. Product string -> "LPC-Link-II" + * 3. Serial number string -> "0001A0000000" + * 4. Interface string -> "LPC-Link-II CMSIS-DAP" + * + * + */ + +const uint8_t kManufacturerString[0x28] = +{ + 0x28, // bLength + 0x03, // bDescriptorType + // "KEIL - Tools By ARM" + 'K', 0, 'E', 0, 'I', 0, 'L', 0, ' ', 0, '-', 0, ' ', 0, 'T', 0, 'o', 0, 'o', 0, + 'l', 0, 's', 0, ' ', 0, 'B', 0, 'y', 0, ' ', 0, 'A', 0, 'R', 0, 'M', 0 +}; + +const uint8_t kProductString[0x18] = +{ + 0x18, // bLength + 0x03, // bDescriptorType + // "LPC-Link-II" + 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, + 'I', 0 +}; + +const uint8_t kSerialNumberString[0x1A] = +{ + 0x1A, // bLength + 0x03, // bDescriptorType + // "0001A0000000" + '0', 0, '0', 0, '0', 0, '1', 0, 'A', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, + '0', 0, '0', 0 +}; + +const uint8_t kInterfaceString[0x2C] = +{ + 0x2C, // bLength + 0x03, // bDescriptorType + // "LPC-Link-II CMSIS-DAP" + 'L', 0, 'P', 0, 'C', 0, '-', 0, 'L', 0, 'i', 0, 'n', 0, 'k', 0, '-', 0, 'I', 0, + 'I', 0, ' ', 0, 'C', 0, 'M', 0, 'S', 0, 'I', 0, 'S', 0, '-', 0, 'D', 0, 'A', 0, + 'P', 0 +}; + +const uint8_t * const kUSBd0StringDescriptorsSet[] = +{ + kLangDescriptor, + kManufacturerString, + kProductString, + kSerialNumberString, + kInterfaceString +}; \ No newline at end of file diff --git a/components/USBIP/USBd_config.h b/components/USBIP/USBd_config.h new file mode 100644 index 0000000..88e213a --- /dev/null +++ b/components/USBIP/USBd_config.h @@ -0,0 +1,41 @@ +#ifndef __USBD_CONFIG_H__ +#define __USBD_CONFIG_H__ + +// Vendor ID assigned by USB-IF (idVendor). +#define USBD0_DEV_DESC_IDVENDOR 0xC251 +// Product ID assigned by manufacturer (idProduct). +#define USBD0_DEV_DESC_IDPRODUCT 0xF00A +// Device Release Number in binary-coded decimal (bcdDevice). +#define USBD0_DEV_DESC_BCDDEVICE 0x0100 + +// Maximum packet size for Endpoint 0 (bMaxPacketSize0). +#define USBD0_MAX_PACKET0 64 + +// If disabled Serial Number String will not be assigned to USB Device. +#define USBD0_STR_DESC_SER_EN 1 + +// bmAttributes +#define USBD0_CFG_DESC_BMATTRIBUTES 0x80 + +// bMaxPower +#define USBD0_CFG_DESC_BMAXPOWER 250 + + +// Interface Number +#define USBD_CUSTOM_CLASS0_IF0_NUM 0 + +// Alternate Setting +#define USBD_CUSTOM_CLASS0_IF0_ALT 0 + +// Class Code +#define USBD_CUSTOM_CLASS0_IF0_CLASS 0xFF // 0xFF: Vendor Specific + +// Subclass Code +#define USBD_CUSTOM_CLASS0_IF0_SUBCLASS 0x00 + +// Protocol Code +#define USBD_CUSTOM_CLASS0_IF0_PROTOCOL 0x00 + + + +#endif \ No newline at end of file diff --git a/components/USBIP/usb_defs.h b/components/USBIP/usb_defs.h index d75f317..995a97e 100644 --- a/components/USBIP/usb_defs.h +++ b/components/USBIP/usb_defs.h @@ -23,10 +23,6 @@ #define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01 - - - - union word_t { struct { uint8_t u8lo; @@ -39,7 +35,7 @@ struct usb_standard_request { uint8_t bmRequestType; uint8_t bRequest; - word_t wValue; + word_t wValue; // 16bit word_t wIndex; word_t wLength; } __attribute__((packed)); diff --git a/components/USBIP/usbip_defs.h b/components/USBIP/usbip_defs.h index 943989a..eb3935c 100644 --- a/components/USBIP/usbip_defs.h +++ b/components/USBIP/usbip_defs.h @@ -165,7 +165,7 @@ struct usbip_stage2_header_cmd_submit { */ struct usbip_stage2_header_ret_submit { int32_t status; - int32_t data_length; + int32_t data_length;//actual_length int32_t start_frame; int32_t number_of_packets; int32_t error_count; diff --git a/main/main.c b/main/main.c index ea82251..03f5354 100644 --- a/main/main.c +++ b/main/main.c @@ -122,7 +122,7 @@ static void wait_for_ip() os_printf("Waiting for AP connection...\r\n"); xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - os_printf("Connected to AP"); + os_printf("Connected to AP\r\n"); } diff --git a/main/tcp_server.c b/main/tcp_server.c index f28213b..7e6f870 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -30,7 +30,7 @@ #include "usbip_server.h" uint8_t state = ACCEPTING; -int sock = -1; +int kSock = -1; void tcp_server_task(void *pvParameters) { char rx_buffer[2048]; @@ -89,8 +89,8 @@ void tcp_server_task(void *pvParameters) struct sockaddr_in sourceAddr; #endif uint32_t addrLen = sizeof(sourceAddr); - sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); - if (sock < 0) + kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); + if (kSock < 0) { os_printf("Unable to accept connection: errno %d\r\n", errno); break; @@ -99,7 +99,7 @@ void tcp_server_task(void *pvParameters) while (1) { - int len = recv(sock, rx_buffer, 2047, 0); + int len = recv(kSock, rx_buffer, 2047, 0); // Error occured during receiving if (len < 0) { @@ -156,11 +156,11 @@ void tcp_server_task(void *pvParameters) } } state = ACCEPTING; - if (sock != -1) + if (kSock != -1) { os_printf("Shutting down socket and restarting...\r\n"); - shutdown(sock, 0); - close(sock); + shutdown(kSock, 0); + close(kSock); shutdown(listen_sock, 0); close(listen_sock); diff --git a/main/usbip_server.c b/main/usbip_server.c index 56b3b06..38faf78 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -8,18 +8,25 @@ #include "usbip_defs.h" #include "usb_defs.h" +// attach helper function static int read_stage1_command(uint8_t *buffer, uint32_t length); static int handle_device_list(uint8_t *buffer, uint32_t length); static int handle_device_attach(uint8_t *buffer, uint32_t length); static void send_stage1_header(uint16_t command, uint32_t status); static void send_device_list(); static void send_device_info(); +static void send_interface_info(); - +// emulate helper function +static void pack(void *data, int size); +static void unpack(void *data, int size); +static int handle_submit(usbip_stage2_header *header); +static int handle_control_request(usbip_stage2_header *header); +static void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length); int attach(uint8_t *buffer, uint32_t length) { - uint32_t command = read_stage1_command(buffer, length); + int command = read_stage1_command(buffer, length); if (command < 0) { return -1; @@ -31,12 +38,12 @@ int attach(uint8_t *buffer, uint32_t length) handle_device_list(buffer, length); break; - case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT - handle_device_attach(buffer, length); + case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT + handle_device_attach(buffer, length); ////TODO: fill this break; default: - os_printf("s1 unknown command: %d\r\n", command); + os_printf("attach Unknown command: %d\r\n", command); break; } } @@ -48,7 +55,7 @@ static int read_stage1_command(uint8_t *buffer, uint32_t length) return -1; } usbip_stage1_header *req = (usbip_stage1_header *)buffer; - return ntohs(req->command) & 0xFF; // 0x80xx low bit + return (ntohs(req->command) & 0xFF); // 0x80xx low bit } static int handle_device_list(uint8_t *buffer, uint32_t length) @@ -60,18 +67,33 @@ static int handle_device_list(uint8_t *buffer, uint32_t length) static int handle_device_attach(uint8_t *buffer, uint32_t length) { - int + os_printf("Handling dev attach request...\r\n"); + + //char bus[USBIP_BUSID_SIZE]; + if (length < sizeof(USBIP_BUSID_SIZE)) + { + return -1; + } + //client.readBytes((uint8_t *)bus, USBIP_BUSID_SIZE); + + send_stage1_header(USBIP_STAGE1_CMD_DEVICE_ATTACH, 0); + + send_device_info(); + + state = EMULATING; } static void send_stage1_header(uint16_t command, uint32_t status) { os_printf("Sending header...\r\n"); usbip_stage1_header header; - header.version = htons(273); // 273??? + header.version = htons(273); ////TODO: 273??? + // may be : https://github.com/Oxalin/usbip_windows/issues/4 + header.command = htons(command); header.status = htonl(status); - send(socket, (uint8_t *)&header, sizeof(usbip_stage1_header), 0); + send(kSock, (uint8_t *)&header, sizeof(usbip_stage1_header), 0); } static void send_device_list() @@ -97,7 +119,7 @@ static void send_device_list() } } -void send_device_info() +static void send_device_info() { //// TODO:fill this os_printf("Sending device info..."); @@ -111,12 +133,11 @@ void send_device_info() device.speed = htonl(2); // what is this??? //// TODO: 0200H for USB2.0 - //// TODO: fill Vendor Product Device-version - device.idVendor = htons(USB_DEVICE_VENDOR_ID); - device.idProduct = htons(USB_DEVICE_PRODUCT_ID); - device.bcdDevice = htons(USB_DEVICE_VERSION); + device.idVendor = htons(USBD0_DEV_DESC_IDVENDOR); + device.idProduct = htons(USBD0_DEV_DESC_IDPRODUCT); + device.bcdDevice = htons(USBD0_DEV_DESC_BCDDEVICE); - device.bDeviceClass = 0x00; // + device.bDeviceClass = 0x00; // We need to use a device other than the USB-IF standard, set to 0x00 device.bDeviceSubClass = 0x00; device.bDeviceProtocol = 0x00; @@ -124,9 +145,185 @@ void send_device_info() device.bNumConfigurations = 1; device.bNumInterfaces = 1; - write(&device, sizeof(usbip_stage1_usb_device)); + send(kSock, (uint8_t *)&device, sizeof(usbip_stage1_usb_device), 0); } +static void send_interface_info() +{ + os_printf("Sending interface info...\r\n"); + usbip_stage1_usb_interface interface; + interface.bInterfaceClass = USBD_CUSTOM_CLASS0_IF0_CLASS; + interface.bInterfaceSubClass = USBD_CUSTOM_CLASS0_IF0_SUBCLASS; + interface.bInterfaceProtocol = USBD_CUSTOM_CLASS0_IF0_PROTOCOL; + interface.padding = 0; // shall be set to zero + + send(kSock, (uint8_t *)&interface, sizeof(usbip_stage1_usb_interface), 0); +} + +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////// + int emulate(uint8_t *buffer, uint32_t length) { + // usbip_stage2_header header; + int command = read_stage2_command((usbip_stage2_header *)buffer); ////TODO: fill this + if (command < 0) + { + return -1; + } + + switch (command) + { + case USBIP_STAGE2_REQ_SUBMIT: + handle_submit((usbip_stage2_header *)buffer); + break; + + case USBIP_STAGE2_REQ_UNLINK: + handle_unlink((usbip_stage2_header *)buffer); + break; + + default: + os_printf("emulate unknown command:%d\r\n", command); + return -1; + } + return 0; +} + +int read_stage2_command(usbip_stage2_header *header, uint32_t length) +{ + if (length < sizeof(usbip_stage2_header)) + { + return -1; + } + + //client.readBytes((uint8_t *)&header, sizeof(usbip_stage2_header)); + unpack((uint32_t *)&header, sizeof(usbip_stage2_header)); + return header->base.command; +} + +/** + * @brief Pack the following packets(Offset 0x00 - 0x28): + * - cmd_submit + * - ret_submit + * - cmd_unlink + * - ret_unlink + * + * @param data Point to packets header + * @param size Packets header size + */ +static void pack(void *data, int size) +{ + + // Ignore the setup field + int size = (size / sizeof(uint32_t)) - 2; + uint32_t *ptr = (uint32_t *)data; + + for (int i = 0; i < size; i++) + { + + ptr[i] = htonl(ptr[i]); + } +} + +/** + * @brief Unack the following packets(Offset 0x00 - 0x28): + * - cmd_submit + * - ret_submit + * - cmd_unlink + * - ret_unlink + * + * @param data Point to packets header + * @param size packets header size + */ +static void unpack(void *data, int size) +{ + + // Ignore the setup field + int size = (size / sizeof(uint32_t)) - 2; + uint32_t *ptr = (uint32_t *)data; + + for (int i = 0; i < size; i++) + { + ptr[i] = ntohl(ptr[i]); + } +} + +////TODO: fill this +/** + * @brief + * + */ +static int handle_submit(usbip_stage2_header *header) +{ + switch (header->base.ep) + { + // control endpoint(endpoint 0) + case 0x00: + handle_control_request(header); + break; + + // data + case 0x01: + if (header->base.direction == 0) + { + // Serial.println("EP 01 DATA FROM HOST"); + handle_data_request(header); + } + else + { + // Serial.println("EP 01 DATA TO HOST"); + handle_data_response(header); + } + break; + + // request to save data to device + case 0x81: + if (header->base.direction == 0) + { + os_printf("*** WARN! EP 81 DATA TX"); + } + else + { + os_printf("*** WARN! EP 81 DATA RX"); + } + return -1; + + default: + os_printf("*** WARN ! UNKNOWN ENDPOINT: "); + os_printf((int)header.base.ep); + return -1; + } + return 0; +} + +static void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length) +{ + + req_header->base.command = USBIP_STAGE2_RSP_SUBMIT; + req_header->base.direction = !req_header->base.direction; + + memset(&req_header->u.ret_submit, 0, sizeof(usbip_stage2_header_ret_submit)); + + req_header->u.ret_submit.status = status; + req_header->u.ret_submit.data_length = data_length; + + pack(&req_header, sizeof(usbip_stage2_header)); + send(kSock, req_header, sizeof(usbip_stage2_header), 0); +} + +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, void *data, int32_t data_length) +{ + + send_stage2_submit(req_header, status, data_length); + + if (data_length) + { + send(kSock, data, data_length, 0); + } } \ No newline at end of file diff --git a/main/usbip_server.h b/main/usbip_server.h index e1c05f3..c085c28 100644 --- a/main/usbip_server.h +++ b/main/usbip_server.h @@ -8,7 +8,7 @@ enum state_t EMULATING }; extern uint32_t state; -extern int socket; +extern int kSock; int attach(uint8_t *buffer, uint32_t length); int emulate(uint8_t *buffer, uint32_t length); From 957cc01656335450f46b72f3b7ad2d3263ce4885 Mon Sep 17 00:00:00 2001 From: windowsair Date: Fri, 24 Jan 2020 16:41:15 +0800 Subject: [PATCH 05/21] fix: C-style structure definition & other details improvements --- components/USBIP/USB_handle.c | 106 +++++++++------- components/USBIP/USBd_config.c | 47 +++----- components/USBIP/USBd_config.h | 13 ++ components/USBIP/usb_defs.h | 214 +++++++++++++++------------------ components/USBIP/usbip_defs.h | 117 ++++++++---------- main/usbip_server.c | 8 +- main/usbip_server.h | 3 + 7 files changed, 248 insertions(+), 260 deletions(-) diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index 8b0cd44..56207a2 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -8,14 +8,21 @@ * */ #include +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include #include "USB_handle.h" +#include "USBd_config.h" +#include "usbip_server.h" +#include "usb_defs.h" + // handle functions -static void handleGetDescriptor(usbip_stage2_header *header); -static void handle_get_device_descriptor(usbip_stage2_header *header); +static void handleGetDescriptor(struct usbip_stage2_header *header); ////TODO: fill this -int handleUSBControlRequest(usbip_stage2_header *header) +int handleUSBControlRequest(struct usbip_stage2_header *header) { // Table 9-3. Standard Device Requests @@ -142,80 +149,87 @@ int handleUSBControlRequest(usbip_stage2_header *header) } ////TODO: fill this -static void handleGetDescriptor(usbip_stage2_header *header) +static void handleGetDescriptor(struct usbip_stage2_header *header) { // 9.4.3 Get Descriptor switch (header->u.cmd_submit.request.wValue.u8hi) { - case USB_DT_DEVICE: - handleGetDeviceDescriptor(header); + case USB_DT_DEVICE: // get device descriptor + os_printf("* GET 0x01 DEVICE DESCRIPTOR\r\n"); + send_stage2_submit_data(header, 0, kUSBd0DeviceDescriptor, sizeof(kUSBd0DeviceDescriptor)); break; - case USB_DT_CONFIGURATION: - handleGetConfigurationDescriptor(header); + case USB_DT_CONFIGURATION: // get configuration descriptor + os_printf("* GET 0x02 CONFIGURATION DESCRIPTOR\r\n"); + ////TODO: ? + if (header->u.cmd_submit.data_length == USB_DT_CONFIGURATION_SIZE) + { + os_printf("Sending only first part of CONFIG\r\n"); + + send_stage2_submit(header, 0, header->u.cmd_submit.data_length); + send(kSock, kUSBd0ConfigDescriptor, sizeof(kUSBd0ConfigDescriptor), 0); + + } + else + { + os_printf("Sending ALL CONFIG\r\n"); + + send_stage2_submit(header, 0, header->u.cmd_submit.data_length); + send(kSock, kUSBd0ConfigDescriptor, sizeof(kUSBd0ConfigDescriptor), 0); + send(kSock, kUSBd0InterfaceDescriptor, sizeof(kUSBd0InterfaceDescriptor), 0); + + } break; case USB_DT_STRING: - handleGetStringDescriptor(header); + os_printf("* GET 0x03 STRING DESCRIPTOR\r\n"); + + if (header->u.cmd_submit.request.wValue.u8lo == 0) { + os_printf("** REQUESTED list of supported languages\r\n"); + send_stage2_submit_data(header, 0, kLangDescriptor, sizeof(kLangDescriptor)); + } + else{ + os_printf("***Unsupported operation***\r\n"); + } break; case USB_DT_INTERFACE: - handleGetInterfaceDescriptor(header); + os_printf("* GET 0x04 INTERFACE DESCRIPTOR (UNIMPLEMENTED)\r\n"); + ////TODO:UNIMPLEMENTED + send_stage2_submit(header, 0, 0); break; case USB_DT_ENDPOINT: - handleGetEndpointDescriptor(header); + os_printf("* GET 0x05 ENDPOINT DESCRIPTOR (UNIMPLEMENTED)\r\n"); + ////TODO:UNIMPLEMENTED + send_stage2_submit(header, 0, 0); break; case USB_DT_DEVICE_QUALIFIER: - handleGetDeviceQualifierDescriptor(header); + os_printf("* GET 0x06 DEVICE QUALIFIER DESCRIPTOR"); + + usb_device_qualifier_descriptor desc; + + memset(&desc, 0, sizeof(usb_device_qualifier_descriptor)); + + send_stage2_submit_data(header, 0, &desc, sizeof(usb_device_qualifier_descriptor)); break; case USB_DT_OTHER_SPEED_CONFIGURATION: os_printf("GET 0x07 [UNIMPLEMENTED] USB_DT_OTHER_SPEED_CONFIGURATION"); + ////TODO:UNIMPLEMENTED + send_stage2_submit(header, 0, 0); break; case USB_DT_INTERFACE_POWER: os_printf("GET 0x08 [UNIMPLEMENTED] USB_DT_INTERFACE_POWER"); + ////TODO:UNIMPLEMENTED + send_stage2_submit(header, 0, 0); break; - case USB_DT_REPORT: - handle_get_hid_report_descriptor(header); - break; default: os_printf("USB unknown Get Descriptor requested:%d", header->u.cmd_submit.request.wValue.u8lo); break; } } - -static void handle_get_device_descriptor(usbip_stage2_header *header) -{ - os_printf("* GET 0x01 DEVICE DESCRIPTOR\r\n"); - - usb_device_descriptor desc; - - desc.bLength = USB_DT_DEVICE_SIZE; - desc.bDescriptorType = USB_DT_DEVICE; - - desc.bcdUSB = 0x0110; - - // defined at interface level - desc.bDeviceClass = 0x0; - desc.bDeviceSubClass = 0x0; - desc.bDeviceProtocol = 0x0; - - desc.bMaxPacketSize0 = USB_HID_MAX_PACKET_SIZE; - - desc.idVendor = USB_DEVICE_VENDOR_ID; - desc.idProduct = USB_DEVICE_PRODUCT_ID; - desc.bcdDevice = USB_DEVICE_VERSION; - - desc.iManufacturer = STR_IMANUFACTURER; - desc.iProduct = STR_IPRODUCT; - desc.iSerialNumber = STR_ISERIAL; - - desc.bNumConfigurations = 1; - - send_stage2_submit_data(header, 0, &desc, sizeof(usb_device_descriptor)); -} \ No newline at end of file diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c index c857de3..e0f57ab 100644 --- a/components/USBIP/USBd_config.c +++ b/components/USBIP/USBd_config.c @@ -12,7 +12,6 @@ #include #include "USBd_config.h" #include "usb_defs.h" -#include "USBd_config_CustomClass_0.h" #define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) @@ -54,7 +53,7 @@ const uint8_t kUSBd0DeviceDescriptor[0x12] = // Standard Interface Descriptor -const uint8_t kUSBd0InterfaceDescriptor[]= +const uint8_t kUSBd0InterfaceDescriptor[0x1E]= { 0x09, // bLength USB_DT_INTERFACE, // bDescriptorType @@ -72,16 +71,6 @@ const uint8_t kUSBd0InterfaceDescriptor[]= // Standard Endpoint Descriptor - 0x07, // bLength - USB_DTYPE_ENDPOINT, // bDescriptorType - USBD_CUSTOM_CLASS0_IF0_EP0_BENDPOINTADDRESS, // bEndpointAddress -> set 0x01 for endpoint 0 - USB_EP_ATTR_BULK, // bmAttributes -> Endpoint is a bulk endpoint. - USBShort(USBD_CUSTOM_CLASS0_IF0_EP0_HS_WMAXPACKETSIZE), - // wMaxPacketSize -> The maximum packet size: 512 bytes - // We assume that it always runs in High Speed. - USBD_CUSTOM_CLASS0_IF0_EP0_HS_BINTERVAL, // bInterval - - // Endpoint 1: Bulk Out – used for commands received from host PC. // Endpoint 2: Bulk In – used for responses send to host PC. // Endpoint 3: Bulk In (optional) – used for streaming SWO trace @@ -98,36 +87,38 @@ const uint8_t kUSBd0InterfaceDescriptor[]= // "Endpoint 1: Bulk Out – used for commands received from host PC." PC -> Device 0x07, // bLength - USB_DTYPE_ENDPOINT, // bDescriptorType + USB_DT_ENDPOINT, // bDescriptorType 0x01, // bEndpointAddress - USB_ENDPOINT_ATTR_BULK, // bmAttributes - USBShort(USBD_CUSTOM_CLASS0_IF0_EP1_HS_WMAXPACKETSIZE), // wMaxPacketSize - USBD_CUSTOM_CLASS0_IF0_EP1_HS_BINTERVAL, // bInterval + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(512), // wMaxPacketSize + // We assume that it always runs in High Speed. + 0x00, // bInterval /* Pysical endpoint 1 */ // "Endpoint 2: Bulk In – used for responses send to host PC." Device -> PC 0x07, // bLength - USB_DTYPE_ENDPOINT, // bDescriptorType + USB_DT_ENDPOINT, // bDescriptorType 0x81, // bEndpointAddress - USB_ENDPOINT_ATTR_BULK, // bmAttributes - USBShort(USBD_CUSTOM_CLASS0_IF0_EP2_HS_WMAXPACKETSIZE), // wMaxPacketSize - USBD_CUSTOM_CLASS0_IF0_EP2_HS_BINTERVAL, // bInterval + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(512), // wMaxPacketSize + 0x00, // bInterval /* Pysical endpoint 2 */ // "Endpoint 3: Bulk In (optional) – used for streaming SWO trace" Device -> PC 0x07, // bLength - USB_DTYPE_ENDPOINT, // bDescriptorType + USB_DT_ENDPOINT, // bDescriptorType 0x82, // bEndpointAddress - USB_ENDPOINT_ATTR_BULK, // bmAttributes - USBShort(USBD_CUSTOM_CLASS0_IF0_EP3_HS_WMAXPACKETSIZE), // wMaxPacketSize - USBD_CUSTOM_CLASS0_IF0_EP3_HS_BINTERVAL, // bInterval + USB_ENDPOINT_ATTR_BULK, // bmAttributes + USBShort(512), // wMaxPacketSize + 0x00, // bInterval }; // Standard Configuration Descriptor -const uint8_t kUSBd0ConfigDescriptor[] = +#define LENGTHOFCONFIGDESCRIPTOR 9 +const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = { // Configuration descriptor header. @@ -135,7 +126,7 @@ const uint8_t kUSBd0ConfigDescriptor[] = 0x03, // bDescriptorType // constant, set to 0x03 - USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (sizeof(kUSBd0ConfigDescriptor))), + USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (LENGTHOFCONFIGDESCRIPTOR)), // wTotalLength 0x01, // bNumInterfaces @@ -155,7 +146,7 @@ const uint8_t kUSBd0ConfigDescriptor[] = */ -const uint8_t kLangDescriptor[] = +const uint8_t kLangDescriptor[0x04] = { 4, USB_DT_STRING, @@ -210,7 +201,7 @@ const uint8_t kInterfaceString[0x2C] = 'P', 0 }; -const uint8_t * const kUSBd0StringDescriptorsSet[] = +const uint8_t * const kUSBd0StringDescriptorsSet[0x05] = { kLangDescriptor, kManufacturerString, diff --git a/components/USBIP/USBd_config.h b/components/USBIP/USBd_config.h index 88e213a..6af8944 100644 --- a/components/USBIP/USBd_config.h +++ b/components/USBIP/USBd_config.h @@ -38,4 +38,17 @@ + + +///////////////////////////////////////////// +extern const uint8_t kUSBd0DeviceDescriptor[0x12]; +extern const uint8_t kUSBd0InterfaceDescriptor[0x1E]; +extern const uint8_t kUSBd0ConfigDescriptor[0x09]; +extern const uint8_t kLangDescriptor[0x04]; +extern const uint8_t kManufacturerString[0x28]; +extern const uint8_t kProductString[0x18]; +extern const uint8_t kSerialNumberString[0x1A]; +extern const uint8_t kInterfaceString[0x2C]; + + #endif \ No newline at end of file diff --git a/components/USBIP/usb_defs.h b/components/USBIP/usb_defs.h index 995a97e..31898da 100644 --- a/components/USBIP/usb_defs.h +++ b/components/USBIP/usb_defs.h @@ -17,37 +17,32 @@ #include - -#define USB_CLASS_MISCELLANEOUS_DEVICE 0xef -#define USB_MISC_SUBCLASS_COMMON 0x02 +#define USB_CLASS_MISCELLANEOUS_DEVICE 0xef +#define USB_MISC_SUBCLASS_COMMON 0x02 #define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01 - -union word_t { - struct { +typedef union { + struct + { uint8_t u8lo; uint8_t u8hi; } __attribute__((packed)); uint16_t u16; -}; +} word_t; -struct usb_standard_request +typedef struct { - uint8_t bmRequestType; - uint8_t bRequest; + uint8_t bmRequestType; + uint8_t bRequest; word_t wValue; // 16bit word_t wIndex; word_t wLength; -} __attribute__((packed)); - - - - +} __attribute__((packed)) usb_standard_request; //#define USB_CLASS_HID 3 -#define USB_DT_HID 0x21 -#define USB_DT_REPORT 0x22 +#define USB_DT_HID 0x21 +#define USB_DT_REPORT 0x22 //struct usb_hid_descriptor { // uint8_t bLength; @@ -63,84 +58,79 @@ struct usb_standard_request // uint16_t wReportLength; //} __attribute__((packed)); - #define USB_DT_REPORT_SIZE sizeof(struct usb_hid_report_descriptor) - /* Class Definition */ -#define USB_CLASS_VENDOR 0xFF +#define USB_CLASS_VENDOR 0xFF /////////////////////////////////////////////////////////////// /* Table 9-2. Format of Setup Data */ /* bmRequestType bit definitions */ /* bit 7 : Direction */ -#define USB_REQ_TYPE_OUT 0x00 // Host-to-device -#define USB_REQ_TYPE_IN 0x80 // Device-to-host +#define USB_REQ_TYPE_OUT 0x00 // Host-to-device +#define USB_REQ_TYPE_IN 0x80 // Device-to-host /* bits 6..5 : Type */ -#define USB_REQ_TYPE_STANDARD 0x00 -#define USB_REQ_TYPE_CLASS 0x20 -#define USB_REQ_TYPE_VENDOR 0x40 -#define USB_REQ_TYPE_RESERVED 0x60 +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +#define USB_REQ_TYPE_RESERVED 0x60 /* bits 4..0 : Recipient */ -#define USB_REQ_TYPE_DEVICE 0x00 -#define USB_REQ_TYPE_INTERFACE 0x01 -#define USB_REQ_TYPE_ENDPOINT 0x02 -#define USB_REQ_TYPE_OTHER 0x03 -#define USB_REQ_TYPE_RESERVED 0x1F +#define USB_REQ_TYPE_DEVICE 0x00 +#define USB_REQ_TYPE_INTERFACE 0x01 +#define USB_REQ_TYPE_ENDPOINT 0x02 +#define USB_REQ_TYPE_OTHER 0x03 +#define USB_REQ_TYPE_RESERVED 0x1F /////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////// /* USB Standard Request Codes - Table 9-4 */ -#define USB_REQ_GET_STATUS 0 -#define USB_REQ_CLEAR_FEATURE 1 +#define USB_REQ_GET_STATUS 0 +#define USB_REQ_CLEAR_FEATURE 1 /* Reserved for future use: 2 */ -#define USB_REQ_SET_FEATURE 3 +#define USB_REQ_SET_FEATURE 3 /* Reserved for future use: 3 */ -#define USB_REQ_SET_ADDRESS 5 -#define USB_REQ_GET_DESCRIPTOR 6 -#define USB_REQ_SET_DESCRIPTOR 7 -#define USB_REQ_GET_CONFIGURATION 8 -#define USB_REQ_SET_CONFIGURATION 9 -#define USB_REQ_GET_INTERFACE 10 -#define USB_REQ_SET_INTERFACE 11 -#define USB_REQ_SET_SYNCH_FRAME 12 +#define USB_REQ_SET_ADDRESS 5 +#define USB_REQ_GET_DESCRIPTOR 6 +#define USB_REQ_SET_DESCRIPTOR 7 +#define USB_REQ_GET_CONFIGURATION 8 +#define USB_REQ_SET_CONFIGURATION 9 +#define USB_REQ_GET_INTERFACE 10 +#define USB_REQ_SET_INTERFACE 11 +#define USB_REQ_SET_SYNCH_FRAME 12 /////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////// /* USB Descriptor Types - Table 9-5 */ -#define USB_DT_DEVICE 1 -#define USB_DT_CONFIGURATION 2 -#define USB_DT_STRING 3 -#define USB_DT_INTERFACE 4 -#define USB_DT_ENDPOINT 5 -#define USB_DT_DEVICE_QUALIFIER 6 -#define USB_DT_OTHER_SPEED_CONFIGURATION 7 -#define USB_DT_INTERFACE_POWER 8 +#define USB_DT_DEVICE 1 +#define USB_DT_CONFIGURATION 2 +#define USB_DT_STRING 3 +#define USB_DT_INTERFACE 4 +#define USB_DT_ENDPOINT 5 +#define USB_DT_DEVICE_QUALIFIER 6 +#define USB_DT_OTHER_SPEED_CONFIGURATION 7 +#define USB_DT_INTERFACE_POWER 8 /* From ECNs */ -#define USB_DT_OTG 9 -#define USB_DT_DEBUG 10 -#define USB_DT_INTERFACE_ASSOCIATION 11 +#define USB_DT_OTG 9 +#define USB_DT_DEBUG 10 +#define USB_DT_INTERFACE_ASSOCIATION 11 /////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////// /* USB Standard Feature Selectors - Table 9-6 */ -#define USB_FEAT_ENDPOINT_HALT 0 // Recipient: Device -#define USB_FEAT_DEVICE_REMOTE_WAKEUP 1 // Recipient: Endpoint -#define USB_FEAT_TEST_MODE 2 // Recipient: Device +#define USB_FEAT_ENDPOINT_HALT 0 // Recipient: Device +#define USB_FEAT_DEVICE_REMOTE_WAKEUP 1 // Recipient: Endpoint +#define USB_FEAT_TEST_MODE 2 // Recipient: Device /* Information Returned by a GetStatus() Request to a Device - Figure 9-4 */ -#define USB_DEV_STATUS_SELF_POWERED 0x01 -#define USB_DEV_STATUS_REMOTE_WAKEUP 0x02 +#define USB_DEV_STATUS_SELF_POWERED 0x01 +#define USB_DEV_STATUS_REMOTE_WAKEUP 0x02 /////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////// /* USB Standard Device Descriptor - Table 9-8 */ -struct usb_device_descriptor { +typedef struct +{ uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; @@ -155,17 +145,16 @@ struct usb_device_descriptor { uint8_t iProduct; uint8_t iSerialNumber; uint8_t bNumConfigurations; -} __attribute__((packed)); -#define USB_DT_DEVICE_SIZE sizeof(struct usb_device_descriptor) +} __attribute__((packed)) usb_device_descriptor; +#define USB_DT_DEVICE_SIZE sizeof(usb_device_descriptor) /////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////// /* USB Device_Qualifier Descriptor - Table 9-9 * Not used in this implementation. */ -struct usb_device_qualifier_descriptor { +typedef struct +{ uint8_t bLength; uint8_t bDescriptorType; uint16_t bcdUSB; @@ -175,25 +164,24 @@ struct usb_device_qualifier_descriptor { uint8_t bMaxPacketSize0; uint8_t bNumConfigurations; uint8_t bReserved; -} __attribute__((packed)); +} __attribute__((packed)) usb_device_qualifier_descriptor; /////////////////////////////////////////////////////////////// - /* This is only defined as a top level named struct to improve c++ * compatibility. You should never need to instance this struct * in user code! */ -struct usb_interface { +typedef struct +{ uint8_t *cur_altsetting; uint8_t num_altsetting; const struct usb_iface_assoc_descriptor *iface_assoc; const struct usb_interface_descriptor *altsetting; -}; - - +} __attribute__((packed)) usb_interface; /////////////////////////////////////////////////////////////// /* USB Standard Configuration Descriptor - Table 9-10 */ -struct usb_config_descriptor { +typedef struct +{ uint8_t bLength; uint8_t bDescriptorType; uint16_t wTotalLength; @@ -202,25 +190,23 @@ struct usb_config_descriptor { uint8_t iConfiguration; uint8_t bmAttributes; uint8_t bMaxPower; -} __attribute__((packed)); -#define USB_DT_CONFIGURATION_SIZE sizeof(struct usb_config_descriptor) +} __attribute__((packed)) usb_config_descriptor; +#define USB_DT_CONFIGURATION_SIZE sizeof(usb_config_descriptor) /////////////////////////////////////////////////////////////// - - /* USB Configuration Descriptor *bmAttributes* bit definitions */ -#define USB_CONFIG_ATTR_DEFAULT 0x80 /** always required (USB2.0 table 9-10) */ -#define USB_CONFIG_ATTR_SELF_POWERED 0x40 -#define USB_CONFIG_ATTR_REMOTE_WAKEUP 0x20 +#define USB_CONFIG_ATTR_DEFAULT 0x80 /** always required (USB2.0 table 9-10) */ +#define USB_CONFIG_ATTR_SELF_POWERED 0x40 +#define USB_CONFIG_ATTR_REMOTE_WAKEUP 0x20 /* Other Speed Configuration is the same as Configuration Descriptor. * - Table 9-11 */ - /////////////////////////////////////////////////////////////// /* USB Standard Interface Descriptor - Table 9-12 */ -struct usb_interface_descriptor { +typedef struct +{ uint8_t bLength; uint8_t bDescriptorType; uint8_t bInterfaceNumber; @@ -230,15 +216,14 @@ struct usb_interface_descriptor { uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; uint8_t iInterface; -} __attribute__((packed)); -#define USB_DT_INTERFACE_SIZE sizeof(struct usb_interface_descriptor) +} __attribute__((packed)) usb_interface_descriptor; +#define USB_DT_INTERFACE_SIZE sizeof(usb_interface_descriptor) /////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////// /* USB Standard Endpoint Descriptor - Table 9-13 */ -struct usb_endpoint_descriptor { +typedef struct usb_endpoint_descriptor +{ uint8_t bLength; uint8_t bDescriptorType; uint8_t bEndpointAddress; @@ -246,52 +231,50 @@ struct usb_endpoint_descriptor { uint16_t wMaxPacketSize; uint8_t bInterval; } __attribute__((packed)); -#define USB_DT_ENDPOINT_SIZE sizeof(struct usb_endpoint_descriptor) +#define USB_DT_ENDPOINT_SIZE sizeof(usb_endpoint_descriptor) /////////////////////////////////////////////////////////////// - /* USB bEndpointAddress helper macros */ #define USB_ENDPOINT_ADDR_OUT(x) (x) #define USB_ENDPOINT_ADDR_IN(x) (0x80 | (x)) - /////////////////////////////////////////////////////////////// /* USB Endpoint Descriptor bmAttributes bit definitions - Table 9-13 */ /* bits 1..0 : Transfer type */ -#define USB_ENDPOINT_ATTR_CONTROL 0x00 -#define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01 -#define USB_ENDPOINT_ATTR_BULK 0x02 -#define USB_ENDPOINT_ATTR_INTERRUPT 0x03 -#define USB_ENDPOINT_ATTR_TYPE 0x03 +#define USB_ENDPOINT_ATTR_CONTROL 0x00 +#define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_ATTR_BULK 0x02 +#define USB_ENDPOINT_ATTR_INTERRUPT 0x03 +#define USB_ENDPOINT_ATTR_TYPE 0x03 // If not an isochronous endpoint, bits 5..2 are reserved // and must be set to zero. /* bits 3..2 : Sync type (only if ISOCHRONOUS) */ -#define USB_ENDPOINT_ATTR_NOSYNC 0x00 -#define USB_ENDPOINT_ATTR_ASYNC 0x04 -#define USB_ENDPOINT_ATTR_ADAPTIVE 0x08 -#define USB_ENDPOINT_ATTR_SYNC 0x0C -#define USB_ENDPOINT_ATTR_SYNCTYPE 0x0C +#define USB_ENDPOINT_ATTR_NOSYNC 0x00 +#define USB_ENDPOINT_ATTR_ASYNC 0x04 +#define USB_ENDPOINT_ATTR_ADAPTIVE 0x08 +#define USB_ENDPOINT_ATTR_SYNC 0x0C +#define USB_ENDPOINT_ATTR_SYNCTYPE 0x0C /* bits 5..4 : Usage type (only if ISOCHRONOUS) */ -#define USB_ENDPOINT_ATTR_DATA 0x00 -#define USB_ENDPOINT_ATTR_FEEDBACK 0x10 +#define USB_ENDPOINT_ATTR_DATA 0x00 +#define USB_ENDPOINT_ATTR_FEEDBACK 0x10 #define USB_ENDPOINT_ATTR_IMPLICIT_FEEDBACK_DATA 0x20 -#define USB_ENDPOINT_ATTR_USAGETYPE 0x30 +#define USB_ENDPOINT_ATTR_USAGETYPE 0x30 /////////////////////////////////////////////////////////////// - - /////////////////////////////////////////////////////////////// /* Table 9-15 specifies String Descriptor Zero. * Table 9-16 specified UNICODE String Descriptor. */ -struct usb_string_descriptor { +typedef struct +{ uint8_t bLength; uint8_t bDescriptorType; uint16_t wData[]; -} __attribute__((packed)); +} __attribute__((packed)) usb_string_descriptor; /* From ECN: Interface Association Descriptors, Table 9-Z */ -struct usb_iface_assoc_descriptor { +typedef struct +{ uint8_t bLength; uint8_t bDescriptorType; uint8_t bFirstInterface; @@ -300,17 +283,14 @@ struct usb_iface_assoc_descriptor { uint8_t bFunctionSubClass; uint8_t bFunctionProtocol; uint8_t iFunction; -} __attribute__((packed)); +} __attribute__((packed)) usb_iface_assoc_descriptor; #define USB_DT_INTERFACE_ASSOCIATION_SIZE \ - sizeof(struct usb_iface_assoc_descriptor) + sizeof(usb_iface_assoc_descriptor) -enum usb_language_id { +enum usb_language_id +{ USB_LANGID_ENGLISH_US = 0x409, }; /////////////////////////////////////////////////////////////// - - - - #endif diff --git a/components/USBIP/usbip_defs.h b/components/USBIP/usbip_defs.h index eb3935c..c977914 100644 --- a/components/USBIP/usbip_defs.h +++ b/components/USBIP/usbip_defs.h @@ -12,7 +12,6 @@ // usbip_stage2_header // usbip_stage1_response_devlist - // // Created by thevoidnn on 10/25/17. // @@ -26,36 +25,39 @@ #define USBIP_SYSFS_PATH_SIZE 256 #define USBIP_BUSID_SIZE 32 -enum usbip_stage1_command { +enum usbip_stage1_command +{ // Offset 2 - USBIP_STAGE1_CMD_DEVICE_LIST = 0x05, // OP_REQ_DEVLIST + USBIP_STAGE1_CMD_DEVICE_LIST = 0x05, // OP_REQ_DEVLIST USBIP_STAGE1_CMD_DEVICE_ATTACH = 0x03, // OP_REQ_IMPORT }; -enum usbip_stager2_command { ////TODO: change to stage2 - //Offset 0 - USBIP_STAGE2_REQ_SUBMIT = 0x0001, +enum usbip_stager2_command +{ ////TODO: change to stage2 + //Offset 0 + USBIP_STAGE2_REQ_SUBMIT = 0x0001, USBIP_STAGE2_REQ_UNLINK = 0x0002, USBIP_STAGE2_RSP_SUBMIT = 0x0003, USBIP_STAGE2_RSP_UNLINK = 0x0004, }; -enum usbip_stage2_direction { +enum usbip_stage2_direction +{ USBIP_DIR_OUT = 0x00, - USBIP_DIR_IN = 0x01, + USBIP_DIR_IN = 0x01, }; -struct usbip_stage1_header { +typedef struct +{ uint16_t version; uint16_t command; - uint32_t status; -} __attribute__ ((__packed__)); + uint32_t status; +} __attribute__((__packed__)) usbip_stage1_header; ///////////////////////////////////////////////////////////// - - // Device description -struct usbip_stage1_usb_device { +typedef struct +{ char path[USBIP_SYSFS_PATH_SIZE]; char busid[USBIP_BUSID_SIZE]; @@ -74,39 +76,33 @@ struct usbip_stage1_usb_device { uint8_t bConfigurationValue; uint8_t bNumConfigurations; uint8_t bNumInterfaces; -} __attribute__((packed)); +} __attribute__((packed)) usbip_stage1_usb_device; // Interface description -struct usbip_stage1_usb_interface { +typedef struct +{ uint8_t bInterfaceClass; uint8_t bInterfaceSubClass; uint8_t bInterfaceProtocol; uint8_t padding; -} __attribute__((packed)); +} __attribute__((packed)) usbip_stage1_usb_interface; +typedef struct +{ + usbip_stage1_usb_device udev; + usbip_stage1_usb_interface uinf[]; +} __attribute__((packed)) usbip_stage1_response_devlist_entry; - - -struct usbip_stage1_response_devlist_entry { - struct usbip_stage1_usb_device udev; - struct usbip_stage1_usb_interface uinf[]; -} __attribute__((packed)); - -struct usbip_stage1_response_devlist { - uint32_t list_size; +typedef struct +{ + uint32_t list_size; usbip_stage1_response_devlist_entry devices[]; -} __attribute__ ((__packed__)); - - - - +} __attribute__((__packed__)) usbip_stage1_response_devlist; /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// - - /** * struct usbip_header_basic - data pertinent to every URB request * RESPONSE & REQUEST @@ -119,13 +115,14 @@ struct usbip_stage1_response_devlist { * @direction: direction of the transfer * @ep: endpoint number */ -struct usbip_stage2_header_basic { +typedef struct +{ uint32_t command; uint32_t seqnum; uint32_t devid; uint32_t direction; uint32_t ep; -} __attribute__((packed)); +} __attribute__((packed)) usbip_stage2_header_basic; /** * struct usbip_header_cmd_submit - USBIP_CMD_SUBMIT packet header @@ -138,7 +135,8 @@ struct usbip_stage2_header_basic { * @interval: maximum time for the request on the server-side host controller * @setup: setup data for a control request */ -struct usbip_stage2_header_cmd_submit { +typedef struct +{ uint32_t transfer_flags; int32_t data_length; @@ -151,7 +149,7 @@ struct usbip_stage2_header_cmd_submit { uint8_t setup[8]; usb_standard_request request; }; -} __attribute__((packed)); +} __attribute__((packed)) usbip_stage2_header_cmd_submit; /** * struct usbip_header_ret_submit - USBIP_RET_SUBMIT packet header @@ -163,61 +161,50 @@ struct usbip_stage2_header_cmd_submit { * @number_of_packets: number of isochronous packets * @error_count: number of errors for isochronous transfers */ -struct usbip_stage2_header_ret_submit { +typedef struct +{ int32_t status; - int32_t data_length;//actual_length + int32_t data_length; //actual_length int32_t start_frame; int32_t number_of_packets; int32_t error_count; -} __attribute__((packed)); - - - +} __attribute__((packed)) usbip_stage2_header_ret_submit; /** * struct usbip_header_cmd_unlink - USBIP_CMD_UNLINK packet header * >>>REQUEST * @seqnum: the URB seqnum to unlink */ -struct usbip_stage2_header_cmd_unlink { +typedef struct +{ uint32_t seqnum; -} __attribute__((packed)); +} __attribute__((packed)) usbip_stage2_header_cmd_unlink; /** * struct usbip_header_ret_unlink - USBIP_RET_UNLINK packet header * <<base.ep); return -1; } return 0; } -static void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length) +void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length) { req_header->base.command = USBIP_STAGE2_RSP_SUBMIT; diff --git a/main/usbip_server.h b/main/usbip_server.h index c085c28..12df7d6 100644 --- a/main/usbip_server.h +++ b/main/usbip_server.h @@ -1,6 +1,7 @@ #ifndef __USBIP_SERVER_H__ #define __USBIP_SERVER_H__ #include +#include "usbip_defs.h" enum state_t { ACCEPTING, @@ -12,5 +13,7 @@ extern int kSock; int attach(uint8_t *buffer, uint32_t length); int emulate(uint8_t *buffer, uint32_t length); +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, void *data, int32_t data_length); +void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length); #endif \ No newline at end of file From 529e0a375f7a84c134be33c4e6ec374326b2ecd2 Mon Sep 17 00:00:00 2001 From: windowsair Date: Sat, 25 Jan 2020 21:45:24 +0800 Subject: [PATCH 06/21] feat: URB packet processing & DAP command push --- components/DAP/config/DAP_config.h | 12 ++--- components/USBIP/USB_handle.c | 83 +++++++++++++++++------------- components/USBIP/USBd_config.c | 3 +- components/USBIP/usbip_defs.h | 10 ++-- main/CMakeLists.txt | 2 +- main/DAP_handle.c | 45 ++++++++++++++++ main/DAP_handle.h | 8 +++ main/usbip_server.c | 11 ++-- 8 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 main/DAP_handle.c create mode 100644 main/DAP_handle.h diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index 048d766..cc272fe 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -100,7 +100,7 @@ This information includes: /// This configuration settings is used to optimize the communication performance with the /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the /// setting can be reduced (valid range is 1 .. 255). -#define DAP_PACKET_COUNT 8U ///< Specifies number of packets buffered. +#define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered. /// Indicate that UART Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of Capabilities. @@ -109,7 +109,7 @@ This information includes: /// Maximum SWO UART Baudrate. #define SWO_UART_MAX_BAUDRATE 50000000U ///< SWO UART Maximum Baudrate in Hz. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz -// TODO: uncertain value +//// TODO: uncertain value /// Indicate that Manchester Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of Capabilities. @@ -144,7 +144,7 @@ This information includes: */ __STATIC_INLINE uint8_t DAP_GetVendorString(char *str) { - //TODO: fill this + ////TODO: fill this // In fact, Keil can get the corresponding information through USB // without filling in this information. (void)str; @@ -296,7 +296,7 @@ __STATIC_INLINE void PORT_OFF(void) */ __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) { - // TODO : can we set to 0? + ////TODO: can we set to 0? return ((GPIO.in >> PIN_SWCLK) & 0x1); } @@ -478,7 +478,7 @@ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) */ __STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) { - //TODO : What does this mean? ? ? + ////TODO: What does this mean? ? ? if ((bit & 1U) == 1) { //set bit @@ -512,7 +512,7 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) */ __STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) { - //TODO : What does this mean? ? ? + ////TODO: What does this mean? ? ? if ((bit & 1U) == 1) { //set bit diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index 56207a2..b8807db 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -1,6 +1,6 @@ /** * @file USB_handle.c - * @brief Handle all Standard Device Requests + * @brief Handle all Standard Device Requests on endpoint 0 * @version 0.1 * @date 2020-01-23 * @@ -17,34 +17,38 @@ #include "usbip_server.h" #include "usb_defs.h" - // handle functions -static void handleGetDescriptor(struct usbip_stage2_header *header); +static void handleGetDescriptor(usbip_stage2_header *header); ////TODO: fill this -int handleUSBControlRequest(struct usbip_stage2_header *header) +int handleUSBControlRequest(usbip_stage2_header *header) { // Table 9-3. Standard Device Requests switch (header->u.cmd_submit.request.bmRequestType) { - case 0x00: + case 0x00: // ignore.. switch (header->u.cmd_submit.request.bRequest) { case USB_REQ_CLEAR_FEATURE: - /* code */ + os_printf("* CLEAR FEATURE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_FEATURE: - /* code */ + os_printf("* SET FEATURE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_ADDRESS: - /* code */ + os_printf("* SET ADDRESS\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_DESCRIPTOR: - /* code */ + os_printf("* SET DESCRIPTOR\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_CONFIGURATION: - /* code */ + os_printf("* SET CONFIGURATION\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; default: os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", @@ -52,17 +56,20 @@ int handleUSBControlRequest(struct usbip_stage2_header *header) break; } break; - case 0x01: + case 0x01: // ignore... switch (header->u.cmd_submit.request.bRequest) { case USB_REQ_CLEAR_FEATURE: - /* code */ + os_printf("* CLEAR FEATURE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_FEATURE: - /* code */ + os_printf("* SET FEATURE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_INTERFACE: - /* code */ + os_printf("* SET INTERFACE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; default: @@ -71,14 +78,16 @@ int handleUSBControlRequest(struct usbip_stage2_header *header) break; } break; - case 0x02: + case 0x02: // ignore.. switch (header->u.cmd_submit.request.bRequest) { case USB_REQ_CLEAR_FEATURE: - /* code */ + os_printf("* CLEAR FEATURE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_FEATURE: - /* code */ + os_printf("* SET INTERFACE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; default: @@ -88,17 +97,19 @@ int handleUSBControlRequest(struct usbip_stage2_header *header) } break; - case 0x80: + case 0x80: // *IMPORTANT* switch (header->u.cmd_submit.request.bRequest) { case USB_REQ_GET_CONFIGURATION: - handleGetDescriptor(header); + os_printf("* GET CONIFGTRATION\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_GET_DESCRIPTOR: - /* code */ + handleGetDescriptor(header); ////TODO: device_qualifier break; case USB_REQ_GET_STATUS: - /* code */ + os_printf("* GET STATUS\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; default: os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", @@ -106,17 +117,20 @@ int handleUSBControlRequest(struct usbip_stage2_header *header) break; } break; - case 0x81: + case 0x81: // ignore... switch (header->u.cmd_submit.request.bRequest) { case USB_REQ_GET_INTERFACE: - /* code */ + os_printf("* GET INTERFACE\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_SET_SYNCH_FRAME: - /* code */ + os_printf("* SET SYNCH FRAME\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; case USB_REQ_GET_STATUS: - /* code */ + os_printf("* GET STATUS\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; default: @@ -126,11 +140,12 @@ int handleUSBControlRequest(struct usbip_stage2_header *header) } break; - case 0x82: + case 0x82: // ignore... switch (header->u.cmd_submit.request.bRequest) { case USB_REQ_GET_STATUS: - /* code */ + os_printf("* GET STATUS\r\n"); + send_stage2_submit_data(header, 0, 0, 0); break; default: @@ -139,7 +154,6 @@ int handleUSBControlRequest(struct usbip_stage2_header *header) break; } break; - ///////// default: os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", @@ -148,8 +162,8 @@ int handleUSBControlRequest(struct usbip_stage2_header *header) } } -////TODO: fill this -static void handleGetDescriptor(struct usbip_stage2_header *header) +////TODO: BOS descriptor +static void handleGetDescriptor(usbip_stage2_header *header) { // 9.4.3 Get Descriptor switch (header->u.cmd_submit.request.wValue.u8hi) @@ -168,7 +182,6 @@ static void handleGetDescriptor(struct usbip_stage2_header *header) send_stage2_submit(header, 0, header->u.cmd_submit.data_length); send(kSock, kUSBd0ConfigDescriptor, sizeof(kUSBd0ConfigDescriptor), 0); - } else { @@ -177,18 +190,19 @@ static void handleGetDescriptor(struct usbip_stage2_header *header) send_stage2_submit(header, 0, header->u.cmd_submit.data_length); send(kSock, kUSBd0ConfigDescriptor, sizeof(kUSBd0ConfigDescriptor), 0); send(kSock, kUSBd0InterfaceDescriptor, sizeof(kUSBd0InterfaceDescriptor), 0); - } break; case USB_DT_STRING: os_printf("* GET 0x03 STRING DESCRIPTOR\r\n"); - if (header->u.cmd_submit.request.wValue.u8lo == 0) { + if (header->u.cmd_submit.request.wValue.u8lo == 0) + { os_printf("** REQUESTED list of supported languages\r\n"); send_stage2_submit_data(header, 0, kLangDescriptor, sizeof(kLangDescriptor)); } - else{ + else + { os_printf("***Unsupported operation***\r\n"); } break; @@ -227,7 +241,6 @@ static void handleGetDescriptor(struct usbip_stage2_header *header) send_stage2_submit(header, 0, 0); break; - default: os_printf("USB unknown Get Descriptor requested:%d", header->u.cmd_submit.request.wValue.u8lo); break; diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c index e0f57ab..c266c16 100644 --- a/components/USBIP/USBd_config.c +++ b/components/USBIP/USBd_config.c @@ -26,7 +26,8 @@ const uint8_t kUSBd0DeviceDescriptor[0x12] = { 0x12, // bLength USB_DT_DEVICE, // bDescriptorType (constant) - USBShort(0x0200), // bcdUSB (2.00) + USBShort(0x0210), // bcdUSB + ////TODO: Is it also available elsewhere? // We need to use a device other than the USB-IF standard, set to 0x00 0x00, // bDeviceClass diff --git a/components/USBIP/usbip_defs.h b/components/USBIP/usbip_defs.h index c977914..84904c6 100644 --- a/components/USBIP/usbip_defs.h +++ b/components/USBIP/usbip_defs.h @@ -197,13 +197,13 @@ typedef struct */ typedef struct { - struct usbip_stage2_header_basic base; + usbip_stage2_header_basic base; union { - struct usbip_stage2_header_cmd_submit cmd_submit; - struct usbip_stage2_header_ret_submit ret_submit; - struct usbip_stage2_header_cmd_unlink cmd_unlink; - struct usbip_stage2_header_ret_unlink ret_unlink; + usbip_stage2_header_cmd_submit cmd_submit; + usbip_stage2_header_ret_submit ret_submit; + usbip_stage2_header_cmd_unlink cmd_unlink; + usbip_stage2_header_ret_unlink ret_unlink; } u; } __attribute__((packed)) usbip_stage2_header; diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 6619874..b961c72 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_SRCS "main.c timer.c tcp_server.c usbip_server.c") +set(COMPONENT_SRCS "main.c timer.c tcp_server.c usbip_server.c DAP_handle.c") set(COMPONENT_ADD_INCLUDEDIRS ". $ENV{IDF_PATH}/components/esp8266/include/esp8266/ ../components/USBIP") register_component() diff --git a/main/DAP_handle.c b/main/DAP_handle.c new file mode 100644 index 0000000..98d26c8 --- /dev/null +++ b/main/DAP_handle.c @@ -0,0 +1,45 @@ +/** + * @file DAP_handle.c + * @brief Handle DAP packets and transaction push + * @version 0.1 + * @date 2020-01-25 + * + * @copyright Copyright (c) 2020 + * + */ + +#include +#include "usbip_server.h" +#include "DAP_handle.h" +#include "DAP.h" + +////TODO: Merge this +#define DAP_PACKET_SIZE 512 + + +uint8_t data_out[DAP_PACKET_SIZE]; +int respond = 0; + + +void handle_dap_data_request(usbip_stage2_header *header) +{ + uint8_t * data_in = (uint8_t *)header; + data_in = &(data_in[sizeof(usbip_stage2_header)]); + // Point to the beginning of the URB packet + respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); + send_stage2_submit(header, 0, 0); + +} +void handle_dap_data_response(usbip_stage2_header *header) +{ + if (respond) { + respond = 0; + //os_printf("*** Will respond"); + send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); + + //os_printf("*** RESPONDED ***"); + } else { + //os_printf("*** Will NOT respond"); + send_stage2_submit(header, 0, 0); + } +} \ No newline at end of file diff --git a/main/DAP_handle.h b/main/DAP_handle.h new file mode 100644 index 0000000..903bc58 --- /dev/null +++ b/main/DAP_handle.h @@ -0,0 +1,8 @@ +#ifndef __DAP_HANDLE_H__ +#define __DAP_HANDLE_H__ + +#include "usbip_defs.h" + +void handle_dap_data_request(usbip_stage2_header *header); +void handle_dap_data_response(usbip_stage2_header *header); +#endif \ No newline at end of file diff --git a/main/usbip_server.c b/main/usbip_server.c index b18d235..034975d 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -121,7 +121,6 @@ static void send_device_list() static void send_device_info() { - //// TODO:fill this os_printf("Sending device info..."); usbip_stage1_usb_device device; @@ -172,7 +171,7 @@ static void send_interface_info() int emulate(uint8_t *buffer, uint32_t length) { // usbip_stage2_header header; - int command = read_stage2_command((usbip_stage2_header *)buffer); ////TODO: fill this + int command = read_stage2_command((usbip_stage2_header *)buffer, length); ////TODO: fill this if (command < 0) { return -1; @@ -272,13 +271,13 @@ static int handle_submit(usbip_stage2_header *header) case 0x01: if (header->base.direction == 0) { - // Serial.println("EP 01 DATA FROM HOST"); - handle_data_request(header); + // os_printf("EP 01 DATA FROM HOST"); + handle_dap_data_request(header); } else { - // Serial.println("EP 01 DATA TO HOST"); - handle_data_response(header); + // os_printf("EP 01 DATA TO HOST"); + handle_dap_data_response(header); } break; From 8cfb843951be031252cb739217b0b17978cdb270 Mon Sep 17 00:00:00 2001 From: windowsair Date: Sun, 26 Jan 2020 15:54:57 +0800 Subject: [PATCH 07/21] feat: Add Microsoft OS 2.0 Descriptors and WinUSB Support. --- components/USBIP/MSOS20Descriptors.c | 84 ++++++++++++++++++++++++++++ components/USBIP/MSOS20Descriptors.h | 81 +++++++++++++++++++++++++++ components/USBIP/USB_handle.c | 28 +++++++++- components/USBIP/usb_defs.h | 1 + components/USBIP/usbip_defs.h | 2 +- main/usbip_server.c | 6 +- 6 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 components/USBIP/MSOS20Descriptors.c create mode 100644 components/USBIP/MSOS20Descriptors.h diff --git a/components/USBIP/MSOS20Descriptors.c b/components/USBIP/MSOS20Descriptors.c new file mode 100644 index 0000000..4337076 --- /dev/null +++ b/components/USBIP/MSOS20Descriptors.c @@ -0,0 +1,84 @@ +/** + * @file MSOS20Descriptors.c + * @author windowsair + * @brief Store related data of Microsoft OS 2.0 descriptor + * @version 0.1 + * @date 2019-11-21 + * + * @copyright Copyright (c) 2019 + * + */ + + ////TODO: refactoring into structure + +#include +#include "MSOS20Descriptors.h" + +#define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) + + + +// Microsoft OS 2.0 descriptor set header +const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20] = +{ + // Microsoft OS 2.0 Descriptor Set header (Table 10) + 0x0A, 0x00, // wLength (Shall be set to 0x0A) + MS_OS_20_SET_HEADER_DESCRIPTOR, 0x00, + 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) + USBShort(kLengthOfMsOS20), // wTotalLength + + // Support WinUSB + // See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/automatic-installation-of-winusb + + // Microsoft OS 2.0 compatible ID descriptor (Table 13) + 0x14, 0x00, // wLength + USBShort(MS_OS_20_FEATURE_COMPATIBLE_ID), // wDescriptorType + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleID + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompatibleID + + // Microsoft OS 2.0 registry property descriptor (Table 14) + 0x84, 0x00, // wLength + USBShort(MS_OS_20_FEATURE_REG_PROPERTY), + 0x07, 0x00, // wPropertyDataType: REG_MULTI_SZ (Unicode Strings) + 0x2A, 0x00, // wPropertyNameLength + 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0, + 'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,'s',0,0,0, + // Set to "DeviceInterfaceGUID" to support WinUSB + 0x50, 0x00, // wPropertyDataLength + // WinUSB GUID + '{',0,'C',0,'D',0,'B',0,'3',0,'B',0,'5',0,'A',0,'D',0,'-',0, + '2',0,'9',0,'3',0,'B',0,'-',0,'4',0,'6',0,'6',0,'3',0,'-',0, + 'A',0,'A',0,'3',0,'6',0,'-',0,'1',0,'A',0,'A',0,'E',0,'4',0, + '6',0,'4',0,'6',0,'3',0,'7',0,'7',0,'6',0,'}',0,0,0,0,0, + // identify a CMSIS-DAP V2 configuration, + // must set to "{CDB3B5AD-293B-4663-AA36-1AAE46463776}" + +}; + +const uint8_t bosDescriptor[kLengthOfBos] = +{ + // Universal Serial Bus 3.0 Specification, Table 9-9. + 0x05, // bLength of this descriptor + USB_DESCRIPTOR_TYPE_BOS, // BOS Descriptor type(Constant) + USBShort(kLengthOfBos), // wLength + 0x01, // bNumDeviceCaps + + // Microsoft OS 2.0 platform capability descriptor header (Table 4) + // See also: + // Universal Serial Bus 3.0 Specification : Format of a Device Capability Descriptor, Table 9-10. + + 0x1C, // bLength of this first device capability descriptor + // bLength -> The total length of the remaining arrays containing this field + USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY, // bDescriptorType + USB_DEVICE_CAPABILITY_TYPE_PLATFORM, // bDevCapabilityType + + // Capability-Dependent (See USB3.0 Specification Table 9-10.) + 0x00, // bReserved + USB_DEVICE_CAPABILITY_UUID, // MS_OS_20_Platform_Capability_ID + + 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) + USBShort(kLengthOfMsOS20), // wMSOSDescriptorSetTotalLength(length of descriptor set header) + kValueOfbMS_VendorCode, // bMS_VendorCode (0x01 will be ok) + ////TODO:change this + 0, // bAltEnumCode +}; \ No newline at end of file diff --git a/components/USBIP/MSOS20Descriptors.h b/components/USBIP/MSOS20Descriptors.h new file mode 100644 index 0000000..61a7ea3 --- /dev/null +++ b/components/USBIP/MSOS20Descriptors.h @@ -0,0 +1,81 @@ +/** + * @file MSOS20Descriptors.h + * @author windowsair + * @brief + * @version 0.1 + * @date 2019-11-21 + * + * @copyright Copyright (c) 2019 + * + */ + +#ifndef __MSOS20DESCRIPTORS_H__ +#define __MSOS20DESCRIPTORS_H__ + +#define kLengthOfMsOS20 0xA2 +#define kLengthOfBos 0x21 +#define kValueOfbMS_VendorCode 0x01// Just set to 0x01 +extern const uint8_t bosDescriptor[kLengthOfBos]; +extern const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20]; + +/* Microsoft OS 2.0 Descriptors BEGIN */ + +// Platform capability BOS descriptor, Table 1. +#define USB_DEVICE_CAPABILITY_TYPE_PLATFORM 5 + +// Platform capability UUID, Table 3. +// {D8DD60DF-4589-4CC7-9CD2-659D9E648A9F} +#define USB_DEVICE_CAPABILITY_UUID 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + + +// Microsoft OS 2.0 descriptor wIndex values enum, Table 8. +#define MS_OS_20_DESCRIPTOR_INDEX 7 +#define MS_OS_20_SET_ALT_ENUMERATION 8 + + +// Microsoft OS 2.0 descriptor types enum for wDescriptorType values, Table 9. +#define MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 +#define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 +#define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 +#define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 +#define MS_OS_20_FEATURE_REG_PROPERTY 0x04 +#define MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 +#define MS_OS_20_FEATURE_MODEL_ID 0x06 +#define MS_OS_20_FEATURE_CCGP_DEVICE 0x07 + +/* Microsoft OS 2.0 Descriptors END */ + + + +/* Wireless USB Standard Extension Descriptor Types BEGIN */ + +// Wireless USB Specification 1.1 revison 1.1, Table 7-21. +#define USB_DESCRIPTOR_TYPE_SECURITY 12 +#define USB_DESCRIPTOR_TYPE_KEY 13 +#define USB_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 14 +#define USB_DESCRIPTOR_TYPE_BOS 15 +#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 16 +#define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMPANION 17 + +/* Wireless USB Standard Extension Descriptor Types END */ + + +/* Microsoft Extended Compat ID OS Feature Descriptor BEGIN */ + +#define USB_MS_EXTENDED_COMPAT_ID_VERSION 0x0100 +#define USB_MS_EXTENDED_COMPAT_ID_TYPE 0x04 + +#define USB_COMPATID_NONE {0} +#define USB_SUBCOMPATID_NONE {0} +#define USB_COMPATID_WINUSB "WINUSB\0" +#define USB_COMPATID_RNDIS "RNDIS\0\0" +#define USB_COMPATID_PTP "PTP\0\0\0\0" +#define USB_COMPATID_MTP "MTP\0\0\0\0" +#define USB_COMPATID_BLUETOOTH "BLUTUTH" +#define USB_SUBCOMPATID_BT_V11 "11\0\0\0\0\0" +#define USB_SUBCOMPATID_BT_V12 "12\0\0\0\0\0" +#define USB_SUBCOMPATID_BT_V20EDR "EDR\0\0\0\0" + +/* Microsoft Extended Compat ID OS Feature Descriptor END */ + +#endif \ No newline at end of file diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index b8807db..d7ef3b2 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -16,11 +16,12 @@ #include "USBd_config.h" #include "usbip_server.h" #include "usb_defs.h" +#include "MSOS20Descriptors.h" // handle functions static void handleGetDescriptor(usbip_stage2_header *header); -////TODO: fill this +////TODO: may be ok int handleUSBControlRequest(usbip_stage2_header *header) { // Table 9-3. Standard Device Requests @@ -154,7 +155,26 @@ int handleUSBControlRequest(usbip_stage2_header *header) break; } break; + case 0xC0: // Microsoft OS 2.0 vendor-specific descriptor + uint16_t *wIndex = (uint16_t *)(&(header->u.cmd_submit.request.wIndex)); + switch (*wIndex) + { + case MS_OS_20_DESCRIPTOR_INDEX: + os_printf("* GET MSOS 2.0 vendor-specific descriptor\r\n"); + send_stage2_submit_data(header, 0, msOs20DescriptorSetHeader, sizeof(msOs20DescriptorSetHeader)); + break; + case MS_OS_20_SET_ALT_ENUMERATION: + // set alternate enumeration command + // bAltEnumCode set to 0 + os_printf("Set alternate enumeration.This should not happen.\r\n"); + break; + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d,wIndex:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest, *wIndex); + break; + } + break; default: os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); @@ -162,7 +182,7 @@ int handleUSBControlRequest(usbip_stage2_header *header) } } -////TODO: BOS descriptor + static void handleGetDescriptor(usbip_stage2_header *header) { // 9.4.3 Get Descriptor @@ -241,6 +261,10 @@ static void handleGetDescriptor(usbip_stage2_header *header) send_stage2_submit(header, 0, 0); break; + case USB_DT_BOS: + os_printf("* GET 0x0F BOS DESCRIPTOR\r\n"); + send_stage2_submit_data(header, 0, bosDescriptor, sizeof(bosDescriptor)); + break; default: os_printf("USB unknown Get Descriptor requested:%d", header->u.cmd_submit.request.wValue.u8lo); break; diff --git a/components/USBIP/usb_defs.h b/components/USBIP/usb_defs.h index 31898da..39add9b 100644 --- a/components/USBIP/usb_defs.h +++ b/components/USBIP/usb_defs.h @@ -110,6 +110,7 @@ typedef struct #define USB_DT_DEVICE_QUALIFIER 6 #define USB_DT_OTHER_SPEED_CONFIGURATION 7 #define USB_DT_INTERFACE_POWER 8 +#define USB_DT_BOS 15 /* From ECNs */ #define USB_DT_OTG 9 #define USB_DT_DEBUG 10 diff --git a/components/USBIP/usbip_defs.h b/components/USBIP/usbip_defs.h index 84904c6..d36d16e 100644 --- a/components/USBIP/usbip_defs.h +++ b/components/USBIP/usbip_defs.h @@ -33,7 +33,7 @@ enum usbip_stage1_command }; enum usbip_stager2_command -{ ////TODO: change to stage2 +{ //Offset 0 USBIP_STAGE2_REQ_SUBMIT = 0x0001, USBIP_STAGE2_REQ_UNLINK = 0x0002, diff --git a/main/usbip_server.c b/main/usbip_server.c index 034975d..1fb7e0e 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -39,7 +39,7 @@ int attach(uint8_t *buffer, uint32_t length) break; case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT - handle_device_attach(buffer, length); ////TODO: fill this + handle_device_attach(buffer, length); break; default: @@ -171,7 +171,7 @@ static void send_interface_info() int emulate(uint8_t *buffer, uint32_t length) { // usbip_stage2_header header; - int command = read_stage2_command((usbip_stage2_header *)buffer, length); ////TODO: fill this + int command = read_stage2_command((usbip_stage2_header *)buffer, length); if (command < 0) { return -1; @@ -253,7 +253,7 @@ static void unpack(void *data, int size) } } -////TODO: fill this + /** * @brief * From 822aa0b6adc6ff5eddda537596da78b2cd2e7a87 Mon Sep 17 00:00:00 2001 From: windowsair Date: Sun, 26 Jan 2020 16:29:52 +0800 Subject: [PATCH 08/21] chore: Add cmake file for components --- CMakeLists.txt | 1 + components/CMakeLists.txt | 0 components/DAP/CMakeLists.txt | 4 ++++ components/USBIP/CMakeLists.txt | 4 ++++ main/CMakeLists.txt | 2 +- 5 files changed, 10 insertions(+), 1 deletion(-) delete mode 100644 components/CMakeLists.txt create mode 100644 components/DAP/CMakeLists.txt create mode 100644 components/USBIP/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index afc306e..0eb1581 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ # The following five lines of boilerplate have to be in your project's # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +#set(COMPONENT_DIRS "${IDF_PATH}/components ${PROJECT_PATH}/components") include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp8266_dap) diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt deleted file mode 100644 index e69de29..0000000 diff --git a/components/DAP/CMakeLists.txt b/components/DAP/CMakeLists.txt new file mode 100644 index 0000000..83bea91 --- /dev/null +++ b/components/DAP/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_ADD_INCLUDEDIRS "config include") +set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c") + +register_component() \ No newline at end of file diff --git a/components/USBIP/CMakeLists.txt b/components/USBIP/CMakeLists.txt new file mode 100644 index 0000000..d8f96b0 --- /dev/null +++ b/components/USBIP/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_ADD_INCLUDEDIRS ".") +set(COMPONENT_SRCS "MSOS20Descriptors.c USB_handle.c USBd_config.c") + +register_component() \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index b961c72..d6ae4a1 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_SRCS "main.c timer.c tcp_server.c usbip_server.c DAP_handle.c") set(COMPONENT_ADD_INCLUDEDIRS ". $ENV{IDF_PATH}/components/esp8266/include/esp8266/ ../components/USBIP") +set(COMPONENT_SRCS "main.c timer.c tcp_server.c usbip_server.c DAP_handle.c") register_component() From 50079136ab7c8324b227b9ee15782fb15c890194 Mon Sep 17 00:00:00 2001 From: windowsair Date: Mon, 27 Jan 2020 10:42:21 +0800 Subject: [PATCH 09/21] fix: Fix some simple bugs (spelling errors, etc.) --- components/DAP/CMakeLists.txt | 5 ++-- components/DAP/config/DAP_config.h | 12 ++++++--- components/DAP/include/DAP.h | 5 +++- components/DAP/include/cmsis_compiler.h | 15 +++++++++++ components/DAP/source/SWO.c | 2 ++ components/USBIP/CMakeLists.txt | 2 +- components/USBIP/USB_handle.c | 10 ++++--- components/USBIP/USB_handle.h | 4 ++- components/USBIP/usb_defs.h | 8 +++--- main/tcp_server.c | 10 +++---- main/timer.c | 2 +- main/usbip_server.c | 36 ++++++++++++++----------- main/usbip_server.h | 4 +-- 13 files changed, 75 insertions(+), 40 deletions(-) create mode 100644 components/DAP/include/cmsis_compiler.h diff --git a/components/DAP/CMakeLists.txt b/components/DAP/CMakeLists.txt index 83bea91..59f8ce1 100644 --- a/components/DAP/CMakeLists.txt +++ b/components/DAP/CMakeLists.txt @@ -1,4 +1,5 @@ -set(COMPONENT_ADD_INCLUDEDIRS "config include") -set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c") +set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp8266/include/esp8266/") +set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ") +# ./source/SWO.c register_component() \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index cc272fe..a4ed661 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -28,10 +28,16 @@ #ifndef __DAP_CONFIG_H__ #define __DAP_CONFIG_H__ +#include +#include "cmsis_compiler.h" #include "gpio.h" #include "gpio_struct.h" #include "timer_struct.h" + + + + //************************************************************************************************** /** \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information @@ -454,7 +460,7 @@ __STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) */ __STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) { - return ((GPIO.in >> PIN_TDO_IN) & 0x1); + return ((GPIO.in >> PIN_TDI) & 0x1); } // nTRST Pin I/O ------------------------------------------- @@ -609,8 +615,8 @@ default, the DWT timer is used. The frequency of this timer is configured with */ __STATIC_INLINE uint32_t TIMESTAMP_GET(void) { - // FRC1 is a 24-bit countdown timer - return (0x1000000U - 1U - (frc1.count.data)); + // FRC1 is a 23-bit countdown timer + return (0x7FFFFF - (frc1.count.data)); } ///@} diff --git a/components/DAP/include/DAP.h b/components/DAP/include/DAP.h index 4194005..516b83d 100644 --- a/components/DAP/include/DAP.h +++ b/components/DAP/include/DAP.h @@ -284,7 +284,10 @@ extern void DAP_Setup (void); #ifndef DELAY_SLOW_CYCLES #define DELAY_SLOW_CYCLES 3U // Number of cycles for one iteration #endif -#if defined(__CC_ARM) + +#define USE_ASSEMBLY 0 + +#if USE_ASSEMBLY == 0 __STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) { uint32_t count = delay; while (--count); diff --git a/components/DAP/include/cmsis_compiler.h b/components/DAP/include/cmsis_compiler.h new file mode 100644 index 0000000..349f5fd --- /dev/null +++ b/components/DAP/include/cmsis_compiler.h @@ -0,0 +1,15 @@ +#ifndef __CMSIS_COMPILER_H__ +#define __CMSIS_COMPILER_H__ + +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE static inline __attribute__((always_inline)) +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline __attribute__((always_inline)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif + + +#endif \ No newline at end of file diff --git a/components/DAP/source/SWO.c b/components/DAP/source/SWO.c index 1093bfb..241d9cb 100644 --- a/components/DAP/source/SWO.c +++ b/components/DAP/source/SWO.c @@ -27,12 +27,14 @@ #include "DAP_config.h" #include "DAP.h" +/* #if (SWO_UART != 0) #include "Driver_USART.h" #endif #if (SWO_STREAM != 0) #include "cmsis_os2.h" #endif +*/ #if (SWO_STREAM != 0) #ifdef DAP_FW_V1 diff --git a/components/USBIP/CMakeLists.txt b/components/USBIP/CMakeLists.txt index d8f96b0..3aeba6c 100644 --- a/components/USBIP/CMakeLists.txt +++ b/components/USBIP/CMakeLists.txt @@ -1,4 +1,4 @@ -set(COMPONENT_ADD_INCLUDEDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS ". ../../main") set(COMPONENT_SRCS "MSOS20Descriptors.c USB_handle.c USBd_config.c") register_component() \ No newline at end of file diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index d7ef3b2..a6dd0ce 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -8,6 +8,7 @@ * */ #include +#include #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" @@ -22,7 +23,7 @@ static void handleGetDescriptor(usbip_stage2_header *header); ////TODO: may be ok -int handleUSBControlRequest(usbip_stage2_header *header) +void handleUSBControlRequest(usbip_stage2_header *header) { // Table 9-3. Standard Device Requests @@ -156,6 +157,7 @@ int handleUSBControlRequest(usbip_stage2_header *header) } break; case 0xC0: // Microsoft OS 2.0 vendor-specific descriptor + { uint16_t *wIndex = (uint16_t *)(&(header->u.cmd_submit.request.wIndex)); switch (*wIndex) { @@ -170,11 +172,12 @@ int handleUSBControlRequest(usbip_stage2_header *header) break; default: - os_printf("USB unknown request, bmRequestType:%d,bRequest:%d,wIndex:%d\r\n", + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d,wIndex:%d\r\n", header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest, *wIndex); break; } - break; + } + break; default: os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); @@ -182,7 +185,6 @@ int handleUSBControlRequest(usbip_stage2_header *header) } } - static void handleGetDescriptor(usbip_stage2_header *header) { // 9.4.3 Get Descriptor diff --git a/components/USBIP/USB_handle.h b/components/USBIP/USB_handle.h index d23789d..ac4eeec 100644 --- a/components/USBIP/USB_handle.h +++ b/components/USBIP/USB_handle.h @@ -1,5 +1,7 @@ #ifndef __USB_HANDLE_H__ #define __USB_HANDLE_H__ + #include "usbip_defs.h" -int handleUSBControlRequest(usbip_stage2_header *header); +void handleUSBControlRequest(usbip_stage2_header *header); + #endif \ No newline at end of file diff --git a/components/USBIP/usb_defs.h b/components/USBIP/usb_defs.h index 39add9b..c33fa06 100644 --- a/components/USBIP/usb_defs.h +++ b/components/USBIP/usb_defs.h @@ -74,13 +74,13 @@ typedef struct #define USB_REQ_TYPE_STANDARD 0x00 #define USB_REQ_TYPE_CLASS 0x20 #define USB_REQ_TYPE_VENDOR 0x40 -#define USB_REQ_TYPE_RESERVED 0x60 +//#define USB_REQ_TYPE_RESERVED 0x60 /* bits 4..0 : Recipient */ #define USB_REQ_TYPE_DEVICE 0x00 #define USB_REQ_TYPE_INTERFACE 0x01 #define USB_REQ_TYPE_ENDPOINT 0x02 #define USB_REQ_TYPE_OTHER 0x03 -#define USB_REQ_TYPE_RESERVED 0x1F +//#define USB_REQ_TYPE_RESERVED 0x1F /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// @@ -223,7 +223,7 @@ typedef struct /////////////////////////////////////////////////////////////// /* USB Standard Endpoint Descriptor - Table 9-13 */ -typedef struct usb_endpoint_descriptor +typedef struct { uint8_t bLength; uint8_t bDescriptorType; @@ -231,7 +231,7 @@ typedef struct usb_endpoint_descriptor uint8_t bmAttributes; uint16_t wMaxPacketSize; uint8_t bInterval; -} __attribute__((packed)); +} __attribute__((packed))usb_endpoint_descriptor; #define USB_DT_ENDPOINT_SIZE sizeof(usb_endpoint_descriptor) /////////////////////////////////////////////////////////////// diff --git a/main/tcp_server.c b/main/tcp_server.c index 7e6f870..5031600 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -29,11 +29,11 @@ #include "wifi_configuration.h" #include "usbip_server.h" -uint8_t state = ACCEPTING; +uint8_t kState = ACCEPTING; int kSock = -1; void tcp_server_task(void *pvParameters) { - char rx_buffer[2048]; + uint8_t rx_buffer[2048]; char addr_str[128]; int addr_family; int ip_protocol; @@ -132,10 +132,10 @@ void tcp_server_task(void *pvParameters) rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string //os_printf("Received %d bytes from %s:\r\n", len, addr_str); // os_printf("%s", rx_buffer); - switch (state) + switch (kState) { case ACCEPTING: - state = ATTACHING; + kState = ATTACHING; break; case ATTACHING: @@ -155,7 +155,7 @@ void tcp_server_task(void *pvParameters) // } } } - state = ACCEPTING; + kState = ACCEPTING; if (kSock != -1) { os_printf("Shutting down socket and restarting...\r\n"); diff --git a/main/timer.c b/main/timer.c index 18be76f..6fbe6b7 100644 --- a/main/timer.c +++ b/main/timer.c @@ -22,7 +22,7 @@ void timer_create_task() frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz frc1.ctrl.intr_type = TIMER_EDGE_INT; frc1.ctrl.reload = 0x01; - frc1.load.data = 0x1000000U - 1U; + frc1.load.data = 0x7FFFFF; // 23bit?? frc1.ctrl.en = 0x01; vPortExitCritical(); vTaskDelete(NULL); diff --git a/main/usbip_server.c b/main/usbip_server.c index 1fb7e0e..0317f6f 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -1,4 +1,5 @@ #include +#include #include "lwip/err.h" #include "lwip/sockets.h" #include "lwip/sys.h" @@ -8,11 +9,13 @@ #include "usbip_defs.h" #include "usb_defs.h" #include "USBd_config.h" +#include "DAP_handle.h" +#include "USB_handle.h" // attach helper function static int read_stage1_command(uint8_t *buffer, uint32_t length); -static int handle_device_list(uint8_t *buffer, uint32_t length); -static int handle_device_attach(uint8_t *buffer, uint32_t length); +static void handle_device_list(uint8_t *buffer, uint32_t length); +static void handle_device_attach(uint8_t *buffer, uint32_t length); static void send_stage1_header(uint16_t command, uint32_t status); static void send_device_list(); static void send_device_info(); @@ -22,7 +25,7 @@ static void send_interface_info(); static void pack(void *data, int size); static void unpack(void *data, int size); static int handle_submit(usbip_stage2_header *header); -static int handle_control_request(usbip_stage2_header *header); +static int read_stage2_command(usbip_stage2_header *header, uint32_t length); int attach(uint8_t *buffer, uint32_t length) { @@ -46,6 +49,7 @@ int attach(uint8_t *buffer, uint32_t length) os_printf("attach Unknown command: %d\r\n", command); break; } + return 0; ////TODO: ... } static int read_stage1_command(uint8_t *buffer, uint32_t length) @@ -58,21 +62,22 @@ static int read_stage1_command(uint8_t *buffer, uint32_t length) return (ntohs(req->command) & 0xFF); // 0x80xx low bit } -static int handle_device_list(uint8_t *buffer, uint32_t length) +static void handle_device_list(uint8_t *buffer, uint32_t length) { os_printf("Handling dev list request...\r\n"); send_stage1_header(USBIP_STAGE1_CMD_DEVICE_LIST, 0); send_device_list(); } -static int handle_device_attach(uint8_t *buffer, uint32_t length) +static void handle_device_attach(uint8_t *buffer, uint32_t length) { os_printf("Handling dev attach request...\r\n"); //char bus[USBIP_BUSID_SIZE]; if (length < sizeof(USBIP_BUSID_SIZE)) { - return -1; + os_printf("handle device attach failed!\r\n"); + return; } //client.readBytes((uint8_t *)bus, USBIP_BUSID_SIZE); @@ -80,7 +85,7 @@ static int handle_device_attach(uint8_t *buffer, uint32_t length) send_device_info(); - state = EMULATING; + kState = EMULATING; } static void send_stage1_header(uint16_t command, uint32_t status) @@ -194,7 +199,7 @@ int emulate(uint8_t *buffer, uint32_t length) return 0; } -int read_stage2_command(usbip_stage2_header *header, uint32_t length) +static int read_stage2_command(usbip_stage2_header *header, uint32_t length) { if (length < sizeof(usbip_stage2_header)) { @@ -220,10 +225,10 @@ static void pack(void *data, int size) { // Ignore the setup field - int size = (size / sizeof(uint32_t)) - 2; + int sz = (size / sizeof(uint32_t)) - 2; uint32_t *ptr = (uint32_t *)data; - for (int i = 0; i < size; i++) + for (int i = 0; i < sz; i++) { ptr[i] = htonl(ptr[i]); @@ -244,10 +249,10 @@ static void unpack(void *data, int size) { // Ignore the setup field - int size = (size / sizeof(uint32_t)) - 2; + int sz = (size / sizeof(uint32_t)) - 2; uint32_t *ptr = (uint32_t *)data; - for (int i = 0; i < size; i++) + for (int i = 0; i < sz; i++) { ptr[i] = ntohl(ptr[i]); } @@ -264,7 +269,7 @@ static int handle_submit(usbip_stage2_header *header) { // control endpoint(endpoint 0) case 0x00: - handle_control_request(header); + handleUSBControlRequest(header); break; // data @@ -294,8 +299,7 @@ static int handle_submit(usbip_stage2_header *header) return -1; default: - os_printf("*** WARN ! UNKNOWN ENDPOINT: "); - os_printf((int)header->base.ep); + os_printf("*** WARN ! UNKNOWN ENDPOINT: %d\r\n", (int)header->base.ep); return -1; } return 0; @@ -316,7 +320,7 @@ void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t send(kSock, req_header, sizeof(usbip_stage2_header), 0); } -void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, void *data, int32_t data_length) +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void * const data, int32_t data_length) { send_stage2_submit(req_header, status, data_length); diff --git a/main/usbip_server.h b/main/usbip_server.h index 12df7d6..2d0effd 100644 --- a/main/usbip_server.h +++ b/main/usbip_server.h @@ -8,12 +8,12 @@ enum state_t ATTACHING, EMULATING }; -extern uint32_t state; +extern uint8_t kState; extern int kSock; int attach(uint8_t *buffer, uint32_t length); int emulate(uint8_t *buffer, uint32_t length); -void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, void *data, int32_t data_length); +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void * const data, int32_t data_length); void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length); #endif \ No newline at end of file From 1070f630748dd5c6938854e713ebeaf34e6d85fe Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 28 Jan 2020 20:21:18 +0800 Subject: [PATCH 10/21] feat: DAP function completion 1. Add streaming SWO trace support(Not tested) 2. Fix Unlink function --- components/DAP/CMakeLists.txt | 6 +- components/DAP/config/DAP_config.h | 2 +- components/DAP/include/uart_modify.h | 565 ++++++++++++ components/DAP/source/SWO.c | 790 +++++++++------- components/DAP/source/uart_modify.c | 1256 ++++++++++++++++++++++++++ main/DAP_handle.c | 72 +- main/DAP_handle.h | 1 + main/main.c | 12 +- main/usbip_server.c | 47 +- 9 files changed, 2398 insertions(+), 353 deletions(-) create mode 100644 components/DAP/include/uart_modify.h create mode 100644 components/DAP/source/uart_modify.c diff --git a/components/DAP/CMakeLists.txt b/components/DAP/CMakeLists.txt index 59f8ce1..3eec5a2 100644 --- a/components/DAP/CMakeLists.txt +++ b/components/DAP/CMakeLists.txt @@ -1,5 +1,5 @@ -set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp8266/include/esp8266/") -set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ") -# ./source/SWO.c +set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp8266/include/esp8266/ $ENV{IDF_PATH}//components/esp_ringbuf/include/") +set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c ./source/uart_modify.c") + register_component() \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index a4ed661..fccf7d3 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -113,7 +113,7 @@ This information includes: #define SWO_UART 1 ///< SWO UART: 1 = available, 0 = not available. /// Maximum SWO UART Baudrate. -#define SWO_UART_MAX_BAUDRATE 50000000U ///< SWO UART Maximum Baudrate in Hz. +#define SWO_UART_MAX_BAUDRATE (115200U*40U) ///< SWO UART Maximum Baudrate in Hz. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz //// TODO: uncertain value diff --git a/components/DAP/include/uart_modify.h b/components/DAP/include/uart_modify.h new file mode 100644 index 0000000..3d3a277 --- /dev/null +++ b/components/DAP/include/uart_modify.h @@ -0,0 +1,565 @@ +/** + * @brief Made some simple modifications to the official UART + * + */ + +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _DRIVER_UART_H_ +#define _DRIVER_UART_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_log.h" +#include "freertos/queue.h" + +#define UART_FIFO_LEN (128) /*!< Length of the hardware FIFO buffers */ +#define UART_INTR_MASK 0x1ff /*!< Mask of all UART interrupts */ +#define UART_LINE_INV_MASK (0x3f << 19) /*!< TBD */ + +#define UART_INVERSE_DISABLE (0x0) /*!< Disable UART signal inverse*/ +#define UART_INVERSE_RXD (BIT(19)) /*!< UART RXD input inverse*/ +#define UART_INVERSE_CTS (BIT(20)) /*!< UART CTS input inverse*/ +#define UART_INVERSE_TXD (BIT(22)) /*!< UART TXD output inverse*/ +#define UART_INVERSE_RTS (BIT(23)) /*!< UART RTS output inverse*/ + +/** + * @brief UART mode selection + */ +typedef enum { + UART_MODE_UART = 0x00, /*!< mode: regular UART mode*/ +} uart_mode_t; + +/** + * @brief UART word length constants + */ +typedef enum { + UART_DATA_5_BITS = 0x0, /*!< word length: 5bits*/ + UART_DATA_6_BITS = 0x1, /*!< word length: 6bits*/ + UART_DATA_7_BITS = 0x2, /*!< word length: 7bits*/ + UART_DATA_8_BITS = 0x3, /*!< word length: 8bits*/ + UART_DATA_BITS_MAX = 0x4, +} uart_word_length_t; + +/** + * @brief UART stop bits number + */ +typedef enum { + UART_STOP_BITS_1 = 0x1, /*!< stop bit: 1bit*/ + UART_STOP_BITS_1_5 = 0x2, /*!< stop bit: 1.5bits*/ + UART_STOP_BITS_2 = 0x3, /*!< stop bit: 2bits*/ + UART_STOP_BITS_MAX = 0x4, +} uart_stop_bits_t; + +/** + * @brief UART peripheral number + */ +typedef enum { + UART_NUM_0 = 0x0, + UART_NUM_1 = 0x1, + UART_NUM_MAX, +} uart_port_t; + +/** + * @brief UART parity constants + */ +typedef enum { + UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/ + UART_PARITY_EVEN = 0x2, /*!< Enable UART even parity*/ + UART_PARITY_ODD = 0x3 /*!< Enable UART odd parity*/ +} uart_parity_t; + +/** + * @brief UART hardware flow control modes + */ +typedef enum { + UART_HW_FLOWCTRL_DISABLE = 0x0, /*!< disable hardware flow control*/ + UART_HW_FLOWCTRL_RTS = 0x1, /*!< enable RX hardware flow control (rts)*/ + UART_HW_FLOWCTRL_CTS = 0x2, /*!< enable TX hardware flow control (cts)*/ + UART_HW_FLOWCTRL_CTS_RTS = 0x3, /*!< enable hardware flow control*/ + UART_HW_FLOWCTRL_MAX = 0x4, +} uart_hw_flowcontrol_t; + +/** + * @brief UART configuration parameters for my_uart_param_config function + */ +typedef struct { + int baud_rate; /*!< UART baud rate*/ + uart_word_length_t data_bits; /*!< UART byte size*/ + uart_parity_t parity; /*!< UART parity mode*/ + uart_stop_bits_t stop_bits; /*!< UART stop bits*/ + uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode (cts/rts)*/ + uint8_t rx_flow_ctrl_thresh; /*!< UART HW RTS threshold*/ +} uart_config_t; + +/** + * @brief UART interrupt configuration parameters for my_uart_intr_config function + */ +typedef struct { + 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*/ + uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold (unit: time of sending one byte)*/ + uint8_t txfifo_empty_intr_thresh; /*!< UART TX empty interrupt threshold.*/ + uint8_t rxfifo_full_thresh; /*!< UART RX full interrupt threshold.*/ +} uart_intr_config_t; + +/** + * @brief UART event types used in the ring buffer + */ +typedef enum { + UART_DATA, /*!< UART data event*/ + UART_BUFFER_FULL, /*!< UART RX buffer full event*/ + UART_FIFO_OVF, /*!< UART FIFO overflow event*/ + UART_FRAME_ERR, /*!< UART RX frame error event*/ + UART_PARITY_ERR, /*!< UART RX parity event*/ + UART_EVENT_MAX, /*!< UART event max index*/ +} uart_event_type_t; + +/** + * @brief Event structure used in UART event queue + */ +typedef struct { + uart_event_type_t type; /*!< UART event type */ + size_t size; /*!< UART data size for UART_DATA event*/ +} uart_event_t; + + +/** + * @brief Set UART data bits. + * + * @param uart_num Uart port number. + * @param data_bit Uart data bits. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit); + +/** + * @brief Get UART data bits. + * + * @param uart_num Uart port number. + * @param data_bit Pointer to accept value of UART data bits. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data_bit); + +/** + * @brief Set UART stop bits. + * + * @param uart_num Uart port number + * @param stop_bits Uart stop bits + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits); + +/** + * @brief Get UART stop bits. + * + * @param uart_num Uart port number. + * @param stop_bits Pointer to accept value of UART stop bits. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bits); + +/** + * @brief Set UART parity mode. + * + * @param uart_num Uart port number. + * @param parity_mode The enum of uart parity configuration. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode); + +/** + * @brief Get UART parity mode. + * + * @param uart_num Uart port number + * @param parity_mode Pointer to accept value of UART parity mode. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode); + +/** + * @brief Set UART baud rate. + * + * @param uart_num Uart port number + * @param baudrate UART baud rate. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate); + +/** + * @brief Get UART baud rate. + * + * @param uart_num Uart port number. + * @param baudrate Pointer to accept value of Uart baud rate. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_baudrate(uart_port_t uart_num, uint32_t *baudrate); + +/** + * @brief Set UART line inverse mode + * + * @param uart_num UART_NUM_0 + * @param inverse_mask Choose the wires that need to be inverted. + * Inverse_mask should be chosen from + * UART_INVERSE_RXD / UART_INVERSE_TXD / UART_INVERSE_RTS / UART_INVERSE_CTS, + * combined with OR operation. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask); + +/** + * @brief Configure Hardware flow control. + * + * @param uart_num Uart port number. + * @param flow_ctrl Hardware flow control mode. + * @param rx_thresh Threshold of Hardware flow control. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh); + +/** + * @brief Get hardware flow control mode + * + * @param uart_num Uart port number. + * @param flow_ctrl Option for different flow control mode. + * + * @return + * - ESP_OK Success, result will be put in (*flow_ctrl) + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl); + +/** + * @brief UART0 swap. + * Use MTCK as UART0 RX, MTDO as UART0 TX, so ROM log will not output from + * this new UART0. We also need to use MTDO (U0RTS) and MTCK (U0CTS) as UART0 in hardware. + * + * @return + * - ESP_OK Success + */ +esp_err_t my_uart_enable_swap(void); + +/** + * @brief Disable UART0 swap. + * Use the original UART0, not MTCK and MTDO. + * + * @return + * - ESP_OK Success + */ +esp_err_t my_uart_disable_swap(void); + +/** + * @brief Clear uart interrupts status. + * + * @param uart_num Uart port number. + * @param mask Uart interrupt bits mask. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_clear_intr_status(uart_port_t uart_num, uint32_t mask); + +/** + * @brief Set UART interrupt enable + * + * @param uart_num Uart port number + * @param enable_mask Bit mask of the enable bits. + * The bit mask should be composed from the fields of register UART_INT_ENA_REG. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); + +/** + * @brief Clear UART interrupt enable bits + * + * @param uart_num Uart port number + * @param disable_mask Bit mask of the disable bits. + * The bit mask should be composed from the fields of register UART_INT_ENA_REG. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); + +/** + * @brief Enable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_enable_rx_intr(uart_port_t uart_num); + +/** + * @brief Disable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_disable_rx_intr(uart_port_t uart_num); + +/** + * @brief Disable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_disable_tx_intr(uart_port_t uart_num); + +/** + * @brief Enable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * @param enable 1: enable; 0: disable + * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); + +/** + * @brief Register UART interrupt handler (ISR). + * + * @param uart_num UART_NUM_0 + * @param fn Interrupt handler function. + * @param arg parameter for handler function + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg); + +/** + * @brief Config Common parameters of serial ports. + * + * @param uart_num Uart port number. + * @param uart_conf Uart config parameters. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_param_config(uart_port_t uart_num, uart_config_t *uart_conf); + +/** + * @brief Config types of uarts. + * + * @param uart_num Uart port number. + * @param uart_intr_conf Uart interrupt config parameters. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_intr_config(uart_port_t uart_num, uart_intr_config_t *uart_intr_conf); + +/** + * @brief Install UART driver. + * + * @note Rx_buffer_size should be greater than UART_FIFO_LEN. Tx_buffer_size should be either zero or greater than UART_FIFO_LEN. + * + * @param uart_num Uart port number. + * @param rx_buffer_size UART RX ring buffer size. + * @param tx_buffer_size UART TX ring buffer size. + * If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out. + * @param queue_size UART event queue size/depth. + * @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide + * access to UART events. If set to NULL, driver will not use an event queue. + * @param no_use Invalid parameters, just to fit some modules. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +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); + +/** + * @brief Uninstall UART driver. + * + * @param uart_num Uart port number. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_driver_delete(uart_port_t uart_num); + +/** + * @brief Waiting for the last byte of data to be sent + * + * @param uart_num Uart port number. + * @param ticks_to_wait Timeout, count in RTOS ticks + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); + +/** + * @brief Send data to the UART port from a given buffer and length. + * + * 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. + * @note This function should only be used when UART TX buffer is not enabled. + * + * @param uart_num Uart port number. + * @param buffer data buffer address + * @param len data length to send + * + * @return + * - (-1) Parameter error + * - OTHERS (>=0) The number of bytes pushed to the TX FIFO + */ +int my_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len); + +/** + * @brief Send data to the UART port from a given buffer and length, + * + * If the UART driver's parameter 'tx_buffer_size' is set to zero: + * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. + * + * Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer, + * UART ISR will then move data from the ring buffer to TX FIFO gradually. + * + * @param uart_num Uart port number. + * @param src data buffer address + * @param size data length to send + * + * @return + * - (-1) Parameter error + * - OTHERS (>=0) The number of bytes pushed to the TX FIFO + */ +int my_uart_write_bytes(uart_port_t uart_num, const char *src, size_t size); + +/** + * @brief UART read bytes from UART buffer + * + * @param uart_num Uart port number. + * @param buf pointer to the buffer. + * @param length data length + * @param ticks_to_wait sTimeout, count in RTOS ticks + * + * @return + * - (-1) Error + * - OTHERS (>=0) The number of bytes read from UART FIFO + */ +int my_uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, TickType_t ticks_to_wait); + +/** + * @brief Alias of my_uart_flush_input. + * UART ring buffer flush. This will discard all data in the UART RX buffer. + * @note Instead of waiting the data sent out, this function will clear UART rx buffer. + * In order to send all the data in tx FIFO, we can use my_uart_wait_tx_done function. + * @param uart_num UART port number. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_flush(uart_port_t uart_num); + +/** + * @brief Clear input buffer, discard all the data is in the ring-buffer. + * @note In order to send all the data in tx FIFO, we can use my_uart_wait_tx_done function. + * @param uart_num UART port number. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_flush_input(uart_port_t uart_num); + +/** + * @brief UART get RX ring buffer cached data length + * + * @param uart_num UART port number. + * @param size Pointer of size_t to accept cached data length + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_buffered_data_len(uart_port_t uart_num, size_t *size); + +/** + * @brief UART set threshold timeout for TOUT feature + * + * @param uart_num Uart number to configure + * @param tout_thresh This parameter defines timeout threshold in uart symbol periods. The maximum value of threshold is 126. + * tout_thresh = 1, defines TOUT interrupt timeout equal to transmission time of one symbol (~11 bit) on current baudrate. + * If the time is expired the UART_RXFIFO_TOUT_INT interrupt is triggered. If tout_thresh == 0, + * the TOUT feature is disabled. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh); + +#ifdef __cplusplus +} +#endif + +#endif // _DRIVER_UART_H_ diff --git a/components/DAP/source/SWO.c b/components/DAP/source/SWO.c index 241d9cb..d331a0c 100644 --- a/components/DAP/source/SWO.c +++ b/components/DAP/source/SWO.c @@ -1,3 +1,8 @@ +/** + * @brief Modify this file to fit esp8266 Uart + * + */ + /* * Copyright (c) 2013-2017 ARM Limited. All rights reserved. * @@ -27,14 +32,21 @@ #include "DAP_config.h" #include "DAP.h" -/* -#if (SWO_UART != 0) -#include "Driver_USART.h" -#endif -#if (SWO_STREAM != 0) -#include "cmsis_os2.h" -#endif -*/ + +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "uart_modify.h" + + +EventGroupHandle_t kSWO_Thread_event_group; +EventGroupHandle_t kUART_Monitoe_event_group; +#define SWO_GOT_DATA BIT0 +#define SWO_ERROR_TIME_OUT BIT1 + +#define UART_GOT_DATA BIT0 + #if (SWO_STREAM != 0) #ifdef DAP_FW_V1 @@ -44,28 +56,22 @@ #if (SWO_UART != 0) -#ifndef USART_PORT -#define USART_PORT 0 /* USART Port Number */ +#ifndef USART_PORT +#define USART_PORT UART_NUM_0 /* USART Port Number */ #endif -// USART Driver -#define _USART_Driver_(n) Driver_USART##n -#define USART_Driver_(n) _USART_Driver_(n) -extern ARM_DRIVER_USART USART_Driver_(USART_PORT); -#define pUSART (&USART_Driver_(USART_PORT)) + static uint8_t USART_Ready = 0U; -#endif /* (SWO_UART != 0) */ - +#endif /* (SWO_UART != 0) */ #if ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) +#define SWO_STREAM_TIMEOUT (50 / portTICK_RATE_MS) /* Stream timeout in ms */ -#define SWO_STREAM_TIMEOUT 50U /* Stream timeout in ms */ - -#define USB_BLOCK_SIZE 512U /* USB Block Size */ -#define TRACE_BLOCK_SIZE 64U /* Trace Block Size (2^n: 32...512) */ +#define USB_BLOCK_SIZE 512U /* USB Block Size */ +#define TRACE_BLOCK_SIZE 64U /* Trace Block Size (2^n: 32...512) */ // Trace State static uint8_t TraceTransport = 0U; /* Trace Transport */ @@ -81,145 +87,190 @@ static volatile uint32_t TraceIndexO = 0U; /* Outgoing Trace Index */ static volatile uint8_t TraceUpdate; /* Trace Update Flag */ static uint32_t TraceBlockSize; /* Current Trace Block Size */ -#if (TIMESTAMP_CLOCK != 0U) +#if (TIMESTAMP_CLOCK != 0U) // Trace Timestamp -static volatile struct { +static volatile struct +{ uint32_t index; uint32_t tick; } TraceTimestamp; #endif // Trace Helper functions -static void ClearTrace (void); -static void ResumeTrace (void); -static uint32_t GetTraceCount (void); -static uint8_t GetTraceStatus (void); -static void SetTraceError (uint8_t flag); +static void ClearTrace(void); +static void ResumeTrace(void); +static uint32_t GetTraceCount(void); +static uint8_t GetTraceStatus(void); +void SetTraceError(uint8_t flag); #if (SWO_STREAM != 0) -extern osThreadId_t SWO_ThreadId; -static volatile uint8_t TransferBusy = 0U; /* Transfer Busy Flag */ -static uint32_t TransferSize; /* Current Transfer Size */ -#endif +static volatile uint8_t TransferBusy = 0U; /* Transfer Busy Flag */ +static uint32_t TransferSize; /* Current Transfer Size */ +#endif #if (SWO_UART != 0) -// USART Driver Callback function -// event: event mask -static void USART_Callback (uint32_t event) { + +void usart_monitor_task(void *argument) +{ uint32_t index_i; uint32_t index_o; uint32_t count; uint32_t num; + uint32_t flags; - if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) { -#if (TIMESTAMP_CLOCK != 0U) - TraceTimestamp.tick = TIMESTAMP_GET(); + kUART_Monitoe_event_group = xEventGroupCreate(); + for (;;) + { + flags = xEventGroupWaitBits(kUART_Monitoe_event_group, UART_GOT_DATA, + pdTRUE, pdFALSE, portMAX_DELAY); + if (flags & UART_GOT_DATA) + { +#if (TIMESTAMP_CLOCK != 0U) + TraceTimestamp.tick = TIMESTAMP_GET(); #endif - index_o = TraceIndexO; - index_i = TraceIndexI; - index_i += TraceBlockSize; - TraceIndexI = index_i; -#if (TIMESTAMP_CLOCK != 0U) - TraceTimestamp.index = index_i; + index_o = TraceIndexO; + index_i = TraceIndexI; + index_i += TraceBlockSize; + TraceIndexI = index_i; +#if (TIMESTAMP_CLOCK != 0U) + TraceTimestamp.index = index_i; #endif - num = TRACE_BLOCK_SIZE - (index_i & (TRACE_BLOCK_SIZE - 1U)); - count = index_i - index_o; - if (count <= (SWO_BUFFER_SIZE - num)) { - index_i &= SWO_BUFFER_SIZE - 1U; - TraceBlockSize = num; - pUSART->Receive(&TraceBuf[index_i], num); - } else { - TraceStatus = DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED; - } - TraceUpdate = 1U; -#if (SWO_STREAM != 0) - if (TraceTransport == 2U) { - if (count >= (USB_BLOCK_SIZE - (index_o & (USB_BLOCK_SIZE - 1U)))) { - osThreadFlagsSet(SWO_ThreadId, 1U); + + num = TRACE_BLOCK_SIZE - (index_i & (TRACE_BLOCK_SIZE - 1U)); + // num is the number of bytes we need to read + // (to achieve the size of TRACE_BLOCK_SIZE) + count = index_i - index_o; + // Amount of data that has not been processed yet + + // (SWO_BUFFER_SIZE-num): the remaining usable length of the buffer after reading this data + if (count <= (SWO_BUFFER_SIZE - num)) + { + index_i &= SWO_BUFFER_SIZE - 1U; + TraceBlockSize = num; + my_uart_read_bytes(USART_PORT, &TraceBuf[index_i], num, 20 / portTICK_RATE_MS); + //pUSART->Receive(&TraceBuf[index_i], num); + } + else + { + // Not enough buffers + TraceStatus = DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED; + } + TraceUpdate = 1U; +#if (SWO_STREAM != 0) + if (TraceTransport == 2U) + { + if (count >= (USB_BLOCK_SIZE - (index_o & (USB_BLOCK_SIZE - 1U)))) + { + xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA); + } } - } #endif + } } - if (event & ARM_USART_EVENT_RX_OVERFLOW) { - SetTraceError(DAP_SWO_BUFFER_OVERRUN); - } - if (event & (ARM_USART_EVENT_RX_BREAK | - ARM_USART_EVENT_RX_FRAMING_ERROR | - ARM_USART_EVENT_RX_PARITY_ERROR)) { - SetTraceError(DAP_SWO_STREAM_ERROR); - } + + // if (event & ARM_USART_EVENT_RX_OVERFLOW) + // { + // SetTraceError(DAP_SWO_BUFFER_OVERRUN); + // } + // if (event & (ARM_USART_EVENT_RX_BREAK | + // ARM_USART_EVENT_RX_FRAMING_ERROR | + // ARM_USART_EVENT_RX_PARITY_ERROR)) + // { + // SetTraceError(DAP_SWO_STREAM_ERROR); + // } } // Enable or disable UART SWO Mode // enable: enable flag // return: 1 - Success, 0 - Error -__WEAK uint32_t UART_SWO_Mode (uint32_t enable) { +__WEAK uint32_t UART_SWO_Mode(uint32_t enable) +{ int32_t status; USART_Ready = 0U; + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE}; + my_uart_param_config(USART_PORT, &uart_config); - if (enable != 0U) { - status = pUSART->Initialize(USART_Callback); - if (status != ARM_DRIVER_OK) { +#define BUF_SIZE (1024) + my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0); + + if (enable != 0U) + { + my_uart_param_config(USART_PORT, &uart_config); + status = my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0); + if (status != ESP_OK) + { return (0U); } - status = pUSART->PowerControl(ARM_POWER_FULL); - if (status != ARM_DRIVER_OK) { - pUSART->Uninitialize(); - return (0U); - } - } else { - pUSART->Control(ARM_USART_CONTROL_RX, 0U); - pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); - pUSART->PowerControl(ARM_POWER_OFF); - pUSART->Uninitialize(); + } + else + { + my_uart_driver_delete(USART_PORT); } return (1U); + + } // Configure UART SWO Baudrate // baudrate: requested baudrate // return: actual baudrate or 0 when not configured -__WEAK uint32_t UART_SWO_Baudrate (uint32_t baudrate) { - int32_t status; +__WEAK uint32_t UART_SWO_Baudrate(uint32_t baudrate) +{ + int32_t status; uint32_t index; uint32_t num; - if (baudrate > SWO_UART_MAX_BAUDRATE) { + if (baudrate > SWO_UART_MAX_BAUDRATE) + { baudrate = SWO_UART_MAX_BAUDRATE; } - if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { - pUSART->Control(ARM_USART_CONTROL_RX, 0U); - if (pUSART->GetStatus().rx_busy) { - TraceIndexI += pUSART->GetRxCount(); - pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); - } + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) + { + size_t len = 0; + my_uart_get_buffered_data_len(USART_PORT, &len); + my_uart_flush(USART_PORT); + TraceIndexI += len; + // pUSART->Control(ARM_USART_CONTROL_RX, 0U); + // if (pUSART->GetStatus().rx_busy) + // { + // TraceIndexI += pUSART->GetRxCount(); + // pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); + // } } - status = pUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | - ARM_USART_DATA_BITS_8 | - ARM_USART_PARITY_NONE | - ARM_USART_STOP_BITS_1, - baudrate); + ///////////// + status = my_uart_set_baudrate(USART_PORT, baudrate); - if (status == ARM_DRIVER_OK) { + if (status == ESP_OK) + { USART_Ready = 1U; - } else { + } + else + { USART_Ready = 0U; return (0U); } - - if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { - if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 0U) { + + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) + { + if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 0U) + { index = TraceIndexI & (SWO_BUFFER_SIZE - 1U); num = TRACE_BLOCK_SIZE - (index & (TRACE_BLOCK_SIZE - 1U)); TraceBlockSize = num; - pUSART->Receive(&TraceBuf[index], num); + //pUSART->Receive(&TraceBuf[index], num); + my_uart_read_bytes(USART_PORT, &TraceBuf[index], num, 20 / portTICK_RATE_MS); } - pUSART->Control(ARM_USART_CONTROL_RX, 1U); + //pUSART->Control(ARM_USART_CONTROL_RX, 1U); ////TODO: } return (baudrate); @@ -228,28 +279,40 @@ __WEAK uint32_t UART_SWO_Baudrate (uint32_t baudrate) { // Control UART SWO Capture // active: active flag // return: 1 - Success, 0 - Error -__WEAK uint32_t UART_SWO_Control (uint32_t active) { +__WEAK uint32_t UART_SWO_Control(uint32_t active) +{ int32_t status; - if (active) { - if (!USART_Ready) { + if (active) + { + if (!USART_Ready) + { return (0U); } TraceBlockSize = 1U; - status = pUSART->Receive(&TraceBuf[0], 1U); - if (status != ARM_DRIVER_OK) { + status = my_uart_read_bytes(USART_PORT, &TraceBuf[0], 1U, 20 / portTICK_RATE_MS); + if (status == ESP_FAIL) + { return (0U); } - status = pUSART->Control(ARM_USART_CONTROL_RX, 1U); - if (status != ARM_DRIVER_OK) { - return (0U); - } - } else { - pUSART->Control(ARM_USART_CONTROL_RX, 0U); - if (pUSART->GetStatus().rx_busy) { - TraceIndexI += pUSART->GetRxCount(); - pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); - } + // status = pUSART->Control(ARM_USART_CONTROL_RX, 1U); + // if (status != ARM_DRIVER_OK) + // { + // return (0U); + // } ////TODO: + } + else + { + size_t len = 0; + my_uart_get_buffered_data_len(USART_PORT, &len); + my_uart_flush(USART_PORT); + TraceIndexI += len; + // pUSART->Control(ARM_USART_CONTROL_RX, 0U); + // if (pUSART->GetStatus().rx_busy) + // { + // TraceIndexI += pUSART->GetRxCount(); + // pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); + // } } return (1U); } @@ -257,70 +320,83 @@ __WEAK uint32_t UART_SWO_Control (uint32_t active) { // Start UART SWO Capture // buf: pointer to buffer for capturing // num: number of bytes to capture -__WEAK void UART_SWO_Capture (uint8_t *buf, uint32_t num) { +__WEAK void UART_SWO_Capture(uint8_t *buf, uint32_t num) +{ TraceBlockSize = num; - pUSART->Receive(buf, num); + my_uart_read_bytes(USART_PORT, buf, num, 20 / portTICK_RATE_MS); } // Get UART SWO Pending Trace Count // return: number of pending trace data bytes -__WEAK uint32_t UART_SWO_GetCount (void) { +__WEAK uint32_t UART_SWO_GetCount(void) +{ uint32_t count; - if (pUSART->GetStatus().rx_busy) { - count = pUSART->GetRxCount(); - } else { - count = 0U; - } + // if (pUSART->GetStatus().rx_busy) + // { + // count = pUSART->GetRxCount(); + // } + // else + // { + // count = 0U; + // } + my_uart_get_buffered_data_len(USART_PORT, &count); return (count); } -#endif /* (SWO_UART != 0) */ - +#endif /* (SWO_UART != 0) */ #if (SWO_MANCHESTER != 0) // Enable or disable Manchester SWO Mode // enable: enable flag // return: 1 - Success, 0 - Error -__WEAK uint32_t Manchester_SWO_Mode (uint32_t enable) { +__WEAK uint32_t Manchester_SWO_Mode(uint32_t enable) +{ return (0U); } // Configure Manchester SWO Baudrate // baudrate: requested baudrate // return: actual baudrate or 0 when not configured -__WEAK uint32_t Manchester_SWO_Baudrate (uint32_t baudrate) { +__WEAK uint32_t Manchester_SWO_Baudrate(uint32_t baudrate) +{ return (0U); } // Control Manchester SWO Capture // active: active flag // return: 1 - Success, 0 - Error -__WEAK uint32_t Manchester_SWO_Control (uint32_t active) { +__WEAK uint32_t Manchester_SWO_Control(uint32_t active) +{ return (0U); } // Start Manchester SWO Capture // buf: pointer to buffer for capturing // num: number of bytes to capture -__WEAK void Manchester_SWO_Capture (uint8_t *buf, uint32_t num) { +__WEAK void Manchester_SWO_Capture(uint8_t *buf, uint32_t num) +{ } // Get Manchester SWO Pending Trace Count // return: number of pending trace data bytes -__WEAK uint32_t Manchester_SWO_GetCount (void) { +__WEAK uint32_t Manchester_SWO_GetCount(void) +{ + return (0U); } -#endif /* (SWO_MANCHESTER != 0) */ - +#endif /* (SWO_MANCHESTER != 0) */ // Clear Trace Errors and Data -static void ClearTrace (void) { +static void ClearTrace(void) +{ #if (SWO_STREAM != 0) - if (TraceTransport == 2U) { - if (TransferBusy != 0U) { + if (TraceTransport == 2U) + { + if (TransferBusy != 0U) + { SWO_AbortTransfer(); TransferBusy = 0U; } @@ -329,41 +405,45 @@ static void ClearTrace (void) { TraceError[0] = 0U; TraceError[1] = 0U; - TraceError_n = 0U; - TraceIndexI = 0U; - TraceIndexO = 0U; + TraceError_n = 0U; + TraceIndexI = 0U; + TraceIndexO = 0U; -#if (TIMESTAMP_CLOCK != 0U) +#if (TIMESTAMP_CLOCK != 0U) TraceTimestamp.index = 0U; - TraceTimestamp.tick = 0U; + TraceTimestamp.tick = 0U; #endif } // Resume Trace Capture -static void ResumeTrace (void) { +static void ResumeTrace(void) +{ uint32_t index_i; uint32_t index_o; - if (TraceStatus == (DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED)) { + if (TraceStatus == (DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED)) + { index_i = TraceIndexI; index_o = TraceIndexO; - if ((index_i - index_o) < SWO_BUFFER_SIZE) { + if ((index_i - index_o) < SWO_BUFFER_SIZE) + { index_i &= SWO_BUFFER_SIZE - 1U; - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - TraceStatus = DAP_SWO_CAPTURE_ACTIVE; - UART_SWO_Capture(&TraceBuf[index_i], 1U); - break; + case DAP_SWO_UART: + TraceStatus = DAP_SWO_CAPTURE_ACTIVE; + UART_SWO_Capture(&TraceBuf[index_i], 1U); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - TraceStatus = DAP_SWO_CAPTURE_ACTIVE; - Manchester_SWO_Capture(&TraceBuf[index_i], 1U); - break; + case DAP_SWO_MANCHESTER: + TraceStatus = DAP_SWO_CAPTURE_ACTIVE; + Manchester_SWO_Capture(&TraceBuf[index_i], 1U); + break; #endif - default: - break; + default: + break; } } } @@ -371,29 +451,35 @@ static void ResumeTrace (void) { // Get Trace Count // return: number of available data bytes in trace buffer -static uint32_t GetTraceCount (void) { +static uint32_t GetTraceCount(void) +{ uint32_t count; - if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) { - do { + if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) + { + do + { TraceUpdate = 0U; count = TraceIndexI - TraceIndexO; - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - count += UART_SWO_GetCount(); - break; + case DAP_SWO_UART: + count += UART_SWO_GetCount(); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - count += Manchester_SWO_GetCount(); - break; + case DAP_SWO_MANCHESTER: + count += Manchester_SWO_GetCount(); + break; #endif - default: - break; + default: + break; } } while (TraceUpdate != 0U); - } else { + } + else + { count = TraceIndexI - TraceIndexO; } @@ -402,8 +488,9 @@ static uint32_t GetTraceCount (void) { // Get Trace Status (clear Error flags) // return: Trace Status (Active flag and Error flags) -static uint8_t GetTraceStatus (void) { - uint8_t status; +static uint8_t GetTraceStatus(void) +{ + uint8_t status; uint32_t n; n = TraceError_n; @@ -416,235 +503,263 @@ static uint8_t GetTraceStatus (void) { // Set Trace Error flag(s) // flag: error flag(s) to set -static void SetTraceError (uint8_t flag) { +void SetTraceError(uint8_t flag) +{ TraceError[TraceError_n] |= flag; } - // Process SWO Transport command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Transport (const uint8_t *request, uint8_t *response) { - uint8_t transport; +uint32_t SWO_Transport(const uint8_t *request, uint8_t *response) +{ + uint8_t transport; uint32_t result; - if ((TraceStatus & DAP_SWO_CAPTURE_ACTIVE) == 0U) { + if ((TraceStatus & DAP_SWO_CAPTURE_ACTIVE) == 0U) + { transport = *request; - switch (transport) { - case 0U: - case 1U: + switch (transport) + { + case 0U: + case 1U: #if (SWO_STREAM != 0) - case 2U: + case 2U: #endif - TraceTransport = transport; - result = 1U; - break; - default: - result = 0U; - break; + TraceTransport = transport; + result = 1U; + break; + default: + result = 0U; + break; } - } else { + } + else + { result = 0U; } - if (result != 0U) { + if (result != 0U) + { *response = DAP_OK; - } else { + } + else + { *response = DAP_ERROR; } return ((1U << 16) | 1U); } - // Process SWO Mode command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Mode (const uint8_t *request, uint8_t *response) { - uint8_t mode; +uint32_t SWO_Mode(const uint8_t *request, uint8_t *response) +{ + uint8_t mode; uint32_t result; mode = *request; - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - UART_SWO_Mode(0U); - break; + case DAP_SWO_UART: + UART_SWO_Mode(0U); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - Manchester_SWO_Mode(0U); - break; + case DAP_SWO_MANCHESTER: + Manchester_SWO_Mode(0U); + break; #endif - default: - break; + default: + break; } - switch (mode) { - case DAP_SWO_OFF: - result = 1U; - break; + switch (mode) + { + case DAP_SWO_OFF: + result = 1U; + break; #if (SWO_UART != 0) - case DAP_SWO_UART: - result = UART_SWO_Mode(1U); - break; + case DAP_SWO_UART: + result = UART_SWO_Mode(1U); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - result = Manchester_SWO_Mode(1U); - break; + case DAP_SWO_MANCHESTER: + result = Manchester_SWO_Mode(1U); + break; #endif - default: - result = 0U; - break; + default: + result = 0U; + break; } - if (result != 0U) { + if (result != 0U) + { TraceMode = mode; - } else { + } + else + { TraceMode = DAP_SWO_OFF; } TraceStatus = 0U; - if (result != 0U) { + if (result != 0U) + { *response = DAP_OK; - } else { + } + else + { *response = DAP_ERROR; } return ((1U << 16) | 1U); } - // Process SWO Baudrate command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response) { +uint32_t SWO_Baudrate(const uint8_t *request, uint8_t *response) +{ uint32_t baudrate; - baudrate = (uint32_t)(*(request+0) << 0) | - (uint32_t)(*(request+1) << 8) | - (uint32_t)(*(request+2) << 16) | - (uint32_t)(*(request+3) << 24); + baudrate = (uint32_t)(*(request + 0) << 0) | + (uint32_t)(*(request + 1) << 8) | + (uint32_t)(*(request + 2) << 16) | + (uint32_t)(*(request + 3) << 24); - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - baudrate = UART_SWO_Baudrate(baudrate); - break; + case DAP_SWO_UART: + baudrate = UART_SWO_Baudrate(baudrate); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - baudrate = Manchester_SWO_Baudrate(baudrate); - break; + case DAP_SWO_MANCHESTER: + baudrate = Manchester_SWO_Baudrate(baudrate); + break; #endif - default: - baudrate = 0U; - break; + default: + baudrate = 0U; + break; } - if (baudrate == 0U) { + if (baudrate == 0U) + { TraceStatus = 0U; } - *response++ = (uint8_t)(baudrate >> 0); - *response++ = (uint8_t)(baudrate >> 8); + *response++ = (uint8_t)(baudrate >> 0); + *response++ = (uint8_t)(baudrate >> 8); *response++ = (uint8_t)(baudrate >> 16); - *response = (uint8_t)(baudrate >> 24); + *response = (uint8_t)(baudrate >> 24); return ((4U << 16) | 4U); } - // Process SWO Control command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Control (const uint8_t *request, uint8_t *response) { - uint8_t active; +uint32_t SWO_Control(const uint8_t *request, uint8_t *response) +{ + uint8_t active; uint32_t result; active = *request & DAP_SWO_CAPTURE_ACTIVE; - if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) { - if (active) { + if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) + { + if (active) + { ClearTrace(); } - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - result = UART_SWO_Control(active); - break; + case DAP_SWO_UART: + result = UART_SWO_Control(active); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - result = Manchester_SWO_Control(active); - break; + case DAP_SWO_MANCHESTER: + result = Manchester_SWO_Control(active); + break; #endif - default: - result = 0U; - break; + default: + result = 0U; + break; } - if (result != 0U) { + if (result != 0U) + { TraceStatus = active; #if (SWO_STREAM != 0) - if (TraceTransport == 2U) { - osThreadFlagsSet(SWO_ThreadId, 1U); + if (TraceTransport == 2U) + { + xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA); } #endif } - } else { + } + else + { result = 1U; } - if (result != 0U) { + if (result != 0U) + { *response = DAP_OK; - } else { + } + else + { *response = DAP_ERROR; } return ((1U << 16) | 1U); } - // Process SWO Status command and prepare response // response: pointer to response data // return: number of bytes in response -uint32_t SWO_Status (uint8_t *response) { - uint8_t status; +uint32_t SWO_Status(uint8_t *response) +{ + uint8_t status; uint32_t count; status = GetTraceStatus(); - count = GetTraceCount(); + count = GetTraceCount(); *response++ = status; - *response++ = (uint8_t)(count >> 0); - *response++ = (uint8_t)(count >> 8); + *response++ = (uint8_t)(count >> 0); + *response++ = (uint8_t)(count >> 8); *response++ = (uint8_t)(count >> 16); - *response = (uint8_t)(count >> 24); + *response = (uint8_t)(count >> 24); return (5U); } - // Process SWO Extended Status command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response) { - uint8_t cmd; - uint8_t status; +uint32_t SWO_ExtendedStatus(const uint8_t *request, uint8_t *response) +{ + uint8_t cmd; + uint8_t status; uint32_t count; -#if (TIMESTAMP_CLOCK != 0U) +#if (TIMESTAMP_CLOCK != 0U) uint32_t index; uint32_t tick; #endif @@ -653,36 +768,40 @@ uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response) { num = 0U; cmd = *request; - if (cmd & 0x01U) { + if (cmd & 0x01U) + { status = GetTraceStatus(); *response++ = status; num += 1U; } - if (cmd & 0x02U) { + if (cmd & 0x02U) + { count = GetTraceCount(); - *response++ = (uint8_t)(count >> 0); - *response++ = (uint8_t)(count >> 8); + *response++ = (uint8_t)(count >> 0); + *response++ = (uint8_t)(count >> 8); *response++ = (uint8_t)(count >> 16); *response++ = (uint8_t)(count >> 24); num += 4U; } -#if (TIMESTAMP_CLOCK != 0U) - if (cmd & 0x04U) { - do { +#if (TIMESTAMP_CLOCK != 0U) + if (cmd & 0x04U) + { + do + { TraceUpdate = 0U; index = TraceTimestamp.index; - tick = TraceTimestamp.tick; + tick = TraceTimestamp.tick; } while (TraceUpdate != 0U); - *response++ = (uint8_t)(index >> 0); - *response++ = (uint8_t)(index >> 8); + *response++ = (uint8_t)(index >> 0); + *response++ = (uint8_t)(index >> 8); *response++ = (uint8_t)(index >> 16); *response++ = (uint8_t)(index >> 24); - *response++ = (uint8_t)(tick >> 0); - *response++ = (uint8_t)(tick >> 8); - *response++ = (uint8_t)(tick >> 16); - *response++ = (uint8_t)(tick >> 24); + *response++ = (uint8_t)(tick >> 0); + *response++ = (uint8_t)(tick >> 8); + *response++ = (uint8_t)(tick >> 16); + *response++ = (uint8_t)(tick >> 24); num += 4U; } #endif @@ -690,31 +809,36 @@ uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response) { return ((1U << 16) | num); } - // Process SWO Data command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Data (const uint8_t *request, uint8_t *response) { - uint8_t status; +uint32_t SWO_Data(const uint8_t *request, uint8_t *response) +{ + uint8_t status; uint32_t count; uint32_t index; uint32_t n, i; status = GetTraceStatus(); - count = GetTraceCount(); + count = GetTraceCount(); - if (TraceTransport == 1U) { - n = (uint32_t)(*(request+0) << 0) | - (uint32_t)(*(request+1) << 8); - if (n > (DAP_PACKET_SIZE - 4U)) { + if (TraceTransport == 1U) + { + n = (uint32_t)(*(request + 0) << 0) | + (uint32_t)(*(request + 1) << 8); + if (n > (DAP_PACKET_SIZE - 4U)) + { n = DAP_PACKET_SIZE - 4U; } - if (count > n) { + if (count > n) + { count = n; } - } else { + } + else + { count = 0U; } @@ -722,9 +846,11 @@ uint32_t SWO_Data (const uint8_t *request, uint8_t *response) { *response++ = (uint8_t)(count >> 0); *response++ = (uint8_t)(count >> 8); - if (TraceTransport == 1U) { + if (TraceTransport == 1U) + { index = TraceIndexO; - for (i = index, n = count; n; n--) { + for (i = index, n = count; n; n--) + { i &= SWO_BUFFER_SIZE - 1U; *response++ = TraceBuf[i++]; } @@ -735,68 +861,86 @@ uint32_t SWO_Data (const uint8_t *request, uint8_t *response) { return ((2U << 16) | (3U + count)); } - #if (SWO_STREAM != 0) // SWO Data Transfer complete callback -void SWO_TransferComplete (void) { +void SWO_TransferComplete(void) +{ TraceIndexO += TransferSize; TransferBusy = 0U; ResumeTrace(); - osThreadFlagsSet(SWO_ThreadId, 1U); + xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA); } // SWO Thread -__NO_RETURN void SWO_Thread (void *argument) { +void SWO_Thread(void *argument) +{ uint32_t timeout; uint32_t flags; uint32_t count; uint32_t index; uint32_t i, n; - (void) argument; + (void)argument; - timeout = osWaitForever; - - for (;;) { - flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout); - if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { + timeout = portMAX_DELAY; + + kSWO_Thread_event_group = xEventGroupCreate(); + for (;;) + { + flags = xEventGroupWaitBits(kSWO_Thread_event_group, SWO_GOT_DATA | SWO_ERROR_TIME_OUT, + pdTRUE, pdFALSE, timeout); + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) + { timeout = SWO_STREAM_TIMEOUT; - } else { - timeout = osWaitForever; - flags = osFlagsErrorTimeout; } - if (TransferBusy == 0U) { + else + { + timeout = portMAX_DELAY; + flags = SWO_ERROR_TIME_OUT; + } + if (TransferBusy == 0U) + { count = GetTraceCount(); - if (count != 0U) { + if (count != 0U) + { index = TraceIndexO & (SWO_BUFFER_SIZE - 1U); n = SWO_BUFFER_SIZE - index; - if (count > n) { + if (count > n) + { count = n; } - if (flags != osFlagsErrorTimeout) { + if ((flags & SWO_ERROR_TIME_OUT) == 0) + { i = index & (USB_BLOCK_SIZE - 1U); - if (i == 0U) { + if (i == 0U) + { count &= ~(USB_BLOCK_SIZE - 1U); - } else { + // Take down to the nearest number that is a multiple of USB_BLOCK_SIZE + } + else + { n = USB_BLOCK_SIZE - i; - if (count >= n) { + if (count >= n) + { count = n; - } else { + } + else + { count = 0U; } } } - if (count != 0U) { + if (count != 0U) + { TransferSize = count; TransferBusy = 1U; - SWO_QueueTransfer(&TraceBuf[index], count); + SWO_QueueTransfer(&TraceBuf[index], count); //through USB } } } } } -#endif /* (SWO_STREAM != 0) */ +#endif /* (SWO_STREAM != 0) */ - -#endif /* ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) */ +#endif /* ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) */ diff --git a/components/DAP/source/uart_modify.c b/components/DAP/source/uart_modify.c new file mode 100644 index 0000000..e485482 --- /dev/null +++ b/components/DAP/source/uart_modify.c @@ -0,0 +1,1256 @@ +/** + * @brief Made some simple modifications to the official UART + * + */ + +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/ringbuf.h" +#include "freertos/event_groups.h" + +#include "esp_err.h" +#include "esp_log.h" +#include "esp_attr.h" + +// SWO modify +#include "DAP_config.h" +#include "esp8266/uart_struct.h" +#include "esp8266/uart_register.h" +#include "esp8266/pin_mux_register.h" +#include "esp8266/eagle_soc.h" +#include "esp8266/rom_functions.h" + +#include "rom/ets_sys.h" + +#include "uart_modify.h" +#include "driver/uart_select.h" + +#define portYIELD_FROM_ISR() taskYIELD() + +#define UART_ENTER_CRITICAL() portENTER_CRITICAL() +#define UART_EXIT_CRITICAL() portEXIT_CRITICAL() + +static const char *UART_TAG = "uart"; +#define UART_CHECK(a, str, ret_val) \ + if (!(a)) \ + { \ + ESP_LOGE(UART_TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +#define UART_EMPTY_THRESH_DEFAULT (10) +#define UART_FULL_THRESH_DEFAULT (120) +#define UART_TOUT_THRESH_DEFAULT (10) + +typedef struct +{ + uart_event_type_t type; /*!< UART TX data type */ + struct + { + size_t size; + uint8_t data[0]; + } tx_data; +} uart_tx_data_t; + +typedef struct +{ + uart_port_t uart_num; /*!< UART port number*/ + int queue_size; /*!< UART event queue size*/ + QueueHandle_t xQueueUart; /*!< UART queue handler*/ + uart_mode_t uart_mode; /*!< UART controller actual mode set by uart_set_mode() */ + + // rx parameters + int rx_buffered_len; /*!< UART cached data length */ + SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/ + int rx_buf_size; /*!< RX ring buffer size */ + RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler*/ + bool rx_buffer_full_flg; /*!< RX ring buffer full flag. */ + int rx_cur_remain; /*!< Data number that waiting to be read out in ring buffer item*/ + uint8_t *rx_ptr; /*!< pointer to the current data in ring buffer*/ + uint8_t *rx_head_ptr; /*!< pointer to the head of RX item*/ + uint8_t rx_data_buf[UART_FIFO_LEN]; /*!< Data buffer to stash FIFO data*/ + uint8_t rx_stash_len; /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */ + + // tx parameters + SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ + SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ + SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ + int tx_buf_size; /*!< TX ring buffer size */ + RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ + bool tx_waiting_fifo; /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/ + uint8_t *tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ + uart_tx_data_t *tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ + uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ + uint32_t tx_len_cur; + bool wait_tx_done_flg; + uart_select_notif_callback_t uart_select_notif_callback; /*!< Notification about select() events */ +} uart_obj_t; + +static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; +// DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR +static DRAM_ATTR uart_dev_t *const UART[UART_NUM_MAX] = {&uart0, &uart1}; + +typedef void (*uart_isr_t)(void *); +typedef struct +{ + uart_isr_t fn; /*!< isr function */ + void *args; /*!< isr function args */ +} uart_isr_func_t; + +static uart_isr_func_t uart_isr_func[UART_NUM_MAX]; + +// SWO modify +extern EventGroupHandle_t kUART_Monitoe_event_group; +#define UART_GOT_DATA BIT0 +extern void SetTraceError(uint8_t flag); +#define DAP_SWO_CAPTURE_ACTIVE (1U << 0) +#define DAP_SWO_CAPTURE_PAUSED (1U << 1) +#define DAP_SWO_STREAM_ERROR (1U << 6) +#define DAP_SWO_BUFFER_OVERRUN (1U << 7) +// + +esp_err_t my_uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((data_bit < UART_DATA_BITS_MAX), "data bit error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->conf0.bit_num = data_bit; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data_bit) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((data_bit), "empty pointer", ESP_FAIL); + + *(data_bit) = UART[uart_num]->conf0.bit_num; + return ESP_OK; +} + +esp_err_t my_uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->conf0.stop_bit_num = stop_bit; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bit) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((stop_bit), "empty pointer", ESP_FAIL); + + (*stop_bit) = UART[uart_num]->conf0.stop_bit_num; + return ESP_OK; +} + +esp_err_t my_uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK(((parity_mode == UART_PARITY_DISABLE) || (parity_mode == UART_PARITY_EVEN) || (parity_mode == UART_PARITY_ODD)), + "parity_mode error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->conf0.parity = (parity_mode & 0x1); + UART[uart_num]->conf0.parity_en = ((parity_mode >> 1) & 0x1); + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((parity_mode), "empty pointer", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + + if (UART[uart_num]->conf0.parity_en) + { + if (UART[uart_num]->conf0.parity) + { + (*parity_mode) = UART_PARITY_ODD; + } + else + { + (*parity_mode) = UART_PARITY_EVEN; + } + } + else + { + (*parity_mode) = UART_PARITY_DISABLE; + } + + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->clk_div.val = (uint32_t)(UART_CLK_FREQ / baud_rate) & 0xFFFFF; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_get_baudrate(uart_port_t uart_num, uint32_t *baudrate) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((baudrate), "empty pointer", ESP_ERR_INVALID_ARG); + + (*baudrate) = (UART_CLK_FREQ / (UART[uart_num]->clk_div.val & 0xFFFFF)); + return ESP_OK; +} + +esp_err_t my_uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((((inverse_mask & ~UART_LINE_INV_MASK) == 0) || (inverse_mask == 0)), "inverse_mask error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->conf0.val &= ~UART_LINE_INV_MASK; + UART[uart_num]->conf0.val |= inverse_mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((flow_ctrl < UART_HW_FLOWCTRL_MAX), "uart_flow ctrl error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + + if (flow_ctrl & UART_HW_FLOWCTRL_RTS) + { + UART[uart_num]->conf1.rx_flow_thrhd = rx_thresh; + UART[uart_num]->conf1.rx_flow_en = 1; + } + else + { + UART[uart_num]->conf1.rx_flow_en = 0; + } + + if (flow_ctrl & UART_HW_FLOWCTRL_CTS) + { + UART[uart_num]->conf0.tx_flow_en = 1; + } + else + { + UART[uart_num]->conf0.tx_flow_en = 0; + } + + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + uart_hw_flowcontrol_t val = UART_HW_FLOWCTRL_DISABLE; + + if (UART[uart_num]->conf1.rx_flow_en) + { + val |= UART_HW_FLOWCTRL_RTS; + } + + if (UART[uart_num]->conf0.tx_flow_en) + { + val |= UART_HW_FLOWCTRL_CTS; + } + + (*flow_ctrl) = val; + return ESP_OK; +} + +esp_err_t my_uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_ARG); + uint32_t baudrate; + uint32_t byte_delay_us = 0; + BaseType_t res; + portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; + + // Take tx_mux + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); + if (res == pdFALSE) + { + return ESP_ERR_TIMEOUT; + } + + if (false == p_uart_obj[uart_num]->wait_tx_done_flg) + { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_OK; + } + + my_uart_get_baudrate(uart_num, &baudrate); + byte_delay_us = (uint32_t)(10000000 / baudrate); // (1/baudrate)*10*1000_000 us + + ticks_to_wait = ticks_end - xTaskGetTickCount(); + // wait for tx done sem. + if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, ticks_to_wait)) + { + while (1) + { + if (UART[uart_num]->status.txfifo_cnt == 0) + { + ets_delay_us(byte_delay_us); // Delay one byte time to guarantee transmission completion + break; + } + } + p_uart_obj[uart_num]->wait_tx_done_flg = false; + } + else + { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_ERR_TIMEOUT; + } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_OK; +} + +esp_err_t my_uart_enable_swap(void) +{ + // wait for tx done. + my_uart_wait_tx_done(UART_NUM_0, portMAX_DELAY); + + UART_ENTER_CRITICAL(); + // MTCK -> UART0_CTS -> U0RXD + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); + // MTD0 -> UART0_RTS -> U0TXD + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_UART0_RTS); + // enable swap U0TXD <-> UART0_RTS and U0RXD <-> UART0_CTS + SET_PERI_REG_MASK(UART_SWAP_REG, 0x4); + UART_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t my_uart_disable_swap(void) +{ + // wait for tx done. + my_uart_wait_tx_done(UART_NUM_0, portMAX_DELAY); + + UART_ENTER_CRITICAL(); + // disable swap U0TXD <-> UART0_RTS and U0RXD <-> UART0_CTS + CLEAR_PERI_REG_MASK(UART_SWAP_REG, 0x4); + UART_EXIT_CRITICAL(); + + return ESP_OK; +} + +static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->conf0.rxfifo_rst = 0x1; + UART[uart_num]->conf0.rxfifo_rst = 0x0; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_clear_intr_status(uart_port_t uart_num, uint32_t mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->int_clr.val |= mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->int_ena.val |= enable_mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->int_ena.val &= ~disable_mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_enable_rx_intr(uart_port_t uart_num) +{ + return my_uart_enable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA); +} + +esp_err_t my_uart_disable_rx_intr(uart_port_t uart_num) +{ + return my_uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA); +} + +esp_err_t my_uart_disable_tx_intr(uart_port_t uart_num) +{ + return my_uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA); +} + +esp_err_t my_uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((thresh < UART_FIFO_LEN), "empty intr threshold error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->int_clr.txfifo_empty = 1; + UART[uart_num]->conf1.txfifo_empty_thrhd = thresh & 0x7f; + UART[uart_num]->int_ena.txfifo_empty = enable & 0x1; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +static void uart_intr_service(void *arg) +{ + // UART intr process + uint32_t uart_num = 0; + // read status to get interrupt status for UART0-1 + uint32_t uart_intr_status = UART[uart_num]->int_st.val; + + if (uart_isr_func == NULL) + { + return; + } + + do + { + uart_intr_status = UART[uart_num]->int_st.val; + if (uart_intr_status != 0) + { + if (uart_isr_func[uart_num].fn != NULL) + { + uart_isr_func[uart_num].fn(uart_isr_func[uart_num].args); + } + } + } while (++uart_num < UART_NUM_MAX); +} + +esp_err_t my_uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + _xt_isr_mask(1 << ETS_UART_INUM); + _xt_isr_attach(ETS_UART_INUM, uart_intr_service, NULL); + uart_isr_func[uart_num].fn = fn; + uart_isr_func[uart_num].args = arg; + _xt_isr_unmask(1 << ETS_UART_INUM); + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_param_config(uart_port_t uart_num, uart_config_t *uart_conf) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + if (uart_num == UART_NUM_1) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); + } + else + { + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); + + if (uart_conf->flow_ctrl & UART_HW_FLOWCTRL_RTS) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); + } + + if (uart_conf->flow_ctrl & UART_HW_FLOWCTRL_CTS) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); + } + + my_uart_set_hw_flow_ctrl(uart_num, uart_conf->flow_ctrl, uart_conf->rx_flow_ctrl_thresh); + } + + my_uart_set_baudrate(uart_num, uart_conf->baud_rate); + my_uart_set_word_length(uart_num, uart_conf->data_bits); + my_uart_set_stop_bits(uart_num, uart_conf->stop_bits); + my_uart_set_parity(uart_num, uart_conf->parity); + uart_reset_rx_fifo(uart_num); + + return ESP_OK; +} + +esp_err_t my_uart_intr_config(uart_port_t uart_num, uart_intr_config_t *intr_conf) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + my_uart_clear_intr_status(uart_num, UART_INTR_MASK); + UART_ENTER_CRITICAL(); + UART[uart_num]->int_clr.val = UART_INTR_MASK; + + if (intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) + { + UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & 0x7f); + UART[uart_num]->conf1.rx_tout_en = 1; + } + else + { + UART[uart_num]->conf1.rx_tout_en = 0; + } + + if (intr_conf->intr_enable_mask & UART_RXFIFO_FULL_INT_ENA_M) + { + UART[uart_num]->conf1.rxfifo_full_thrhd = intr_conf->rxfifo_full_thresh; + } + + if (intr_conf->intr_enable_mask & UART_TXFIFO_EMPTY_INT_ENA_M) + { + UART[uart_num]->conf1.txfifo_empty_thrhd = intr_conf->txfifo_empty_intr_thresh; + } + + // my_uart_clear_intr_status(UART[uart_num], mask); + UART[uart_num]->int_ena.val = intr_conf->intr_enable_mask; + _xt_isr_unmask(0x1 << ETS_UART_INUM); + UART_EXIT_CRITICAL(); + + return ESP_OK; +} + +// internal isr handler for default driver code. +static void uart_rx_intr_handler_default(void *param) +{ + uart_obj_t *p_uart = (uart_obj_t *)param; + uint8_t uart_num = p_uart->uart_num; + uart_dev_t *uart_reg = UART[uart_num]; + int rx_fifo_len = uart_reg->status.rxfifo_cnt; + uint8_t buf_idx = 0; + uint32_t uart_intr_status = UART[uart_num]->int_st.val; + uart_event_t uart_event; + BaseType_t task_woken = 0; + + + while (uart_intr_status != 0x0) + { + uart_select_notif_t notify = UART_SELECT_ERROR_NOTIF; + + buf_idx = 0; + uart_event.type = UART_EVENT_MAX; + + if (uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) + { + my_uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M); + my_uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA_M); + + // TX semaphore will only be used when tx_buf_size is zero. + if (p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) + { + p_uart->tx_waiting_fifo = false; + xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &task_woken); + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else + { + // We don't use TX ring buffer, because the size is zero. + if (p_uart->tx_buf_size == 0) + { + continue; + } + + int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt; + bool en_tx_flg = false; + + // We need to put a loop here, in case all the buffer items are very short. + // That would cause a watch_dog reset because empty interrupt happens so often. + // Although this is a loop in ISR, this loop will execute at most 128 turns. + while (tx_fifo_rem) + { + if (p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) + { + size_t size; + p_uart->tx_head = (uart_tx_data_t *)xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + + if (p_uart->tx_head) + { + // The first item is the data description + // Get the first item to get the data information + if (p_uart->tx_len_tot == 0) + { + p_uart->tx_ptr = NULL; + p_uart->tx_len_tot = p_uart->tx_head->tx_data.size; + // We have saved the data description from the 1st item, return buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &task_woken); + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else if (p_uart->tx_ptr == NULL) + { + // Update the TX item pointer, we will need this to return item to buffer. + p_uart->tx_ptr = (uint8_t *)p_uart->tx_head; + en_tx_flg = true; + p_uart->tx_len_cur = size; + } + } + else + { + // Can not get data from ring buffer, return; + break; + } + } + + if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) + { + // To fill the TX FIFO. + int send_len = p_uart->tx_len_cur > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_cur; + + for (buf_idx = 0; buf_idx < send_len; buf_idx++) + { + UART[uart_num]->fifo.rw_byte = *(p_uart->tx_ptr++) & 0xff; + } + + p_uart->tx_len_tot -= send_len; + p_uart->tx_len_cur -= send_len; + tx_fifo_rem -= send_len; + + if (p_uart->tx_len_cur == 0) + { + // Return item to ring buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &task_woken); + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + + p_uart->tx_head = NULL; + p_uart->tx_ptr = NULL; + } + + if (p_uart->tx_len_tot == 0) + { + en_tx_flg = false; + xSemaphoreGiveFromISR(p_uart->tx_done_sem, &task_woken); + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else + { + en_tx_flg = true; + } + } + } + + if (en_tx_flg) + { + my_uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M); + my_uart_enable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA_M); + } + } + } + else if ((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) + { + rx_fifo_len = uart_reg->status.rxfifo_cnt; + + if (p_uart->rx_buffer_full_flg == false) + { + // We have to read out all data in RX FIFO to clear the interrupt signal + while (buf_idx < rx_fifo_len) + { + p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte; + } + + // Get the buffer from the FIFO + // After Copying the Data From FIFO ,Clear intr_status + my_uart_clear_intr_status(uart_num, UART_RXFIFO_TOUT_INT_CLR_M | UART_RXFIFO_FULL_INT_CLR_M); + uart_event.type = UART_DATA; + uart_event.size = rx_fifo_len; + p_uart->rx_stash_len = rx_fifo_len; + + // If we fail to push data to ring buffer, we will have to stash the data, and send next time. + // Mainly for applications that uses flow control or small ring buffer. + if (pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &task_woken)) + { + my_uart_disable_intr_mask(uart_num, UART_RXFIFO_TOUT_INT_ENA_M | UART_RXFIFO_FULL_INT_ENA_M); + uart_event.type = UART_BUFFER_FULL; + p_uart->rx_buffer_full_flg = true; + // SWO modify + // When we cannot write to the ring buffer, we also think that the serial port is "overflow". + SetTraceError(DAP_SWO_BUFFER_OVERRUN); + } + else + { + p_uart->rx_buffered_len += p_uart->rx_stash_len; + xEventGroupSetBitsFromISR(kUART_Monitoe_event_group, UART_GOT_DATA, pdFALSE); + } + + notify = UART_SELECT_READ_NOTIF; + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else + { + my_uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M); + my_uart_clear_intr_status(uart_num, UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M); + } + } + else if (uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) + { + // When fifo overflows, we reset the fifo. + uart_reset_rx_fifo(uart_num); + uart_reg->int_clr.rxfifo_ovf = 1; + uart_event.type = UART_FIFO_OVF; + notify = UART_SELECT_ERROR_NOTIF; + // SWO modify + // Unfortunately, Overflow occurs usually there is no flow control. + // Although the overflow situation often occurs, + // the buffer stability of the serial port is better, + // and there is basically no data loss. + ////TODO: Can we get rid of this code? + SetTraceError(DAP_SWO_BUFFER_OVERRUN); + } + else if (uart_intr_status & UART_FRM_ERR_INT_ST_M) + { + uart_reg->int_clr.frm_err = 1; + uart_event.type = UART_FRAME_ERR; + notify = UART_SELECT_ERROR_NOTIF; + // SWO modify + SetTraceError(DAP_SWO_STREAM_ERROR); + } + else if (uart_intr_status & UART_PARITY_ERR_INT_ST_M) + { + uart_reg->int_clr.parity_err = 1; + uart_event.type = UART_PARITY_ERR; + notify = UART_SELECT_ERROR_NOTIF; + // SWO modify + SetTraceError(DAP_SWO_STREAM_ERROR); + } + else + { + uart_reg->int_clr.val = uart_intr_status; // simply clear all other intr status + uart_event.type = UART_EVENT_MAX; + notify = UART_SELECT_ERROR_NOTIF; + // SWO modify + SetTraceError(DAP_SWO_STREAM_ERROR); + } + +#ifdef CONFIG_USING_ESP_VFS + if (uart_event.type != UART_EVENT_MAX && p_uart->uart_select_notif_callback) + { + p_uart->uart_select_notif_callback(uart_num, notify, &task_woken); + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } +#else + (void)notify; +#endif + + if (uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) + { + if (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void *)&uart_event, &task_woken)) + { + ESP_EARLY_LOGV(UART_TAG, "UART event queue full"); + } + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + + uart_intr_status = uart_reg->int_st.val; + } +} + +// Fill UART tx_fifo and return a number, +// This function by itself is not thread-safe, always call from within a muxed section. +static int uart_fill_fifo(uart_port_t uart_num, const char *buffer, uint32_t len) +{ + uint8_t i = 0; + uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt; + uint8_t tx_remain_fifo_cnt = (UART_FIFO_LEN - tx_fifo_cnt); + uint8_t copy_cnt = (len >= tx_remain_fifo_cnt ? tx_remain_fifo_cnt : len); + + for (i = 0; i < copy_cnt; i++) + { + UART[uart_num]->fifo.rw_byte = buffer[i]; + } + + return copy_cnt; +} + +int my_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + UART_CHECK(buffer, "buffer null", (-1)); + + if (len == 0) + { + return 0; + } + + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); + int tx_len = uart_fill_fifo(uart_num, (const char *)buffer, len); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return tx_len; +} + +static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size) +{ + if (size == 0) + { + return 0; + } + + size_t original_size = size; + + // lock for uart_tx + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); + p_uart_obj[uart_num]->wait_tx_done_flg = true; + if (p_uart_obj[uart_num]->tx_buf_size > 0) + { + int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); + int offset = 0; + uart_tx_data_t evt; + evt.tx_data.size = size; + evt.type = UART_DATA; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)&evt, sizeof(uart_tx_data_t), portMAX_DELAY); + + while (size > 0) + { + int send_size = size > max_size / 2 ? max_size / 2 : size; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)(src + offset), send_size, portMAX_DELAY); + size -= send_size; + offset += send_size; + my_uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); + } + } + else + { + while (size) + { + // semaphore for tx_fifo available + if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) + { + size_t sent = uart_fill_fifo(uart_num, (char *)src, size); + + if (sent < size) + { + p_uart_obj[uart_num]->tx_waiting_fifo = true; + my_uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); + } + + size -= sent; + src += sent; + } + } + + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); + } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return original_size; +} + +int my_uart_write_bytes(uart_port_t uart_num, const char *src, size_t size) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + UART_CHECK(src, "buffer null", (-1)); + + return uart_tx_all(uart_num, src, size); +} + +int my_uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, TickType_t ticks_to_wait) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((buf), "uart data null", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + + uint8_t *data = NULL; + size_t size; + size_t copy_len = 0; + int len_tmp; + + if (xSemaphoreTake(p_uart_obj[uart_num]->rx_mux, (portTickType)ticks_to_wait) != pdTRUE) + { + return -1; + } + + while (length) + { + if (p_uart_obj[uart_num]->rx_cur_remain == 0) + { + data = (uint8_t *)xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType)ticks_to_wait); + + if (data) + { + p_uart_obj[uart_num]->rx_head_ptr = data; + p_uart_obj[uart_num]->rx_ptr = data; + p_uart_obj[uart_num]->rx_cur_remain = size; + } + else + { + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); + return copy_len; + } + } + + if (p_uart_obj[uart_num]->rx_cur_remain > length) + { + len_tmp = length; + } + else + { + len_tmp = p_uart_obj[uart_num]->rx_cur_remain; + } + + memcpy(buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp); + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len -= len_tmp; + p_uart_obj[uart_num]->rx_ptr += len_tmp; + UART_EXIT_CRITICAL(); + p_uart_obj[uart_num]->rx_cur_remain -= len_tmp; + copy_len += len_tmp; + length -= len_tmp; + + if (p_uart_obj[uart_num]->rx_cur_remain == 0) + { + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ptr = NULL; + + if (p_uart_obj[uart_num]->rx_buffer_full_flg) + { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); + + if (res == pdTRUE) + { + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len; + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + UART_EXIT_CRITICAL(); + my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); + } + } + } + } + + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); + return copy_len; +} + +esp_err_t my_uart_get_buffered_data_len(uart_port_t uart_num, size_t *size) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_ARG); + + *size = p_uart_obj[uart_num]->rx_buffered_len; + return ESP_OK; +} + +esp_err_t my_uart_flush(uart_port_t uart_num) __attribute__((alias("my_uart_flush_input"))); + +esp_err_t my_uart_flush_input(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_ARG); + uart_obj_t *p_uart = p_uart_obj[uart_num]; + uint8_t *data; + size_t size; + + // rx sem protect the ring buffer read related functions + xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY); + my_uart_disable_rx_intr(p_uart_obj[uart_num]->uart_num); + + while (true) + { + if (p_uart->rx_head_ptr) + { + vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr); + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len -= p_uart->rx_cur_remain; + UART_EXIT_CRITICAL(); + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; + } + + data = (uint8_t *)xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType)0); + + if (data == NULL) + { + if (p_uart_obj[uart_num]->rx_buffered_len != 0) + { + ESP_LOGE(UART_TAG, "rx_buffered_len error"); + p_uart_obj[uart_num]->rx_buffered_len = 0; + } + + // We also need to clear the `rx_buffer_full_flg` here. + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + UART_EXIT_CRITICAL(); + break; + } + + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len -= size; + UART_EXIT_CRITICAL(); + vRingbufferReturnItem(p_uart->rx_ring_buf, data); + + if (p_uart_obj[uart_num]->rx_buffer_full_flg) + { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); + + if (res == pdTRUE) + { + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len; + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + UART_EXIT_CRITICAL(); + } + } + } + + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; + uart_reset_rx_fifo(uart_num); + my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); + xSemaphoreGive(p_uart->rx_mux); + return ESP_OK; +} + +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) +{ + esp_err_t r; + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((rx_buffer_size > UART_FIFO_LEN) || ((uart_num == UART_NUM_1) && (rx_buffer_size == 0)), "uart rx buffer length error(>128)", ESP_ERR_INVALID_ARG); + UART_CHECK((tx_buffer_size > UART_FIFO_LEN) || (tx_buffer_size == 0), "uart tx buffer length error(>128 or 0)", ESP_ERR_INVALID_ARG); + UART_CHECK((queue_size >= 0), "queue_size error(>=0)", ESP_ERR_INVALID_ARG); + + if (p_uart_obj[uart_num] == NULL) + { + p_uart_obj[uart_num] = (uart_obj_t *)calloc(1, sizeof(uart_obj_t)); + + if (p_uart_obj[uart_num] == NULL) + { + ESP_LOGE(UART_TAG, "UART driver malloc error"); + return ESP_FAIL; + } + + p_uart_obj[uart_num]->uart_num = uart_num; + p_uart_obj[uart_num]->uart_mode = UART_MODE_UART; + p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary(); + p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->queue_size = queue_size; + p_uart_obj[uart_num]->tx_ptr = NULL; + p_uart_obj[uart_num]->tx_head = NULL; + p_uart_obj[uart_num]->tx_len_tot = 0; + p_uart_obj[uart_num]->rx_buffered_len = 0; + p_uart_obj[uart_num]->wait_tx_done_flg = false; + + if (uart_queue) + { + p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); + *uart_queue = p_uart_obj[uart_num]->xQueueUart; + ESP_LOGI(UART_TAG, "queue free spaces: %d", (int)uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); + } + else + { + p_uart_obj[uart_num]->xQueueUart = NULL; + } + + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + p_uart_obj[uart_num]->tx_waiting_fifo = false; + p_uart_obj[uart_num]->rx_ptr = NULL; + p_uart_obj[uart_num]->rx_cur_remain = 0; + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF); + p_uart_obj[uart_num]->rx_buf_size = rx_buffer_size; + + if (tx_buffer_size > 0) + { + p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT); + p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; + } + else + { + p_uart_obj[uart_num]->tx_ring_buf = NULL; + p_uart_obj[uart_num]->tx_buf_size = 0; + } + + p_uart_obj[uart_num]->uart_select_notif_callback = NULL; + } + else + { + ESP_LOGE(UART_TAG, "UART driver already installed"); + return ESP_FAIL; + } + + r = my_uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num]); + + if (r != ESP_OK) + { + goto err; + } + + uart_intr_config_t uart_intr = { + .intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M | UART_FRM_ERR_INT_ENA_M | UART_RXFIFO_OVF_INT_ENA_M, + .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT, + .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT, + .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT}; + r = my_uart_intr_config(uart_num, &uart_intr); + + if (r != ESP_OK) + { + goto err; + } + + return r; + +err: + ESP_LOGE(UART_TAG, "driver install error"); + my_uart_driver_delete(uart_num); + return r; +} + +// Make sure no other tasks are still using UART before you call this function +esp_err_t my_uart_driver_delete(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + if (p_uart_obj[uart_num] == NULL) + { + ESP_LOGI(UART_TAG, "ALREADY NULL"); + return ESP_OK; + } + + my_uart_disable_rx_intr(uart_num); + my_uart_disable_tx_intr(uart_num); + _xt_isr_mask(0x1 << ETS_UART_INUM); + + if (p_uart_obj[uart_num]->tx_fifo_sem) + { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_fifo_sem = NULL; + } + + if (p_uart_obj[uart_num]->tx_done_sem) + { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem); + p_uart_obj[uart_num]->tx_done_sem = NULL; + } + + if (p_uart_obj[uart_num]->tx_mux) + { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux); + p_uart_obj[uart_num]->tx_mux = NULL; + } + + if (p_uart_obj[uart_num]->rx_mux) + { + vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux); + p_uart_obj[uart_num]->rx_mux = NULL; + } + + if (p_uart_obj[uart_num]->xQueueUart) + { + vQueueDelete(p_uart_obj[uart_num]->xQueueUart); + p_uart_obj[uart_num]->xQueueUart = NULL; + } + + if (p_uart_obj[uart_num]->rx_ring_buf) + { + vRingbufferDelete(p_uart_obj[uart_num]->rx_ring_buf); + p_uart_obj[uart_num]->rx_ring_buf = NULL; + } + + if (p_uart_obj[uart_num]->tx_ring_buf) + { + vRingbufferDelete(p_uart_obj[uart_num]->tx_ring_buf); + p_uart_obj[uart_num]->tx_ring_buf = NULL; + } + + free(p_uart_obj[uart_num]); + p_uart_obj[uart_num] = NULL; + + return ESP_OK; +} + +void uart_set_select_notif_callback(uart_port_t uart_num, uart_select_notif_callback_t uart_select_notif_callback) +{ + if (uart_num < UART_NUM_MAX && p_uart_obj[uart_num]) + { + p_uart_obj[uart_num]->uart_select_notif_callback = (uart_select_notif_callback_t)uart_select_notif_callback; + } +} + +esp_err_t my_uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((tout_thresh < 127), "tout_thresh max value is 126", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + + // The tout_thresh = 1, defines TOUT interrupt timeout equal to + // transmission time of one symbol (~11 bit) on current baudrate + if (tout_thresh > 0) + { + UART[uart_num]->conf1.rx_tout_thrhd = (tout_thresh & 0x7f); + UART[uart_num]->conf1.rx_tout_en = 1; + } + else + { + UART[uart_num]->conf1.rx_tout_en = 0; + } + + UART_EXIT_CRITICAL(); + return ESP_OK; +} diff --git a/main/DAP_handle.c b/main/DAP_handle.c index 98d26c8..02975b9 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -14,32 +14,70 @@ #include "DAP.h" ////TODO: Merge this -#define DAP_PACKET_SIZE 512 +#define DAP_PACKET_SIZE 512 +static uint8_t data_out[DAP_PACKET_SIZE]; +static int dap_respond = 0; -uint8_t data_out[DAP_PACKET_SIZE]; -int respond = 0; - +// SWO Trace +static int swo_trace_respond = 0; +static uint8_t *swo_data_to_send; +static uint32_t num_swo_data; void handle_dap_data_request(usbip_stage2_header *header) { - uint8_t * data_in = (uint8_t *)header; + uint8_t *data_in = (uint8_t *)header; data_in = &(data_in[sizeof(usbip_stage2_header)]); // Point to the beginning of the URB packet - respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); + dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); send_stage2_submit(header, 0, 0); - } void handle_dap_data_response(usbip_stage2_header *header) { - if (respond) { - respond = 0; - //os_printf("*** Will respond"); - send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); - - //os_printf("*** RESPONDED ***"); - } else { - //os_printf("*** Will NOT respond"); - send_stage2_submit(header, 0, 0); - } + if (dap_respond) + { + dap_respond = 0; + //os_printf("*** Will respond"); + send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); + + //os_printf("*** RESPONDED ***"); + } + else + { + //os_printf("*** Will NOT respond"); + send_stage2_submit(header, 0, 0); + } +} + +void handle_swo_trace_response(usbip_stage2_header *header) +{ + if (swo_trace_respond) + { + swo_trace_respond = 0; + //os_printf("*** Will respond"); + send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); + + //os_printf("*** RESPONDED ***"); + } + else + { + //os_printf("*** Will NOT respond"); + send_stage2_submit(header, 0, 0); + } +} + + +// SWO Data Queue Transfer +// buf: pointer to buffer with data +// num: number of bytes to transfer +void SWO_QueueTransfer (uint8_t *buf, uint32_t num) { + swo_data_to_send = buf; + num_swo_data = num; + swo_trace_respond = 1; +} + +// SWO Data Abort Transfer +void SWO_AbortTransfer (void) { + //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U)); + ////TODO: unlink might be useful ... } \ No newline at end of file diff --git a/main/DAP_handle.h b/main/DAP_handle.h index 903bc58..5ac91f2 100644 --- a/main/DAP_handle.h +++ b/main/DAP_handle.h @@ -5,4 +5,5 @@ void handle_dap_data_request(usbip_stage2_header *header); void handle_dap_data_response(usbip_stage2_header *header); +void handle_swo_trace_response(usbip_stage2_header *header); #endif \ No newline at end of file diff --git a/main/main.c b/main/main.c index 03f5354..b658cec 100644 --- a/main/main.c +++ b/main/main.c @@ -26,13 +26,14 @@ #include "tcp_server.h" #include "timer.h" #include "wifi_configuration.h" - /* The examples use simple WiFi configuration that you can set via 'make menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" */ +extern void SWO_Thread(void *argument); +extern void usart_monitor_task(void *argument); /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; @@ -95,6 +96,7 @@ static void initialise_wifi(void) { tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); @@ -109,7 +111,7 @@ static void initialise_wifi(void) ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); - + } static void wait_for_ip() @@ -135,6 +137,10 @@ void app_main() initialise_wifi(); wait_for_ip(); - xTaskCreate(timer_create_task, "timer_create", 1024, NULL, 10, NULL); + xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); + // SWO Trace Task + xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); + xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); + } diff --git a/main/usbip_server.c b/main/usbip_server.c index 0317f6f..cf87a53 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -27,6 +27,10 @@ static void unpack(void *data, int size); static int handle_submit(usbip_stage2_header *header); static int read_stage2_command(usbip_stage2_header *header, uint32_t length); +static void handle_unlink(usbip_stage2_header *header); +// unlink helper function +static void send_stage2_unlink(usbip_stage2_header *req_header); + int attach(uint8_t *buffer, uint32_t length) { int command = read_stage1_command(buffer, length); @@ -41,7 +45,7 @@ int attach(uint8_t *buffer, uint32_t length) handle_device_list(buffer, length); break; - case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT + case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT handle_device_attach(buffer, length); break; @@ -176,7 +180,7 @@ static void send_interface_info() int emulate(uint8_t *buffer, uint32_t length) { // usbip_stage2_header header; - int command = read_stage2_command((usbip_stage2_header *)buffer, length); + int command = read_stage2_command((usbip_stage2_header *)buffer, length); if (command < 0) { return -1; @@ -258,7 +262,6 @@ static void unpack(void *data, int size) } } - /** * @brief * @@ -272,7 +275,7 @@ static int handle_submit(usbip_stage2_header *header) handleUSBControlRequest(header); break; - // data + // endpoint 1 data receicve and response case 0x01: if (header->base.direction == 0) { @@ -285,7 +288,19 @@ static int handle_submit(usbip_stage2_header *header) handle_dap_data_response(header); } break; - + // endpoint 2 for SWO trace + case 0x02: + if (header->base.direction == 0) + { + // os_printf("EP 02 DATA FROM HOST"); + send_stage2_submit(header, 0, 0); + } + else + { + // os_printf("EP 02 DATA TO HOST"); + handle_swo_trace_response(header); + } + break; // request to save data to device case 0x81: if (header->base.direction == 0) @@ -320,7 +335,7 @@ void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t send(kSock, req_header, sizeof(usbip_stage2_header), 0); } -void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void * const data, int32_t data_length) +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length) { send_stage2_submit(req_header, status, data_length); @@ -329,4 +344,24 @@ void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, co { send(kSock, data, data_length, 0); } +} + +static void handle_unlink(usbip_stage2_header *header) +{ + os_printf("s2 handling cmd unlink...\r\n"); + send_stage2_unlink(header); +} +static void send_stage2_unlink(usbip_stage2_header *req_header) +{ + + req_header->base.command = USBIP_STAGE2_RSP_UNLINK; + req_header->base.direction = USBIP_DIR_OUT; + + memset(&(req_header->u.ret_unlink), 0, sizeof(usbip_stage2_header_ret_unlink)); + + // req_header.u.ret_unlink.status = 0; + + pack(req_header, sizeof(usbip_stage2_header)); + + send(kSock, req_header, sizeof(usbip_stage2_header), 0); } \ No newline at end of file From ad6b9b3609207840448b6f3f3d72e438c49936e4 Mon Sep 17 00:00:00 2001 From: windowsair Date: Fri, 31 Jan 2020 15:57:17 +0800 Subject: [PATCH 11/21] fix: Fixed some rookie mistakes This is a temporary "stable" release. See the Readme.md file in the root directory for more instructions. --- README.md | 10 +- components/DAP/config/DAP_config.h | 15 ++- components/README.md | 4 +- components/USBIP/MSOS20Descriptors.c | 166 +++++++++++++-------------- components/USBIP/MSOS20Descriptors.h | 160 +++++++++++++------------- components/USBIP/USB_handle.c | 38 +++++- components/USBIP/USBd_config.c | 34 +++--- main/DAP_handle.c | 29 ++--- main/main.c | 2 + main/tcp_server.c | 122 ++++++++++---------- main/usbip_server.c | 23 ++-- main/wifi_configuration.h | 4 +- 12 files changed, 318 insertions(+), 289 deletions(-) diff --git a/README.md b/README.md index e00d592..4a1abdf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -# Setup -1. DAP_Setup() -2. Server begin +# Attention -# Loop \ No newline at end of file +At present, the adaptation to WCID, WinUSB, etc. has all been completed. However, when transmitting data on the endpoint, we received an error message from USBIP. This is most likely a problem with the USBIP project itself. + +Due to the completeness of the USBIP protocol document, we have not yet understood its role in the Bulk transmission process, which may also lead to errors in subsequent processes. + +We will continue to try to make it work under USB HID. Once the USBIP problem is solved, we will immediately transfer it to work under WinUSB \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index fccf7d3..a61956e 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -29,6 +29,7 @@ #define __DAP_CONFIG_H__ #include +#include #include "cmsis_compiler.h" #include "gpio.h" #include "gpio_struct.h" @@ -153,8 +154,9 @@ __STATIC_INLINE uint8_t DAP_GetVendorString(char *str) ////TODO: fill this // In fact, Keil can get the corresponding information through USB // without filling in this information. - (void)str; - return (0U); + // (void)str; + strcpy(str, "windowsair"); + return (sizeof("windowsair")); } /** @@ -165,8 +167,9 @@ __STATIC_INLINE uint8_t DAP_GetVendorString(char *str) */ __STATIC_INLINE uint8_t DAP_GetProductString(char *str) { - (void)str; - return (0U); + //(void)str; + strcpy(str, "CMSIS-DAP v2"); + return (sizeof("CMSIS-DAP v2")); } /** @@ -177,8 +180,8 @@ __STATIC_INLINE uint8_t DAP_GetProductString(char *str) */ __STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) { - (void)str; - return (0U); + strcpy(str, "1234"); + return (sizeof("1234")); } ///@} diff --git a/components/README.md b/components/README.md index e52e5e9..3fc0da1 100644 --- a/components/README.md +++ b/components/README.md @@ -1,4 +1,2 @@ # TODO -1. adapt to special hardware -2. USB -3. Significant Bit is difficult to judge, may need to dive into the details of usbip \ No newline at end of file +1. USB \ No newline at end of file diff --git a/components/USBIP/MSOS20Descriptors.c b/components/USBIP/MSOS20Descriptors.c index 4337076..6621557 100644 --- a/components/USBIP/MSOS20Descriptors.c +++ b/components/USBIP/MSOS20Descriptors.c @@ -1,84 +1,84 @@ -/** - * @file MSOS20Descriptors.c - * @author windowsair - * @brief Store related data of Microsoft OS 2.0 descriptor - * @version 0.1 - * @date 2019-11-21 - * - * @copyright Copyright (c) 2019 - * - */ - - ////TODO: refactoring into structure - -#include -#include "MSOS20Descriptors.h" - -#define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) - - - -// Microsoft OS 2.0 descriptor set header -const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20] = -{ - // Microsoft OS 2.0 Descriptor Set header (Table 10) - 0x0A, 0x00, // wLength (Shall be set to 0x0A) - MS_OS_20_SET_HEADER_DESCRIPTOR, 0x00, - 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) - USBShort(kLengthOfMsOS20), // wTotalLength - - // Support WinUSB - // See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/automatic-installation-of-winusb - - // Microsoft OS 2.0 compatible ID descriptor (Table 13) - 0x14, 0x00, // wLength - USBShort(MS_OS_20_FEATURE_COMPATIBLE_ID), // wDescriptorType - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleID - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompatibleID - - // Microsoft OS 2.0 registry property descriptor (Table 14) - 0x84, 0x00, // wLength - USBShort(MS_OS_20_FEATURE_REG_PROPERTY), - 0x07, 0x00, // wPropertyDataType: REG_MULTI_SZ (Unicode Strings) - 0x2A, 0x00, // wPropertyNameLength - 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0, - 'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,'s',0,0,0, - // Set to "DeviceInterfaceGUID" to support WinUSB - 0x50, 0x00, // wPropertyDataLength - // WinUSB GUID - '{',0,'C',0,'D',0,'B',0,'3',0,'B',0,'5',0,'A',0,'D',0,'-',0, - '2',0,'9',0,'3',0,'B',0,'-',0,'4',0,'6',0,'6',0,'3',0,'-',0, - 'A',0,'A',0,'3',0,'6',0,'-',0,'1',0,'A',0,'A',0,'E',0,'4',0, - '6',0,'4',0,'6',0,'3',0,'7',0,'7',0,'6',0,'}',0,0,0,0,0, - // identify a CMSIS-DAP V2 configuration, - // must set to "{CDB3B5AD-293B-4663-AA36-1AAE46463776}" - -}; - -const uint8_t bosDescriptor[kLengthOfBos] = -{ - // Universal Serial Bus 3.0 Specification, Table 9-9. - 0x05, // bLength of this descriptor - USB_DESCRIPTOR_TYPE_BOS, // BOS Descriptor type(Constant) - USBShort(kLengthOfBos), // wLength - 0x01, // bNumDeviceCaps - - // Microsoft OS 2.0 platform capability descriptor header (Table 4) - // See also: - // Universal Serial Bus 3.0 Specification : Format of a Device Capability Descriptor, Table 9-10. - - 0x1C, // bLength of this first device capability descriptor - // bLength -> The total length of the remaining arrays containing this field - USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY, // bDescriptorType - USB_DEVICE_CAPABILITY_TYPE_PLATFORM, // bDevCapabilityType - - // Capability-Dependent (See USB3.0 Specification Table 9-10.) - 0x00, // bReserved - USB_DEVICE_CAPABILITY_UUID, // MS_OS_20_Platform_Capability_ID - - 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) - USBShort(kLengthOfMsOS20), // wMSOSDescriptorSetTotalLength(length of descriptor set header) - kValueOfbMS_VendorCode, // bMS_VendorCode (0x01 will be ok) - ////TODO:change this - 0, // bAltEnumCode +/** + * @file MSOS20Descriptors.c + * @author windowsair + * @brief Store related data of Microsoft OS 2.0 descriptor + * @version 0.1 + * @date 2019-11-21 + * + * @copyright Copyright (c) 2019 + * + */ + + ////TODO: refactoring into structure + +#include +#include "MSOS20Descriptors.h" + +#define USBShort(ui16Value) ((ui16Value) & 0xff), ((ui16Value) >> 8) //((ui16Value) & 0xFF),(((ui16Value) >> 8) & 0xFF) + + + +// Microsoft OS 2.0 descriptor set header +const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20] = +{ + // Microsoft OS 2.0 Descriptor Set header (Table 10) + 0x0A, 0x00, // wLength (Shall be set to 0x0A) + MS_OS_20_SET_HEADER_DESCRIPTOR, 0x00, + 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) + USBShort(kLengthOfMsOS20), // wTotalLength + + // Support WinUSB + // See https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/automatic-installation-of-winusb + + // Microsoft OS 2.0 compatible ID descriptor (Table 13) + 0x14, 0x00, // wLength + USBShort(MS_OS_20_FEATURE_COMPATIBLE_ID), // wDescriptorType + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatibleID + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // subCompatibleID + + // Microsoft OS 2.0 registry property descriptor (Table 14) + 0x84, 0x00, // wLength + USBShort(MS_OS_20_FEATURE_REG_PROPERTY), + 0x07, 0x00, // wPropertyDataType: REG_MULTI_SZ (Unicode Strings) + 0x2A, 0x00, // wPropertyNameLength + 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0, + 'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,'s',0,0,0, + // Set to "DeviceInterfaceGUID" to support WinUSB + 0x50, 0x00, // wPropertyDataLength + // WinUSB GUID + '{',0,'C',0,'D',0,'B',0,'3',0,'B',0,'5',0,'A',0,'D',0,'-',0, + '2',0,'9',0,'3',0,'B',0,'-',0,'4',0,'6',0,'6',0,'3',0,'-',0, + 'A',0,'A',0,'3',0,'6',0,'-',0,'1',0,'A',0,'A',0,'E',0,'4',0, + '6',0,'4',0,'6',0,'3',0,'7',0,'7',0,'6',0,'}',0,0,0,0,0, + // identify a CMSIS-DAP V2 configuration, + // must set to "{CDB3B5AD-293B-4663-AA36-1AAE46463776}" + +}; + +const uint8_t bosDescriptor[kLengthOfBos] = +{ + // Universal Serial Bus 3.0 Specification, Table 9-9. + 0x05, // bLength of this descriptor + USB_DESCRIPTOR_TYPE_BOS, // BOS Descriptor type(Constant) + USBShort(kLengthOfBos), // wLength + 0x01, // bNumDeviceCaps + + // Microsoft OS 2.0 platform capability descriptor header (Table 4) + // See also: + // Universal Serial Bus 3.0 Specification : Format of a Device Capability Descriptor, Table 9-10. + + 0x1C, // bLength of this first device capability descriptor + // bLength -> The total length of the remaining arrays containing this field + USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY, // bDescriptorType + USB_DEVICE_CAPABILITY_TYPE_PLATFORM, // bDevCapabilityType + + // Capability-Dependent (See USB3.0 Specification Table 9-10.) + 0x00, // bReserved + USB_DEVICE_CAPABILITY_UUID, // MS_OS_20_Platform_Capability_ID + + 0x00, 0x00, 0x03, 0x06, // dwWindowsVersion: Windows 8.1 (NTDDI_WINBLUE) + USBShort(kLengthOfMsOS20), // wMSOSDescriptorSetTotalLength(length of descriptor set header) + kValueOfbMS_VendorCode, // bMS_VendorCode (0x01 will be ok) + ////TODO:change this + 0, // bAltEnumCode }; \ No newline at end of file diff --git a/components/USBIP/MSOS20Descriptors.h b/components/USBIP/MSOS20Descriptors.h index 61a7ea3..51bbcb1 100644 --- a/components/USBIP/MSOS20Descriptors.h +++ b/components/USBIP/MSOS20Descriptors.h @@ -1,81 +1,81 @@ -/** - * @file MSOS20Descriptors.h - * @author windowsair - * @brief - * @version 0.1 - * @date 2019-11-21 - * - * @copyright Copyright (c) 2019 - * - */ - -#ifndef __MSOS20DESCRIPTORS_H__ -#define __MSOS20DESCRIPTORS_H__ - -#define kLengthOfMsOS20 0xA2 -#define kLengthOfBos 0x21 -#define kValueOfbMS_VendorCode 0x01// Just set to 0x01 -extern const uint8_t bosDescriptor[kLengthOfBos]; -extern const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20]; - -/* Microsoft OS 2.0 Descriptors BEGIN */ - -// Platform capability BOS descriptor, Table 1. -#define USB_DEVICE_CAPABILITY_TYPE_PLATFORM 5 - -// Platform capability UUID, Table 3. -// {D8DD60DF-4589-4CC7-9CD2-659D9E648A9F} -#define USB_DEVICE_CAPABILITY_UUID 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F - - -// Microsoft OS 2.0 descriptor wIndex values enum, Table 8. -#define MS_OS_20_DESCRIPTOR_INDEX 7 -#define MS_OS_20_SET_ALT_ENUMERATION 8 - - -// Microsoft OS 2.0 descriptor types enum for wDescriptorType values, Table 9. -#define MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 -#define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 -#define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 -#define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 -#define MS_OS_20_FEATURE_REG_PROPERTY 0x04 -#define MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 -#define MS_OS_20_FEATURE_MODEL_ID 0x06 -#define MS_OS_20_FEATURE_CCGP_DEVICE 0x07 - -/* Microsoft OS 2.0 Descriptors END */ - - - -/* Wireless USB Standard Extension Descriptor Types BEGIN */ - -// Wireless USB Specification 1.1 revison 1.1, Table 7-21. -#define USB_DESCRIPTOR_TYPE_SECURITY 12 -#define USB_DESCRIPTOR_TYPE_KEY 13 -#define USB_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 14 -#define USB_DESCRIPTOR_TYPE_BOS 15 -#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 16 -#define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMPANION 17 - -/* Wireless USB Standard Extension Descriptor Types END */ - - -/* Microsoft Extended Compat ID OS Feature Descriptor BEGIN */ - -#define USB_MS_EXTENDED_COMPAT_ID_VERSION 0x0100 -#define USB_MS_EXTENDED_COMPAT_ID_TYPE 0x04 - -#define USB_COMPATID_NONE {0} -#define USB_SUBCOMPATID_NONE {0} -#define USB_COMPATID_WINUSB "WINUSB\0" -#define USB_COMPATID_RNDIS "RNDIS\0\0" -#define USB_COMPATID_PTP "PTP\0\0\0\0" -#define USB_COMPATID_MTP "MTP\0\0\0\0" -#define USB_COMPATID_BLUETOOTH "BLUTUTH" -#define USB_SUBCOMPATID_BT_V11 "11\0\0\0\0\0" -#define USB_SUBCOMPATID_BT_V12 "12\0\0\0\0\0" -#define USB_SUBCOMPATID_BT_V20EDR "EDR\0\0\0\0" - -/* Microsoft Extended Compat ID OS Feature Descriptor END */ - +/** + * @file MSOS20Descriptors.h + * @author windowsair + * @brief + * @version 0.1 + * @date 2019-11-21 + * + * @copyright Copyright (c) 2019 + * + */ + +#ifndef __MSOS20DESCRIPTORS_H__ +#define __MSOS20DESCRIPTORS_H__ + +#define kLengthOfMsOS20 0xA2 +#define kLengthOfBos 0x21 +#define kValueOfbMS_VendorCode 0x01// Just set to 0x01 +extern const uint8_t bosDescriptor[kLengthOfBos]; +extern const uint8_t msOs20DescriptorSetHeader[kLengthOfMsOS20]; + +/* Microsoft OS 2.0 Descriptors BEGIN */ + +// Platform capability BOS descriptor, Table 1. +#define USB_DEVICE_CAPABILITY_TYPE_PLATFORM 5 + +// Platform capability UUID, Table 3. +// {D8DD60DF-4589-4CC7-9CD2-659D9E648A9F} +#define USB_DEVICE_CAPABILITY_UUID 0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F + + +// Microsoft OS 2.0 descriptor wIndex values enum, Table 8. +#define MS_OS_20_DESCRIPTOR_INDEX 7 +#define MS_OS_20_SET_ALT_ENUMERATION 8 + + +// Microsoft OS 2.0 descriptor types enum for wDescriptorType values, Table 9. +#define MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 +#define MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 +#define MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 +#define MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 +#define MS_OS_20_FEATURE_REG_PROPERTY 0x04 +#define MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 +#define MS_OS_20_FEATURE_MODEL_ID 0x06 +#define MS_OS_20_FEATURE_CCGP_DEVICE 0x07 + +/* Microsoft OS 2.0 Descriptors END */ + + + +/* Wireless USB Standard Extension Descriptor Types BEGIN */ + +// Wireless USB Specification 1.1 revison 1.1, Table 7-21. +#define USB_DESCRIPTOR_TYPE_SECURITY 12 +#define USB_DESCRIPTOR_TYPE_KEY 13 +#define USB_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 14 +#define USB_DESCRIPTOR_TYPE_BOS 15 +#define USB_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 16 +#define USB_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMPANION 17 + +/* Wireless USB Standard Extension Descriptor Types END */ + + +/* Microsoft Extended Compat ID OS Feature Descriptor BEGIN */ + +#define USB_MS_EXTENDED_COMPAT_ID_VERSION 0x0100 +#define USB_MS_EXTENDED_COMPAT_ID_TYPE 0x04 + +#define USB_COMPATID_NONE {0} +#define USB_SUBCOMPATID_NONE {0} +#define USB_COMPATID_WINUSB "WINUSB\0" +#define USB_COMPATID_RNDIS "RNDIS\0\0" +#define USB_COMPATID_PTP "PTP\0\0\0\0" +#define USB_COMPATID_MTP "MTP\0\0\0\0" +#define USB_COMPATID_BLUETOOTH "BLUTUTH" +#define USB_SUBCOMPATID_BT_V11 "11\0\0\0\0\0" +#define USB_SUBCOMPATID_BT_V12 "12\0\0\0\0\0" +#define USB_SUBCOMPATID_BT_V20EDR "EDR\0\0\0\0" + +/* Microsoft Extended Compat ID OS Feature Descriptor END */ + #endif \ No newline at end of file diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index a6dd0ce..666d026 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -19,6 +19,12 @@ #include "usb_defs.h" #include "MSOS20Descriptors.h" +const char *strings_list[] = { + 0, // reserved: available languages + "windowsair", + "CMSIS-DAP v2", + "1234", +}; // handle functions static void handleGetDescriptor(usbip_stage2_header *header); @@ -192,7 +198,7 @@ static void handleGetDescriptor(usbip_stage2_header *header) { case USB_DT_DEVICE: // get device descriptor os_printf("* GET 0x01 DEVICE DESCRIPTOR\r\n"); - send_stage2_submit_data(header, 0, kUSBd0DeviceDescriptor, sizeof(kUSBd0DeviceDescriptor)); + send_stage2_submit_data(header, 0, &kUSBd0DeviceDescriptor[0], sizeof(kUSBd0DeviceDescriptor)); break; case USB_DT_CONFIGURATION: // get configuration descriptor @@ -223,9 +229,29 @@ static void handleGetDescriptor(usbip_stage2_header *header) os_printf("** REQUESTED list of supported languages\r\n"); send_stage2_submit_data(header, 0, kLangDescriptor, sizeof(kLangDescriptor)); } + else if (header->u.cmd_submit.request.wValue.u8lo != 0xee) + { + os_printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); + os_printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); + int slen = strlen(strings_list[header->u.cmd_submit.request.wValue.u8lo]); + int wslen = slen * 2; + int buff_len = sizeof(usb_string_descriptor) + wslen; + char temp_buff[256]; + usb_string_descriptor *desc = (usb_string_descriptor *)temp_buff; + desc->bLength = buff_len; + desc->bDescriptorType = USB_DT_STRING; + for (int i = 0; i < slen; i++) + { + desc->wData[i] = strings_list[header->u.cmd_submit.request.wValue.u8lo][i]; + send_stage2_submit_data(header, 0, (uint8_t *)temp_buff, buff_len); + } + } else { - os_printf("***Unsupported operation***\r\n"); + os_printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); + os_printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); + os_printf("***Unsupported String descriptor***\r\n"); + } break; @@ -242,7 +268,7 @@ static void handleGetDescriptor(usbip_stage2_header *header) break; case USB_DT_DEVICE_QUALIFIER: - os_printf("* GET 0x06 DEVICE QUALIFIER DESCRIPTOR"); + os_printf("* GET 0x06 DEVICE QUALIFIER DESCRIPTOR\r\n"); usb_device_qualifier_descriptor desc; @@ -252,13 +278,13 @@ static void handleGetDescriptor(usbip_stage2_header *header) break; case USB_DT_OTHER_SPEED_CONFIGURATION: - os_printf("GET 0x07 [UNIMPLEMENTED] USB_DT_OTHER_SPEED_CONFIGURATION"); + os_printf("GET 0x07 [UNIMPLEMENTED] USB_DT_OTHER_SPEED_CONFIGURATION\r\n"); ////TODO:UNIMPLEMENTED send_stage2_submit(header, 0, 0); break; case USB_DT_INTERFACE_POWER: - os_printf("GET 0x08 [UNIMPLEMENTED] USB_DT_INTERFACE_POWER"); + os_printf("GET 0x08 [UNIMPLEMENTED] USB_DT_INTERFACE_POWER\r\n"); ////TODO:UNIMPLEMENTED send_stage2_submit(header, 0, 0); break; @@ -268,7 +294,7 @@ static void handleGetDescriptor(usbip_stage2_header *header) send_stage2_submit_data(header, 0, bosDescriptor, sizeof(bosDescriptor)); break; default: - os_printf("USB unknown Get Descriptor requested:%d", header->u.cmd_submit.request.wValue.u8lo); + os_printf("USB unknown Get Descriptor requested:%d\r\n", header->u.cmd_submit.request.wValue.u8lo); break; } } diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c index c266c16..f28d636 100644 --- a/components/USBIP/USBd_config.c +++ b/components/USBIP/USBd_config.c @@ -25,7 +25,7 @@ const uint8_t kUSBd0DeviceDescriptor[0x12] = { 0x12, // bLength - USB_DT_DEVICE, // bDescriptorType (constant) + USB_DT_DEVICE, // bDescriptorType USBShort(0x0210), // bcdUSB ////TODO: Is it also available elsewhere? @@ -34,14 +34,14 @@ const uint8_t kUSBd0DeviceDescriptor[0x12] = 0x00, // bDeviceSubClass 0x00, // bDeviceProtocol - USBD0_MAX_PACKET0, // Maximum packet size for default pipe. - USBShort(USBD0_DEV_DESC_IDVENDOR), // Vendor ID (VID). - USBShort(USBD0_DEV_DESC_IDPRODUCT), // Product ID (PID). - USBShort(USBD0_DEV_DESC_BCDDEVICE), // Device Version BCD. - 0x01, // Index of Manufacturer string identifier. - 0x02, // Index of Product string identifier. - 0x03 * USBD0_STR_DESC_SER_EN, // Index of Product serial number. - 0x01 // Number of configurations. + USBD0_MAX_PACKET0, // bMaxPacketSize0 Maximum packet size for default pipe. + USBShort(USBD0_DEV_DESC_IDVENDOR), // idVendor Vendor ID (VID). + USBShort(USBD0_DEV_DESC_IDPRODUCT), // idProduct Product ID (PID). + USBShort(USBD0_DEV_DESC_BCDDEVICE), // bcdDevice Device Version BCD. + 0x01, // iManufacturer Index of Manufacturer string identifier. + 0x02, // iProduct Index of Product string identifier. + 0x03 * USBD0_STR_DESC_SER_EN, // iSerialNumber Index of Product serial number. + 0x01 // bNumConfigurations Number of configurations. }; @@ -60,7 +60,7 @@ const uint8_t kUSBd0InterfaceDescriptor[0x1E]= USB_DT_INTERFACE, // bDescriptorType USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting - 0x03, // bNumEndpoints(we will use three endpoints) + 0x03, // bNumEndpoints(we will use 3 endpoints) // USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass @@ -91,7 +91,7 @@ const uint8_t kUSBd0InterfaceDescriptor[0x1E]= USB_DT_ENDPOINT, // bDescriptorType 0x01, // bEndpointAddress USB_ENDPOINT_ATTR_BULK, // bmAttributes - USBShort(512), // wMaxPacketSize + USBShort(512), // wMaxPacketSize // We assume that it always runs in High Speed. 0x00, // bInterval @@ -102,16 +102,17 @@ const uint8_t kUSBd0InterfaceDescriptor[0x1E]= USB_DT_ENDPOINT, // bDescriptorType 0x81, // bEndpointAddress USB_ENDPOINT_ATTR_BULK, // bmAttributes - USBShort(512), // wMaxPacketSize - 0x00, // bInterval + USBShort(512), // wMaxPacketSize + 0x00, // bInterval /* Pysical endpoint 2 */ + // "Endpoint 3: Bulk In (optional) – used for streaming SWO trace" Device -> PC 0x07, // bLength USB_DT_ENDPOINT, // bDescriptorType 0x82, // bEndpointAddress USB_ENDPOINT_ATTR_BULK, // bmAttributes - USBShort(512), // wMaxPacketSize + USBShort(512), // wMaxPacketSize 0x00, // bInterval @@ -123,9 +124,8 @@ const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = { // Configuration descriptor header. - 0x09, // bLength -> 0x09?? may be ok... 1-23 - 0x03, // bDescriptorType - // constant, set to 0x03 + 0x09, // bLength + USB_DT_CONFIGURATION, // bDescriptorType USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (LENGTHOFCONFIGDESCRIPTOR)), // wTotalLength diff --git a/main/DAP_handle.c b/main/DAP_handle.c index 02975b9..d80e4e3 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -12,7 +12,7 @@ #include "usbip_server.h" #include "DAP_handle.h" #include "DAP.h" - +#include "esp_libc.h" ////TODO: Merge this #define DAP_PACKET_SIZE 512 @@ -30,16 +30,18 @@ void handle_dap_data_request(usbip_stage2_header *header) data_in = &(data_in[sizeof(usbip_stage2_header)]); // Point to the beginning of the URB packet dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); - send_stage2_submit(header, 0, 0); + handle_dap_data_response(header); + //send_stage2_submit(header, 0, 0); } void handle_dap_data_response(usbip_stage2_header *header) { if (dap_respond) { - dap_respond = 0; - //os_printf("*** Will respond"); - send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); + //os_printf("*** Will respond"); + + send_stage2_submit_data(header, 0, data_out, (dap_respond & 0x0000FFFF)); + dap_respond = 0; //os_printf("*** RESPONDED ***"); } else @@ -66,18 +68,19 @@ void handle_swo_trace_response(usbip_stage2_header *header) } } - // SWO Data Queue Transfer // buf: pointer to buffer with data // num: number of bytes to transfer -void SWO_QueueTransfer (uint8_t *buf, uint32_t num) { - swo_data_to_send = buf; - num_swo_data = num; - swo_trace_respond = 1; +void SWO_QueueTransfer(uint8_t *buf, uint32_t num) +{ + swo_data_to_send = buf; + num_swo_data = num; + swo_trace_respond = 1; } // SWO Data Abort Transfer -void SWO_AbortTransfer (void) { - //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U)); - ////TODO: unlink might be useful ... +void SWO_AbortTransfer(void) +{ + //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U)); + ////TODO: unlink might be useful ... } \ No newline at end of file diff --git a/main/main.c b/main/main.c index b658cec..5676c15 100644 --- a/main/main.c +++ b/main/main.c @@ -34,6 +34,7 @@ extern void SWO_Thread(void *argument); extern void usart_monitor_task(void *argument); +extern void DAP_Setup(void); /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; @@ -136,6 +137,7 @@ void app_main() ESP_ERROR_CHECK(nvs_flash_init()); initialise_wifi(); wait_for_ip(); + DAP_Setup(); // DAP Setup xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); diff --git a/main/tcp_server.c b/main/tcp_server.c index 5031600..fbb16b7 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -65,7 +65,7 @@ void tcp_server_task(void *pvParameters) os_printf("Unable to create socket: errno %d\r\n", errno); break; } - os_printf("Socket created"); + os_printf("Socket created\r\n"); int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); if (err != 0) @@ -73,7 +73,7 @@ void tcp_server_task(void *pvParameters) os_printf("Socket unable to bind: errno %d\r\n", errno); break; } - os_printf("Socket binded"); + os_printf("Socket binded\r\n"); err = listen(listen_sock, 1); if (err != 0) @@ -81,7 +81,7 @@ void tcp_server_task(void *pvParameters) os_printf("Error occured during listen: errno %d\r\n", errno); break; } - os_printf("Socket listening"); + os_printf("Socket listening\r\n"); #ifdef CONFIG_EXAMPLE_IPV6 struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 @@ -89,82 +89,76 @@ void tcp_server_task(void *pvParameters) struct sockaddr_in sourceAddr; #endif uint32_t addrLen = sizeof(sourceAddr); - kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); - if (kSock < 0) - { - os_printf("Unable to accept connection: errno %d\r\n", errno); - break; - } - os_printf("Socket accepted"); - while (1) { - int len = recv(kSock, rx_buffer, 2047, 0); - // Error occured during receiving - if (len < 0) + kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); + if (kSock < 0) { - os_printf("recv failed: errno %d\r\n", errno); + os_printf("Unable to accept connection: errno %d\r\n", errno); break; } - // Connection closed - else if (len == 0) - { - os_printf("Connection closed\r\n"); - break; - } - // Data received - else + os_printf("Socket accepted\r\n"); + + while (1) { + int len = recv(kSock, rx_buffer, 2047, 0); + // Error occured during receiving + if (len < 0) + { + os_printf("recv failed: errno %d\r\n", errno); + break; + } + // Connection closed + else if (len == 0) + { + os_printf("Connection closed\r\n"); + break; + } + // Data received + else + { #ifdef CONFIG_EXAMPLE_IPV6 - // Get the sender's ip address as string - if (sourceAddr.sin6_family == PF_INET) - { - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - } - else if (sourceAddr.sin6_family == PF_INET6) - { - inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); - } + // Get the sender's ip address as string + if (sourceAddr.sin6_family == PF_INET) + { + inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + } + else if (sourceAddr.sin6_family == PF_INET6) + { + inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + } #else - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); #endif - rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string - //os_printf("Received %d bytes from %s:\r\n", len, addr_str); - // os_printf("%s", rx_buffer); - switch (kState) - { - case ACCEPTING: - kState = ATTACHING; - break; + switch (kState) + { + case ACCEPTING: + kState = ATTACHING; - case ATTACHING: - attach(rx_buffer, len); - break; + case ATTACHING: + attach(rx_buffer, len); + break; - case EMULATING: - emulate(rx_buffer, len); - break; + case EMULATING: + emulate(rx_buffer, len); + break; + default: + os_printf("unkonw kstate!\r\n"); + } } - - // int err = send(sock, rx_buffer, len, 0); - // if (err < 0) - // { - // os_printf("Error occured during sending: errno %d\r\n", errno); - // break; - // } } - } - kState = ACCEPTING; - if (kSock != -1) - { - os_printf("Shutting down socket and restarting...\r\n"); - shutdown(kSock, 0); - close(kSock); + // kState = ACCEPTING; + if (kSock != -1) + { + os_printf("Shutting down socket and restarting...\r\n"); + //shutdown(kSock, 0); + close(kSock); - shutdown(listen_sock, 0); - close(listen_sock); - vTaskDelay(5); + //shutdown(listen_sock, 0); + //close(listen_sock); + //vTaskDelay(5); + } } } vTaskDelete(NULL); diff --git a/main/usbip_server.c b/main/usbip_server.c index cf87a53..f9ad467 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -53,7 +53,7 @@ int attach(uint8_t *buffer, uint32_t length) os_printf("attach Unknown command: %d\r\n", command); break; } - return 0; ////TODO: ... + return 0; } static int read_stage1_command(uint8_t *buffer, uint32_t length) @@ -130,16 +130,15 @@ static void send_device_list() static void send_device_info() { - os_printf("Sending device info..."); + os_printf("Sending device info...\r\n"); usbip_stage1_usb_device device; strcpy(device.path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1"); strcpy(device.busid, "1-1"); device.busnum = htonl(1); - device.devnum = htonl(2); - device.speed = htonl(2); // what is this??? - //// TODO: 0200H for USB2.0 + device.devnum = htonl(1); + device.speed = htonl(3); // See usb_device_speed enum device.idVendor = htons(USBD0_DEV_DESC_IDVENDOR); device.idProduct = htons(USBD0_DEV_DESC_IDPRODUCT); @@ -183,7 +182,7 @@ int emulate(uint8_t *buffer, uint32_t length) int command = read_stage2_command((usbip_stage2_header *)buffer, length); if (command < 0) { - return -1; + return -1; } switch (command) @@ -211,7 +210,7 @@ static int read_stage2_command(usbip_stage2_header *header, uint32_t length) } //client.readBytes((uint8_t *)&header, sizeof(usbip_stage2_header)); - unpack((uint32_t *)&header, sizeof(usbip_stage2_header)); + unpack((uint32_t *)header, sizeof(usbip_stage2_header)); return header->base.command; } @@ -263,7 +262,7 @@ static void unpack(void *data, int size) } /** - * @brief + * @brief USB transaction processing * */ static int handle_submit(usbip_stage2_header *header) @@ -324,18 +323,18 @@ void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t { req_header->base.command = USBIP_STAGE2_RSP_SUBMIT; - req_header->base.direction = !req_header->base.direction; + req_header->base.direction = !(req_header->base.direction); - memset(&req_header->u.ret_submit, 0, sizeof(usbip_stage2_header_ret_submit)); + memset(&(req_header->u.ret_submit), 0, sizeof(usbip_stage2_header_ret_submit)); req_header->u.ret_submit.status = status; req_header->u.ret_submit.data_length = data_length; - pack(&req_header, sizeof(usbip_stage2_header)); + pack(req_header, sizeof(usbip_stage2_header)); send(kSock, req_header, sizeof(usbip_stage2_header), 0); } -void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length) +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const uint8_t *const data, int32_t data_length) { send_stage2_submit(req_header, status, data_length); diff --git a/main/wifi_configuration.h b/main/wifi_configuration.h index cb2701c..407261e 100644 --- a/main/wifi_configuration.h +++ b/main/wifi_configuration.h @@ -13,6 +13,8 @@ #define EXAMPLE_WIFI_SSID "DAP" #define EXAMPLE_WIFI_PASS "12345678" -#define PORT 22350 +#define PORT 3240 + +#define CONFIG_EXAMPLE_IPV4 1 #endif \ No newline at end of file From 3258b847958f4f340f4883c06b81a2f8fd54df79 Mon Sep 17 00:00:00 2001 From: windowsair Date: Fri, 31 Jan 2020 16:24:06 +0800 Subject: [PATCH 12/21] fix: Fixed some rookie mistakes This is a temporary "stable" release. See the Readme.md file in the root directory for more instructions. --- main/DAP_handle.c | 4 ++-- main/usbip_server.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main/DAP_handle.c b/main/DAP_handle.c index d80e4e3..9d928fb 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -30,8 +30,8 @@ void handle_dap_data_request(usbip_stage2_header *header) data_in = &(data_in[sizeof(usbip_stage2_header)]); // Point to the beginning of the URB packet dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); - handle_dap_data_response(header); - //send_stage2_submit(header, 0, 0); + //handle_dap_data_response(header); + send_stage2_submit(header, 0, 0); } void handle_dap_data_response(usbip_stage2_header *header) { diff --git a/main/usbip_server.c b/main/usbip_server.c index f9ad467..2227bd2 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -283,7 +283,7 @@ static int handle_submit(usbip_stage2_header *header) } else { - // os_printf("EP 01 DATA TO HOST"); + os_printf("EP 01 DATA TO HOST\r\n"); handle_dap_data_response(header); } break; @@ -334,7 +334,7 @@ void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t send(kSock, req_header, sizeof(usbip_stage2_header), 0); } -void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const uint8_t *const data, int32_t data_length) +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length) { send_stage2_submit(req_header, status, data_length); From c3582e8e2beda2b547fe8783ea319ad2354dc628 Mon Sep 17 00:00:00 2001 From: windowsair Date: Sun, 2 Feb 2020 14:49:14 +0800 Subject: [PATCH 13/21] feat: Switch to USB HID, now fully available --- components/DAP/config/DAP_config.h | 243 +++++++++++++++++++++-------- components/USBIP/USB_handle.c | 57 +++++-- components/USBIP/USBd_config.c | 98 ++++++++++++ components/USBIP/USBd_config.h | 46 ++++-- components/USBIP/usb_defs.h | 11 ++ main/DAP_handle.c | 4 +- main/main.c | 6 +- main/tcp_server.c | 35 +++-- main/usbip_server.c | 8 +- sdkconfig | 10 +- 10 files changed, 399 insertions(+), 119 deletions(-) diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index a61956e..226145b 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -34,11 +34,42 @@ #include "gpio.h" #include "gpio_struct.h" #include "timer_struct.h" - - - - - +#include "esp8266/pin_mux_register.h" +#define GPIO_PIN_REG_0 PERIPHS_IO_MUX_GPIO0_U +#define GPIO_PIN_REG_1 PERIPHS_IO_MUX_U0TXD_U +#define GPIO_PIN_REG_2 PERIPHS_IO_MUX_GPIO2_U +#define GPIO_PIN_REG_3 PERIPHS_IO_MUX_U0RXD_U +#define GPIO_PIN_REG_4 PERIPHS_IO_MUX_GPIO4_U +#define GPIO_PIN_REG_5 PERIPHS_IO_MUX_GPIO5_U +#define GPIO_PIN_REG_6 PERIPHS_IO_MUX_SD_CLK_U +#define GPIO_PIN_REG_7 PERIPHS_IO_MUX_SD_DATA0_U +#define GPIO_PIN_REG_8 PERIPHS_IO_MUX_SD_DATA1_U +#define GPIO_PIN_REG_9 PERIPHS_IO_MUX_SD_DATA2_U +#define GPIO_PIN_REG_10 PERIPHS_IO_MUX_SD_DATA3_U +#define GPIO_PIN_REG_11 PERIPHS_IO_MUX_SD_CMD_U +#define GPIO_PIN_REG_12 PERIPHS_IO_MUX_MTDI_U +#define GPIO_PIN_REG_13 PERIPHS_IO_MUX_MTCK_U +#define GPIO_PIN_REG_14 PERIPHS_IO_MUX_MTMS_U +#define GPIO_PIN_REG_15 PERIPHS_IO_MUX_MTDO_U +#define GPIO_PIN_REG_16 PAD_XPD_DCDC_CONF +#define GPIO_PIN_REG(i) \ + (i==0) ? GPIO_PIN_REG_0: \ + (i==1) ? GPIO_PIN_REG_1: \ + (i==2) ? GPIO_PIN_REG_2: \ + (i==3) ? GPIO_PIN_REG_3: \ + (i==4) ? GPIO_PIN_REG_4: \ + (i==5) ? GPIO_PIN_REG_5: \ + (i==6) ? GPIO_PIN_REG_6: \ + (i==7) ? GPIO_PIN_REG_7: \ + (i==8) ? GPIO_PIN_REG_8: \ + (i==9) ? GPIO_PIN_REG_9: \ + (i==10)? GPIO_PIN_REG_10: \ + (i==11)? GPIO_PIN_REG_11: \ + (i==12)? GPIO_PIN_REG_12: \ + (i==13)? GPIO_PIN_REG_13: \ + (i==14)? GPIO_PIN_REG_14: \ + (i==15)? GPIO_PIN_REG_15: \ + GPIO_PIN_REG_16 //************************************************************************************************** /** \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information @@ -63,7 +94,7 @@ This information includes: /// Processor Clock of the Cortex-M MCU used in the Debug Unit. /// This value is used to calculate the SWD/JTAG clock speed. -#define CPU_CLOCK 160000000U ///< Specifies the CPU Clock in Hz. +#define CPU_CLOCK 160000000 ///< Specifies the CPU Clock in Hz. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz /// Number of processor cycles for I/O Port write operations. @@ -80,7 +111,7 @@ This information includes: /// Indicate that JTAG communication mode is available at the Debug Port. /// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. +#define DAP_JTAG 0 ///< JTAG Mode: 1 = available, 0 = not available. /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. @@ -100,7 +131,7 @@ This information includes: /// This configuration settings is used to optimize the communication performance with the /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, /// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. -#define DAP_PACKET_SIZE 512U ///< Specifies Packet Size in bytes. +#define DAP_PACKET_SIZE 64U ///< Specifies Packet Size in bytes. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 512 for High-speed USB WinUSB. /// Maximum Package Buffers for Command and Response data. @@ -111,22 +142,22 @@ This information includes: /// Indicate that UART Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define SWO_UART 1 ///< SWO UART: 1 = available, 0 = not available. +#define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available. /// Maximum SWO UART Baudrate. -#define SWO_UART_MAX_BAUDRATE (115200U*40U) ///< SWO UART Maximum Baudrate in Hz. +#define SWO_UART_MAX_BAUDRATE (115200U * 40U) ///< SWO UART Maximum Baudrate in Hz. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz //// TODO: uncertain value /// Indicate that Manchester Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define SWO_MANCHESTER 1 ///< SWO Manchester: 1 = available, 0 = not available. +#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. /// SWO Trace Buffer Size. #define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). /// SWO Streaming Trace. -#define SWO_STREAM 1 ///< SWO Streaming Trace: 1 = available, 0 = not available. +#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. /// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. #define TIMESTAMP_CLOCK 5000000U ///< Timestamp clock in Hz (0 = timestamps not supported). @@ -168,7 +199,7 @@ __STATIC_INLINE uint8_t DAP_GetVendorString(char *str) __STATIC_INLINE uint8_t DAP_GetProductString(char *str) { //(void)str; - strcpy(str, "CMSIS-DAP v2"); + strcpy(str, "CMSIS-DAP v2"); return (sizeof("CMSIS-DAP v2")); } @@ -180,7 +211,7 @@ __STATIC_INLINE uint8_t DAP_GetProductString(char *str) */ __STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) { - strcpy(str, "1234"); + strcpy(str, "1234"); return (sizeof("1234")); } @@ -189,14 +220,14 @@ __STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) // Modify your pins here // ATTENTION: DO NOT USE RTC GPIO16 -#define PIN_SWDIO 2 -#define PIN_SWCLK 0 -#define PIN_TDO 4 -#define PIN_TDI 5 -#define PIN_nTRST 1 // optional -#define PIN_nRESET 16 +#define PIN_SWDIO 4 +#define PIN_SWCLK 5 +#define PIN_TDO 13 +#define PIN_TDI 12 +#define PIN_nTRST 0 // optional +#define PIN_nRESET 14 // LED_BUILTIN -#define PIN_LED_CONNECTED 13 +#define PIN_LED_CONNECTED 2 // LED_BUILTIN #define PIN_LED_RUNNING 15 @@ -244,16 +275,49 @@ of the same I/O port. The following SWDIO I/O Pin functions are provided: */ __STATIC_INLINE void PORT_JTAG_SETUP(void) { - gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); - gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); + gpio_pin_reg_t pin_reg; - gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); - gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); + // gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); + // gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); + GPIO.enable_w1ts |= (0x1 << PIN_SWCLK); + GPIO.pin[PIN_SWCLK].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWCLK)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWCLK), pin_reg.val); + GPIO.enable_w1ts |= (0x1 << PIN_SWDIO); + GPIO.pin[PIN_SWDIO].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWDIO)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWDIO), pin_reg.val); - gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); - gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); - gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); + // gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); + GPIO.enable_w1tc |= (0x1 << PIN_TDO); + GPIO.pin[PIN_TDO].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDO)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDO), pin_reg.val); + // gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); + GPIO.enable_w1ts |= (0x1 << PIN_TDI); + GPIO.pin[PIN_TDI].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDI)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDI), pin_reg.val); + + // gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); + // gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); + GPIO.enable_w1tc |= (0x1 << PIN_nTRST); + GPIO.pin[PIN_nTRST].driver = 1; + GPIO.enable_w1tc |= (0x1 << PIN_nRESET); + GPIO.pin[PIN_nRESET].driver = 1; + + // gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); + // gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nTRST)); + pin_reg.pullup = 1; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_nTRST), pin_reg.val); + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nRESET)); + pin_reg.pullup = 1; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_nRESET), pin_reg.val); } /** @@ -265,16 +329,49 @@ __STATIC_INLINE void PORT_JTAG_SETUP(void) */ __STATIC_INLINE void PORT_SWD_SETUP(void) { - gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); - gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); + gpio_pin_reg_t pin_reg; - gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); - gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); + // gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); + // gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); + GPIO.enable_w1ts |= (0x1 << PIN_SWCLK); + GPIO.pin[PIN_SWCLK].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWCLK)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWCLK), pin_reg.val); + GPIO.enable_w1ts |= (0x1 << PIN_SWDIO); + GPIO.pin[PIN_SWDIO].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWDIO)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWDIO), pin_reg.val); - gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); - gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); - gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); - gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); + // gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); + GPIO.enable_w1tc |= (0x1 << PIN_TDO); + GPIO.pin[PIN_TDO].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDO)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDO), pin_reg.val); + // gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); + GPIO.enable_w1ts |= (0x1 << PIN_TDI); + GPIO.pin[PIN_TDI].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDI)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDI), pin_reg.val); + + // gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); + // gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); + GPIO.enable_w1tc |= (0x1 << PIN_nTRST); + GPIO.pin[PIN_nTRST].driver = 1; + GPIO.enable_w1tc |= (0x1 << PIN_nRESET); + GPIO.pin[PIN_nRESET].driver = 1; + + // gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); + // gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nTRST)); + pin_reg.pullup = 1; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_nTRST), pin_reg.val); + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nRESET)); + pin_reg.pullup = 1; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_nRESET), pin_reg.val); } /** @@ -286,14 +383,31 @@ __STATIC_INLINE void PORT_SWD_SETUP(void) __STATIC_INLINE void PORT_OFF(void) { // Will be called when the DAP disconnected - gpio_set_direction(PIN_SWCLK, GPIO_MODE_DEF_DISABLE); - gpio_set_direction(PIN_SWDIO, GPIO_MODE_DEF_DISABLE); + // gpio_set_direction(PIN_SWCLK, GPIO_MODE_DEF_DISABLE); + // gpio_set_direction(PIN_SWDIO, GPIO_MODE_DEF_DISABLE); - gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_DISABLE); - gpio_set_direction(PIN_TDI, GPIO_MODE_DEF_DISABLE); + // gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_DISABLE); + // gpio_set_direction(PIN_TDI, GPIO_MODE_DEF_DISABLE); - gpio_set_direction(PIN_nTRST, GPIO_MODE_DEF_DISABLE); - gpio_set_direction(PIN_nRESET, GPIO_MODE_DEF_DISABLE); + // gpio_set_direction(PIN_nTRST, GPIO_MODE_DEF_DISABLE); + // gpio_set_direction(PIN_nRESET, GPIO_MODE_DEF_DISABLE); + GPIO.pin[PIN_SWCLK].driver = 0; + GPIO.enable_w1tc |= (0x1 << PIN_SWCLK); + + GPIO.pin[PIN_SWDIO].driver = 0; + GPIO.enable_w1tc |= (0x1 << PIN_SWDIO); + + GPIO.pin[PIN_TDO].driver = 0; + GPIO.enable_w1tc |= (0x1 << PIN_TDO); + + GPIO.pin[PIN_TDI].driver = 0; + GPIO.enable_w1tc |= (0x1 << PIN_TDI); + + GPIO.pin[PIN_nTRST].driver = 0; + GPIO.enable_w1tc |= (0x1 << PIN_nTRST); + + GPIO.pin[PIN_nRESET].driver = 0; + GPIO.enable_w1tc |= (0x1 << PIN_nRESET); } // SWCLK/TCK I/O pin ------------------------------------- @@ -306,7 +420,7 @@ __STATIC_INLINE void PORT_OFF(void) __STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) { ////TODO: can we set to 0? - return ((GPIO.in >> PIN_SWCLK) & 0x1); + return 0; } /** @@ -338,7 +452,7 @@ __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) */ __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) { - return ((GPIO.in >> PIN_SWDIO) & 0x1); + return ((GPIO.in >> PIN_SWDIO) & 0x1) ? 1 : 0; } /** @@ -368,7 +482,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) */ __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) { - return ((GPIO.in >> PIN_SWDIO) & 0x1); + return ((GPIO.in >> PIN_SWDIO) & 0x1) ? 1 : 0; } /** @@ -388,11 +502,13 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) { //set bit GPIO.out_w1ts |= (0x1 << PIN_SWDIO); + } else { //reset bit GPIO.out_w1tc |= (0x1 << PIN_SWDIO); + } } @@ -407,6 +523,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) // set \ref gpio_set_direction -> OUTPUT GPIO.enable_w1ts |= (0x1 << PIN_SWDIO); + GPIO.pin[PIN_SWDIO].driver = 0; } /** @@ -420,6 +537,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) // set \ref gpio_set_dircetion -> INPUT // esp8266 input is always connected GPIO.enable_w1tc |= (0x1 << PIN_SWDIO); + GPIO.pin[PIN_SWDIO].driver = 0; } // TDI Pin I/O --------------------------------------------- @@ -431,7 +549,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) */ __STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) { - return ((GPIO.in >> PIN_TDI) & 0x1); + return ((GPIO.in >> PIN_TDI) & 0x1) ? 1 : 0; } /** @@ -446,11 +564,13 @@ __STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) { //set bit GPIO.out_w1ts |= (0x1 << PIN_TDI); + } else { //reset bit GPIO.out_w1tc |= (0x1 << PIN_TDI); + } } @@ -463,7 +583,7 @@ __STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) */ __STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) { - return ((GPIO.in >> PIN_TDI) & 0x1); + return ((GPIO.in >> PIN_TDO) & 0x1) ? 1 : 0; } // nTRST Pin I/O ------------------------------------------- @@ -475,7 +595,7 @@ __STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) */ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) { - return ((GPIO.in >> PIN_nTRST) & 0x1); + return 0; // not available } /** @@ -487,17 +607,18 @@ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) */ __STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) { - ////TODO: What does this mean? ? ? - if ((bit & 1U) == 1) - { - //set bit - GPIO.out_w1ts |= (0x1 << PIN_nTRST); - } - else - { - //reset bit - GPIO.out_w1tc |= (0x1 << PIN_nTRST); - } + // ////TODO: What does this mean? ? ? + // if ((bit & 1U) == 1) + // { + // //set bit + // GPIO.out_w1ts |= (0x1 << PIN_nTRST); + // } + // else + // { + // //reset bit + // GPIO.out_w1tc |= (0x1 << PIN_nTRST); + // } + ; // not available } // nRESET Pin I/O------------------------------------------ @@ -509,7 +630,7 @@ __STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) */ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) { - return ((GPIO.in >> PIN_nRESET) & 0x1); + return ((GPIO.in >> PIN_nRESET) & 0x1) ? 1 : 0; } /** diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index 666d026..62ba946 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -19,11 +19,18 @@ #include "usb_defs.h" #include "MSOS20Descriptors.h" +// const char *strings_list[] = { +// 0, // reserved: available languages +// "windowsair", +// "CMSIS-DAP v2", +// "1234", +// }; + const char *strings_list[] = { - 0, // reserved: available languages - "windowsair", - "CMSIS-DAP v2", - "1234", + 0, // reserved: available languages + "windowsair", + "esp8266 CMSIS-DAP", + "1234", }; // handle functions static void handleGetDescriptor(usbip_stage2_header *header); @@ -106,6 +113,10 @@ void handleUSBControlRequest(usbip_stage2_header *header) break; case 0x80: // *IMPORTANT* +#if (USE_WINUSB == 0) + case 0x81: +#endif + { switch (header->u.cmd_submit.request.bRequest) { case USB_REQ_GET_CONFIGURATION: @@ -125,6 +136,8 @@ void handleUSBControlRequest(usbip_stage2_header *header) break; } break; + } +#if (USE_WINUSB == 1) case 0x81: // ignore... switch (header->u.cmd_submit.request.bRequest) { @@ -147,7 +160,7 @@ void handleUSBControlRequest(usbip_stage2_header *header) break; } break; - +#endif case 0x82: // ignore... switch (header->u.cmd_submit.request.bRequest) { @@ -182,8 +195,22 @@ void handleUSBControlRequest(usbip_stage2_header *header) header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest, *wIndex); break; } + break; } - break; + case 0x21: // Set_Idle for HID + switch (header->u.cmd_submit.request.bRequest) + { + case USB_REQ_SET_IDLE: + os_printf("* SET IDLE\r\n"); + send_stage2_submit(header, 0, 0); + break; + + default: + os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", + header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); + break; + } + break; default: os_printf("USB unknown request, bmRequestType:%d,bRequest:%d\r\n", header->u.cmd_submit.request.bmRequestType, header->u.cmd_submit.request.bRequest); @@ -222,7 +249,7 @@ static void handleGetDescriptor(usbip_stage2_header *header) break; case USB_DT_STRING: - os_printf("* GET 0x03 STRING DESCRIPTOR\r\n"); + //os_printf("* GET 0x03 STRING DESCRIPTOR\r\n"); if (header->u.cmd_submit.request.wValue.u8lo == 0) { @@ -231,27 +258,27 @@ static void handleGetDescriptor(usbip_stage2_header *header) } else if (header->u.cmd_submit.request.wValue.u8lo != 0xee) { - os_printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); - os_printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); + //os_printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); + //os_printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); int slen = strlen(strings_list[header->u.cmd_submit.request.wValue.u8lo]); int wslen = slen * 2; int buff_len = sizeof(usb_string_descriptor) + wslen; - char temp_buff[256]; + char temp_buff[64]; usb_string_descriptor *desc = (usb_string_descriptor *)temp_buff; desc->bLength = buff_len; desc->bDescriptorType = USB_DT_STRING; for (int i = 0; i < slen; i++) { desc->wData[i] = strings_list[header->u.cmd_submit.request.wValue.u8lo][i]; - send_stage2_submit_data(header, 0, (uint8_t *)temp_buff, buff_len); + } + send_stage2_submit_data(header, 0, (uint8_t *)temp_buff, buff_len); } else { os_printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); os_printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); os_printf("***Unsupported String descriptor***\r\n"); - } break; @@ -293,8 +320,14 @@ static void handleGetDescriptor(usbip_stage2_header *header) os_printf("* GET 0x0F BOS DESCRIPTOR\r\n"); send_stage2_submit_data(header, 0, bosDescriptor, sizeof(bosDescriptor)); break; + case USB_DT_HID_REPORT: + os_printf("* GET 0x22 HID REPORT DESCRIPTOR"); + send_stage2_submit_data(header, 0, (void *)kHidReportDescriptor, sizeof(kHidReportDescriptor)); + break; default: os_printf("USB unknown Get Descriptor requested:%d\r\n", header->u.cmd_submit.request.wValue.u8lo); + os_printf("low bit :%d\r\n",header->u.cmd_submit.request.wValue.u8lo); + os_printf("high bit :%d\r\n",header->u.cmd_submit.request.wValue.u8hi); break; } } diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c index f28d636..598e7d9 100644 --- a/components/USBIP/USBd_config.c +++ b/components/USBIP/USBd_config.c @@ -54,6 +54,8 @@ const uint8_t kUSBd0DeviceDescriptor[0x12] = // Standard Interface Descriptor + +#if (USE_WINUSB ==1) const uint8_t kUSBd0InterfaceDescriptor[0x1E]= { 0x09, // bLength @@ -118,8 +120,58 @@ const uint8_t kUSBd0InterfaceDescriptor[0x1E]= }; +#else +const uint8_t kUSBd0InterfaceDescriptor[0x20]= +{ + 0x09, // bLength + USB_DT_INTERFACE, // bDescriptorType + USBD_CUSTOM_CLASS0_IF0_NUM, // bInterfaceNumber + USBD_CUSTOM_CLASS0_IF0_ALT, // bAlternateSetting + 0x02, // bNumEndpoints ----> 2 endpoint for USB HID + // + USBD_CUSTOM_CLASS0_IF0_CLASS, // bInterfaceClass + USBD_CUSTOM_CLASS0_IF0_SUBCLASS, // bInterfaceSubClass + USBD_CUSTOM_CLASS0_IF0_PROTOCOL, // bInterfaceProtocol + 0x00, // iInterface + // Index of string descriptor describing this interface + + // HID Descriptor + 0x09, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType1 + 0x21, 0x00, // wDescriptorLength1 + + // Standard Endpoint Descriptor + + // We perform all transfer operations on Pysical endpoint 1. + + /* Pysical endpoint 1 */ + + 0x07, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x81, // bEndpointAddress + USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes + USBShort(64), // wMaxPacketSize + 0xff, // bInterval + + /* Pysical endpoint 1 */ + + 0x07, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x01, // bEndpointAddress + USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes + USBShort(64), // wMaxPacketSize + 0xff, // bInterval +}; +#endif + // Standard Configuration Descriptor #define LENGTHOFCONFIGDESCRIPTOR 9 + +#if (USE_WINUSB == 1) const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = { // Configuration descriptor header. @@ -139,6 +191,52 @@ const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = USBD0_CFG_DESC_BMAXPOWER, // bMaxPower }; +#else +const uint8_t kUSBd0ConfigDescriptor[LENGTHOFCONFIGDESCRIPTOR] = +{ + // Configuration descriptor header. + + 0x09, // bLength + USB_DT_CONFIGURATION, // bDescriptorType + + USBShort((sizeof(kUSBd0InterfaceDescriptor)) + (LENGTHOFCONFIGDESCRIPTOR)), + // wTotalLength + + 0x01, // bNumInterfaces + // There is only one interface in the CMSIS-DAP project + 0x01, // bConfigurationValue: 0x01 is used to select this configuration */ + 0x00, // iConfiguration: no string to describe this configuration */ + USBD0_CFG_DESC_BMATTRIBUTES, // bmAttributes + + USBD0_CFG_DESC_BMAXPOWER, // bMaxPower +}; +#endif + + +// USB HID Report Descriptor +const uint8_t kHidReportDescriptor[0x21] = { + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x01, // Usage (0x01) + 0xA1, 0x01, // Collection (Application) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x40, // Report Count (64) + 0x09, 0x01, // Usage (0x01) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x40, // Report Count (64) + 0x09, 0x01, // Usage (0x01) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x95, 0x01, // Report Count (1) + 0x09, 0x01, // Usage (0x01) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0xC0, // End Collection + // 33 bytes +}; + + + + /** diff --git a/components/USBIP/USBd_config.h b/components/USBIP/USBd_config.h index 6af8944..dc3a3e2 100644 --- a/components/USBIP/USBd_config.h +++ b/components/USBIP/USBd_config.h @@ -1,34 +1,39 @@ #ifndef __USBD_CONFIG_H__ #define __USBD_CONFIG_H__ +#define USE_WINUSB 0 + // Vendor ID assigned by USB-IF (idVendor). -#define USBD0_DEV_DESC_IDVENDOR 0xC251 +#define USBD0_DEV_DESC_IDVENDOR 0xC251 // Product ID assigned by manufacturer (idProduct). -#define USBD0_DEV_DESC_IDPRODUCT 0xF00A +#define USBD0_DEV_DESC_IDPRODUCT 0xF00A // Device Release Number in binary-coded decimal (bcdDevice). -#define USBD0_DEV_DESC_BCDDEVICE 0x0100 +#define USBD0_DEV_DESC_BCDDEVICE 0x0100 // Maximum packet size for Endpoint 0 (bMaxPacketSize0). -#define USBD0_MAX_PACKET0 64 +#define USBD0_MAX_PACKET0 64 // If disabled Serial Number String will not be assigned to USB Device. -#define USBD0_STR_DESC_SER_EN 1 +#define USBD0_STR_DESC_SER_EN 1 // bmAttributes -#define USBD0_CFG_DESC_BMATTRIBUTES 0x80 +#define USBD0_CFG_DESC_BMATTRIBUTES 0x80 // bMaxPower -#define USBD0_CFG_DESC_BMAXPOWER 250 - +#define USBD0_CFG_DESC_BMAXPOWER 250 // Interface Number -#define USBD_CUSTOM_CLASS0_IF0_NUM 0 +#define USBD_CUSTOM_CLASS0_IF0_NUM 0 // Alternate Setting -#define USBD_CUSTOM_CLASS0_IF0_ALT 0 +#define USBD_CUSTOM_CLASS0_IF0_ALT 0 // Class Code -#define USBD_CUSTOM_CLASS0_IF0_CLASS 0xFF // 0xFF: Vendor Specific +#if (USE_WINUSB == 1) +#define USBD_CUSTOM_CLASS0_IF0_CLASS 0xFF // 0xFF: Vendor Specific +#else +#define USBD_CUSTOM_CLASS0_IF0_CLASS 0x03 // 0x03: HID class +#endif // Subclass Code #define USBD_CUSTOM_CLASS0_IF0_SUBCLASS 0x00 @@ -36,19 +41,26 @@ // Protocol Code #define USBD_CUSTOM_CLASS0_IF0_PROTOCOL 0x00 - - - - ///////////////////////////////////////////// + +// common part extern const uint8_t kUSBd0DeviceDescriptor[0x12]; -extern const uint8_t kUSBd0InterfaceDescriptor[0x1E]; -extern const uint8_t kUSBd0ConfigDescriptor[0x09]; extern const uint8_t kLangDescriptor[0x04]; extern const uint8_t kManufacturerString[0x28]; extern const uint8_t kProductString[0x18]; extern const uint8_t kSerialNumberString[0x1A]; + +#if (USE_WINUSB == 1) +extern const uint8_t kUSBd0InterfaceDescriptor[0x1E]; +extern const uint8_t kUSBd0ConfigDescriptor[0x09]; extern const uint8_t kInterfaceString[0x2C]; +#else +extern const uint8_t kUSBd0InterfaceDescriptor[0x20]; +extern const uint8_t kUSBd0ConfigDescriptor[0x09]; +extern const uint8_t kInterfaceString[0x2C]; +extern const uint8_t kHidReportDescriptor[0x21]; + +#endif #endif \ No newline at end of file diff --git a/components/USBIP/usb_defs.h b/components/USBIP/usb_defs.h index c33fa06..0377dc4 100644 --- a/components/USBIP/usb_defs.h +++ b/components/USBIP/usb_defs.h @@ -98,6 +98,14 @@ typedef struct #define USB_REQ_GET_INTERFACE 10 #define USB_REQ_SET_INTERFACE 11 #define USB_REQ_SET_SYNCH_FRAME 12 + +// USB HID Request +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_GET_IDLE 0x02 +#define USB_REQ_GET_PROTOCOL 0x03 +#define USB_REQ_SET_REPORT 0x09 +#define USB_REQ_SET_IDLE 0X0A +#define USB_REQ_SET_PROTOCOL 0X0B /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// @@ -115,6 +123,9 @@ typedef struct #define USB_DT_OTG 9 #define USB_DT_DEBUG 10 #define USB_DT_INTERFACE_ASSOCIATION 11 +/* USB HID */ +#define USB_DT_HID 0x21 +#define USB_DT_HID_REPORT 0x22 /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// diff --git a/main/DAP_handle.c b/main/DAP_handle.c index 9d928fb..4f51da4 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -14,7 +14,7 @@ #include "DAP.h" #include "esp_libc.h" ////TODO: Merge this -#define DAP_PACKET_SIZE 512 +#define DAP_PACKET_SIZE 64 static uint8_t data_out[DAP_PACKET_SIZE]; static int dap_respond = 0; @@ -40,7 +40,7 @@ void handle_dap_data_response(usbip_stage2_header *header) //os_printf("*** Will respond"); - send_stage2_submit_data(header, 0, data_out, (dap_respond & 0x0000FFFF)); + send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); dap_respond = 0; //os_printf("*** RESPONDED ***"); } diff --git a/main/main.c b/main/main.c index 5676c15..b26615d 100644 --- a/main/main.c +++ b/main/main.c @@ -140,9 +140,9 @@ void app_main() DAP_Setup(); // DAP Setup xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL); - xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); + xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 20, NULL); // SWO Trace Task - xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); - xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); + //xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); + //xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); } diff --git a/main/tcp_server.c b/main/tcp_server.c index fbb16b7..834381f 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -31,9 +31,10 @@ uint8_t kState = ACCEPTING; int kSock = -1; + void tcp_server_task(void *pvParameters) { - uint8_t rx_buffer[2048]; + uint8_t tcp_rx_buffer[256]; char addr_str[128]; int addr_family; int ip_protocol; @@ -101,7 +102,7 @@ void tcp_server_task(void *pvParameters) while (1) { - int len = recv(kSock, rx_buffer, 2047, 0); + int len = recv(kSock, tcp_rx_buffer, 255, 0); // Error occured during receiving if (len < 0) { @@ -117,19 +118,19 @@ void tcp_server_task(void *pvParameters) // Data received else { -#ifdef CONFIG_EXAMPLE_IPV6 - // Get the sender's ip address as string - if (sourceAddr.sin6_family == PF_INET) - { - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - } - else if (sourceAddr.sin6_family == PF_INET6) - { - inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); - } -#else - inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); -#endif +// #ifdef CONFIG_EXAMPLE_IPV6 +// // Get the sender's ip address as string +// if (sourceAddr.sin6_family == PF_INET) +// { +// inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); +// } +// else if (sourceAddr.sin6_family == PF_INET6) +// { +// inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); +// } +// #else +// inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); +// #endif switch (kState) { @@ -137,11 +138,11 @@ void tcp_server_task(void *pvParameters) kState = ATTACHING; case ATTACHING: - attach(rx_buffer, len); + attach(tcp_rx_buffer, len); break; case EMULATING: - emulate(rx_buffer, len); + emulate(tcp_rx_buffer, len); break; default: os_printf("unkonw kstate!\r\n"); diff --git a/main/usbip_server.c b/main/usbip_server.c index 2227bd2..9c41eef 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -31,6 +31,9 @@ static void handle_unlink(usbip_stage2_header *header); // unlink helper function static void send_stage2_unlink(usbip_stage2_header *req_header); +static void fast_submit_reply(usbip_stage2_header *req_header); + + int attach(uint8_t *buffer, uint32_t length) { int command = read_stage1_command(buffer, length); @@ -197,6 +200,7 @@ int emulate(uint8_t *buffer, uint32_t length) default: os_printf("emulate unknown command:%d\r\n", command); + handle_submit((usbip_stage2_header *)buffer); return -1; } return 0; @@ -278,12 +282,12 @@ static int handle_submit(usbip_stage2_header *header) case 0x01: if (header->base.direction == 0) { - // os_printf("EP 01 DATA FROM HOST"); + //os_printf("EP 01 DATA FROM HOST"); handle_dap_data_request(header); } else { - os_printf("EP 01 DATA TO HOST\r\n"); + // os_printf("EP 01 DATA TO HOST\r\n"); handle_dap_data_response(header); } break; diff --git a/sdkconfig b/sdkconfig index 0b1692e..08378b1 100644 --- a/sdkconfig +++ b/sdkconfig @@ -25,7 +25,7 @@ CONFIG_ESPTOOLPY_BAUD_921600B=y # CONFIG_ESPTOOLPY_BAUD_2MB is not set # CONFIG_ESPTOOLPY_BAUD_OTHER is not set CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 -CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_BAUD=115200 CONFIG_ESPTOOLPY_COMPRESSED=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y # CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set @@ -42,10 +42,10 @@ CONFIG_SPI_FLASH_FREQ=0x0 # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y -# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="8MB" -CONFIG_SPI_FLASH_SIZE=0x800000 +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_ESPTOOLPY_FLASHSIZE="16MB" +CONFIG_SPI_FLASH_SIZE=0x1000000 CONFIG_ESPTOOLPY_BEFORE_RESET=y # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set CONFIG_ESPTOOLPY_BEFORE="default_reset" From ede735c2a73ed8a911190ec33cd2fb477c493acb Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 4 Feb 2020 20:45:01 +0800 Subject: [PATCH 14/21] feat: Improve DAP performance on USB-HID --- components/DAP/config/DAP_config.h | 45 ++----- components/DAP/include/DAP.h | 30 +++-- components/DAP/include/cmsis_compiler.h | 35 ++++++ components/DAP/source/DAP.c | 4 + components/USBIP/USB_handle.c | 2 +- components/USBIP/USBd_config.c | 8 +- main/DAP_handle.c | 155 ++++++++++++++++++++++-- main/DAP_handle.h | 5 +- main/main.c | 10 +- main/tcp_server.c | 32 ++--- main/usbip_server.c | 18 ++- sdkconfig | 62 +++++----- 12 files changed, 277 insertions(+), 129 deletions(-) diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index 226145b..7121a2e 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -35,41 +35,7 @@ #include "gpio_struct.h" #include "timer_struct.h" #include "esp8266/pin_mux_register.h" -#define GPIO_PIN_REG_0 PERIPHS_IO_MUX_GPIO0_U -#define GPIO_PIN_REG_1 PERIPHS_IO_MUX_U0TXD_U -#define GPIO_PIN_REG_2 PERIPHS_IO_MUX_GPIO2_U -#define GPIO_PIN_REG_3 PERIPHS_IO_MUX_U0RXD_U -#define GPIO_PIN_REG_4 PERIPHS_IO_MUX_GPIO4_U -#define GPIO_PIN_REG_5 PERIPHS_IO_MUX_GPIO5_U -#define GPIO_PIN_REG_6 PERIPHS_IO_MUX_SD_CLK_U -#define GPIO_PIN_REG_7 PERIPHS_IO_MUX_SD_DATA0_U -#define GPIO_PIN_REG_8 PERIPHS_IO_MUX_SD_DATA1_U -#define GPIO_PIN_REG_9 PERIPHS_IO_MUX_SD_DATA2_U -#define GPIO_PIN_REG_10 PERIPHS_IO_MUX_SD_DATA3_U -#define GPIO_PIN_REG_11 PERIPHS_IO_MUX_SD_CMD_U -#define GPIO_PIN_REG_12 PERIPHS_IO_MUX_MTDI_U -#define GPIO_PIN_REG_13 PERIPHS_IO_MUX_MTCK_U -#define GPIO_PIN_REG_14 PERIPHS_IO_MUX_MTMS_U -#define GPIO_PIN_REG_15 PERIPHS_IO_MUX_MTDO_U -#define GPIO_PIN_REG_16 PAD_XPD_DCDC_CONF -#define GPIO_PIN_REG(i) \ - (i==0) ? GPIO_PIN_REG_0: \ - (i==1) ? GPIO_PIN_REG_1: \ - (i==2) ? GPIO_PIN_REG_2: \ - (i==3) ? GPIO_PIN_REG_3: \ - (i==4) ? GPIO_PIN_REG_4: \ - (i==5) ? GPIO_PIN_REG_5: \ - (i==6) ? GPIO_PIN_REG_6: \ - (i==7) ? GPIO_PIN_REG_7: \ - (i==8) ? GPIO_PIN_REG_8: \ - (i==9) ? GPIO_PIN_REG_9: \ - (i==10)? GPIO_PIN_REG_10: \ - (i==11)? GPIO_PIN_REG_11: \ - (i==12)? GPIO_PIN_REG_12: \ - (i==13)? GPIO_PIN_REG_13: \ - (i==14)? GPIO_PIN_REG_14: \ - (i==15)? GPIO_PIN_REG_15: \ - GPIO_PIN_REG_16 + //************************************************************************************************** /** \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information @@ -97,6 +63,9 @@ This information includes: #define CPU_CLOCK 160000000 ///< Specifies the CPU Clock in Hz. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz +// This value is used to replace the largest 10MHZ speed clock in Keil +#define MAX_USER_CLOCK 10000000 ///< Specifies the max Debug Clock in Hz. + /// Number of processor cycles for I/O Port write operations. /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O /// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors @@ -111,7 +80,7 @@ This information includes: /// Indicate that JTAG communication mode is available at the Debug Port. /// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define DAP_JTAG 0 ///< JTAG Mode: 1 = available, 0 = not available. +#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. @@ -131,14 +100,14 @@ This information includes: /// This configuration settings is used to optimize the communication performance with the /// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, /// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. -#define DAP_PACKET_SIZE 64U ///< Specifies Packet Size in bytes. +#define DAP_PACKET_SIZE 255U ///< Specifies Packet Size in bytes. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 512 for High-speed USB WinUSB. /// Maximum Package Buffers for Command and Response data. /// This configuration settings is used to optimize the communication performance with the /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the /// setting can be reduced (valid range is 1 .. 255). -#define DAP_PACKET_COUNT 1U ///< Specifies number of packets buffered. +#define DAP_PACKET_COUNT 20 ///< Specifies number of packets buffered. /// Indicate that UART Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of Capabilities. diff --git a/components/DAP/include/DAP.h b/components/DAP/include/DAP.h index 516b83d..b467714 100644 --- a/components/DAP/include/DAP.h +++ b/components/DAP/include/DAP.h @@ -287,21 +287,25 @@ extern void DAP_Setup (void); #define USE_ASSEMBLY 0 -#if USE_ASSEMBLY == 0 -__STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) { - uint32_t count = delay; - while (--count); -} +#define USE_ASSEMBLY 1 + +#if (USE_ASSEMBLY == 0) + __STATIC_FORCEINLINE void PIN_DELAY_SLOW(uint32_t delay) + { + uint32_t count = delay; + while (--count) + ; + } #else -__STATIC_FORCEINLINE void PIN_DELAY_SLOW (uint32_t delay) { - __ASM volatile ( - ".syntax unified\n" - "0:\n\t" - "subs %0,%0,#1\n\t" - "bne 0b\n" - : "+l" (delay) : : "cc" - ); +__STATIC_FORCEINLINE void PIN_DELAY_SLOW(uint32_t delay) +{ + __asm__ volatile( + "l_PINDELAYSLOW%=:" + "ADDI.N %[time], %[time], -1;" + "BNEZ %[time], l_PINDELAYSLOW%=;" + : [time] "+r"(delay)); } + #endif // Fixed delay for fast clock generation diff --git a/components/DAP/include/cmsis_compiler.h b/components/DAP/include/cmsis_compiler.h index 349f5fd..aafbe21 100644 --- a/components/DAP/include/cmsis_compiler.h +++ b/components/DAP/include/cmsis_compiler.h @@ -11,5 +11,40 @@ #define __WEAK __attribute__((weak)) #endif +#define GPIO_PIN_REG_0 PERIPHS_IO_MUX_GPIO0_U +#define GPIO_PIN_REG_1 PERIPHS_IO_MUX_U0TXD_U +#define GPIO_PIN_REG_2 PERIPHS_IO_MUX_GPIO2_U +#define GPIO_PIN_REG_3 PERIPHS_IO_MUX_U0RXD_U +#define GPIO_PIN_REG_4 PERIPHS_IO_MUX_GPIO4_U +#define GPIO_PIN_REG_5 PERIPHS_IO_MUX_GPIO5_U +#define GPIO_PIN_REG_6 PERIPHS_IO_MUX_SD_CLK_U +#define GPIO_PIN_REG_7 PERIPHS_IO_MUX_SD_DATA0_U +#define GPIO_PIN_REG_8 PERIPHS_IO_MUX_SD_DATA1_U +#define GPIO_PIN_REG_9 PERIPHS_IO_MUX_SD_DATA2_U +#define GPIO_PIN_REG_10 PERIPHS_IO_MUX_SD_DATA3_U +#define GPIO_PIN_REG_11 PERIPHS_IO_MUX_SD_CMD_U +#define GPIO_PIN_REG_12 PERIPHS_IO_MUX_MTDI_U +#define GPIO_PIN_REG_13 PERIPHS_IO_MUX_MTCK_U +#define GPIO_PIN_REG_14 PERIPHS_IO_MUX_MTMS_U +#define GPIO_PIN_REG_15 PERIPHS_IO_MUX_MTDO_U +#define GPIO_PIN_REG_16 PAD_XPD_DCDC_CONF +#define GPIO_PIN_REG(i) \ + (i==0) ? GPIO_PIN_REG_0: \ + (i==1) ? GPIO_PIN_REG_1: \ + (i==2) ? GPIO_PIN_REG_2: \ + (i==3) ? GPIO_PIN_REG_3: \ + (i==4) ? GPIO_PIN_REG_4: \ + (i==5) ? GPIO_PIN_REG_5: \ + (i==6) ? GPIO_PIN_REG_6: \ + (i==7) ? GPIO_PIN_REG_7: \ + (i==8) ? GPIO_PIN_REG_8: \ + (i==9) ? GPIO_PIN_REG_9: \ + (i==10)? GPIO_PIN_REG_10: \ + (i==11)? GPIO_PIN_REG_11: \ + (i==12)? GPIO_PIN_REG_12: \ + (i==13)? GPIO_PIN_REG_13: \ + (i==14)? GPIO_PIN_REG_14: \ + (i==15)? GPIO_PIN_REG_15: \ + GPIO_PIN_REG_16 #endif \ No newline at end of file diff --git a/components/DAP/source/DAP.c b/components/DAP/source/DAP.c index 9e1f620..03f048c 100644 --- a/components/DAP/source/DAP.c +++ b/components/DAP/source/DAP.c @@ -377,6 +377,10 @@ static uint32_t DAP_SWJ_Clock(const uint8_t *request, uint8_t *response) { *response = DAP_ERROR; return ((4U << 16) | 1U); } + if(clock == 10000000){ + clock = MAX_USER_CLOCK; + } + if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { DAP_Data.fast_clock = 1U; diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index 62ba946..f9fe76a 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -321,7 +321,7 @@ static void handleGetDescriptor(usbip_stage2_header *header) send_stage2_submit_data(header, 0, bosDescriptor, sizeof(bosDescriptor)); break; case USB_DT_HID_REPORT: - os_printf("* GET 0x22 HID REPORT DESCRIPTOR"); + os_printf("* GET 0x22 HID REPORT DESCRIPTOR\r\n"); send_stage2_submit_data(header, 0, (void *)kHidReportDescriptor, sizeof(kHidReportDescriptor)); break; default: diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c index 598e7d9..0061a8b 100644 --- a/components/USBIP/USBd_config.c +++ b/components/USBIP/USBd_config.c @@ -155,7 +155,7 @@ const uint8_t kUSBd0InterfaceDescriptor[0x20]= 0x81, // bEndpointAddress USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes USBShort(64), // wMaxPacketSize - 0xff, // bInterval + 0x01, // bInterval /* Pysical endpoint 1 */ @@ -164,7 +164,7 @@ const uint8_t kUSBd0InterfaceDescriptor[0x20]= 0x01, // bEndpointAddress USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes USBShort(64), // wMaxPacketSize - 0xff, // bInterval + 0x01, // bInterval }; #endif @@ -221,10 +221,10 @@ const uint8_t kHidReportDescriptor[0x21] = { 0x15, 0x00, // Logical Minimum (0) 0x26, 0xFF, 0x00, // Logical Maximum (255) 0x75, 0x08, // Report Size (8) - 0x95, 0x40, // Report Count (64) + 0x95, 0xFF, // Report Count (64) 0x09, 0x01, // Usage (0x01) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x95, 0x40, // Report Count (64) + 0x95, 0xFF, // Report Count (64) 0x09, 0x01, // Usage (0x01) 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0x95, 0x01, // Report Count (1) diff --git a/main/DAP_handle.c b/main/DAP_handle.c index 4f51da4..a3bff99 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -1,20 +1,35 @@ /** * @file DAP_handle.c * @brief Handle DAP packets and transaction push - * @version 0.1 - * @date 2020-01-25 + * @version 0.2 + * @date 2020-02-04 * * @copyright Copyright (c) 2020 * */ #include +#include #include "usbip_server.h" #include "DAP_handle.h" #include "DAP.h" #include "esp_libc.h" +#include "USBd_config.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/ringbuf.h" +#include "freertos/semphr.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +extern int kSock; +extern TaskHandle_t kDAPTaskHandle; ////TODO: Merge this -#define DAP_PACKET_SIZE 64 +#define DAP_PACKET_SIZE 255 static uint8_t data_out[DAP_PACKET_SIZE]; static int dap_respond = 0; @@ -24,29 +39,40 @@ static int swo_trace_respond = 0; static uint8_t *swo_data_to_send; static uint32_t num_swo_data; -void handle_dap_data_request(usbip_stage2_header *header) +static RingbufHandle_t dap_dataIN_handle = NULL; +static RingbufHandle_t dap_dataOUT_handle = NULL; +static SemaphoreHandle_t data_response_mux = NULL; + +static void unpack(void *data, int size); + +void handle_dap_data_request(usbip_stage2_header *header, uint32_t length) { uint8_t *data_in = (uint8_t *)header; data_in = &(data_in[sizeof(usbip_stage2_header)]); // Point to the beginning of the URB packet + +#if (USE_WINUSB == 1) dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); //handle_dap_data_response(header); send_stage2_submit(header, 0, 0); +#else + xRingbufferSend(dap_dataIN_handle, data_in, length - sizeof(usbip_stage2_header), portMAX_DELAY); + //os_printf("LENGTH: %d\r\n", length - sizeof(usbip_stage2_header)); + xTaskNotifyGive(kDAPTaskHandle); + send_stage2_submit(header, 0, 0); + +#endif } + void handle_dap_data_response(usbip_stage2_header *header) { if (dap_respond) { - - //os_printf("*** Will respond"); - send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); dap_respond = 0; - //os_printf("*** RESPONDED ***"); } else { - //os_printf("*** Will NOT respond"); send_stage2_submit(header, 0, 0); } } @@ -56,14 +82,10 @@ void handle_swo_trace_response(usbip_stage2_header *header) if (swo_trace_respond) { swo_trace_respond = 0; - //os_printf("*** Will respond"); send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); - - //os_printf("*** RESPONDED ***"); } else { - //os_printf("*** Will NOT respond"); send_stage2_submit(header, 0, 0); } } @@ -83,4 +105,111 @@ void SWO_AbortTransfer(void) { //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U)); ////TODO: unlink might be useful ... +} + +void DAP_Thread(void *argument) +{ + dap_dataIN_handle = xRingbufferCreate(DAP_PACKET_SIZE * 20, RINGBUF_TYPE_BYTEBUF); + dap_dataOUT_handle = xRingbufferCreate(DAP_PACKET_SIZE * 10, RINGBUF_TYPE_BYTEBUF); + data_response_mux = xSemaphoreCreateMutex(); + size_t packetSize; + uint8_t *item; + + if (dap_dataIN_handle == NULL || dap_dataIN_handle == NULL || + data_response_mux == NULL) + { + os_printf("Can not create DAP ringbuf/mux!\r\n"); + vTaskDelete(NULL); + } + for (;;) + { + + while (1) + { + ulTaskNotifyTake(pdFALSE, portMAX_DELAY); + packetSize = 0; + item = (uint8_t *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize, + (1 / portTICK_RATE_MS), DAP_PACKET_SIZE); + if (packetSize == 0) + { + break; + } + + else if (packetSize < DAP_PACKET_SIZE) + { + os_printf("Wrong data in packet size:%d , data in remain: %d\r\n", packetSize, (int)xRingbufferGetMaxItemSize(dap_dataIN_handle)); + vRingbufferReturnItem(dap_dataIN_handle, (void *)item); + break; + // This may not happen because there is a semaphore acquisition + } + + if (item[0] == ID_DAP_QueueCommands) + item[0] = ID_DAP_ExecuteCommands; + DAP_ProcessCommand(item, data_out); + + vRingbufferReturnItem(dap_dataIN_handle, (void *)item); + xRingbufferSend(dap_dataOUT_handle, data_out, DAP_PACKET_SIZE, portMAX_DELAY); + if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) + { + ++dap_respond; + xSemaphoreGive(data_response_mux); + } + } + } +} + +int fast_reply(uint8_t *buf, uint32_t length) +{ + if (length == 48 && buf[3] == 1 && buf[15] == 1 && buf[19] == 1) + { + if (dap_respond > 0) + { + uint8_t *item; + size_t packetSize = 0; + item = (uint8_t *)xRingbufferReceiveUpTo(dap_dataOUT_handle, &packetSize, + (10 / portTICK_RATE_MS), DAP_PACKET_SIZE); + if (packetSize == DAP_PACKET_SIZE) + { + unpack((uint32_t *)buf, sizeof(usbip_stage2_header)); + send_stage2_submit_data((usbip_stage2_header *)buf, 0, item, DAP_PACKET_SIZE); + if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) + { + --dap_respond; + xSemaphoreGive(data_response_mux); + } + vRingbufferReturnItem(dap_dataOUT_handle, (void *)item); + return 1; + } + else if (packetSize > 0) + { + os_printf("Wrong data out packet size:%d!\r\n", packetSize); + } + ////TODO: fast reply + } + else + { + buf[3] = 0x3; // command + buf[15] = 0; // direction + buf[0x16] = 0; + buf[0x17] = 0; + buf[27] = 0; + buf[39] = 0; + send(kSock, buf, 48, 0); + return 1; + } + } + return 0; +} + +static void unpack(void *data, int size) +{ + + // Ignore the setup field + int sz = (size / sizeof(uint32_t)) - 2; + uint32_t *ptr = (uint32_t *)data; + + for (int i = 0; i < sz; i++) + { + ptr[i] = ntohl(ptr[i]); + } } \ No newline at end of file diff --git a/main/DAP_handle.h b/main/DAP_handle.h index 5ac91f2..2d71be2 100644 --- a/main/DAP_handle.h +++ b/main/DAP_handle.h @@ -3,7 +3,10 @@ #include "usbip_defs.h" -void handle_dap_data_request(usbip_stage2_header *header); +void handle_dap_data_request(usbip_stage2_header *header, uint32_t length); void handle_dap_data_response(usbip_stage2_header *header); void handle_swo_trace_response(usbip_stage2_header *header); + +int fast_reply(uint8_t *buf, uint32_t length); + #endif \ No newline at end of file diff --git a/main/main.c b/main/main.c index b26615d..6369f17 100644 --- a/main/main.c +++ b/main/main.c @@ -26,18 +26,17 @@ #include "tcp_server.h" #include "timer.h" #include "wifi_configuration.h" -/* The examples use simple WiFi configuration that you can set via - 'make menuconfig'. - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ + + extern void SWO_Thread(void *argument); extern void usart_monitor_task(void *argument); extern void DAP_Setup(void); +extern void DAP_Thread(void *argument); /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; +TaskHandle_t kDAPTaskHandle = NULL; const int IPV4_GOTIP_BIT = BIT0; #ifdef CONFIG_EXAMPLE_IPV6 @@ -141,6 +140,7 @@ void app_main() xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 20, NULL); + xTaskCreate(DAP_Thread, "DAP_Task", 2048, NULL, 22, &kDAPTaskHandle); // SWO Trace Task //xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); //xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); diff --git a/main/tcp_server.c b/main/tcp_server.c index 834381f..99e9fe8 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -34,7 +34,7 @@ int kSock = -1; void tcp_server_task(void *pvParameters) { - uint8_t tcp_rx_buffer[256]; + uint8_t tcp_rx_buffer[305]; char addr_str[128]; int addr_family; int ip_protocol; @@ -102,7 +102,7 @@ void tcp_server_task(void *pvParameters) while (1) { - int len = recv(kSock, tcp_rx_buffer, 255, 0); + int len = recv(kSock, tcp_rx_buffer, sizeof(tcp_rx_buffer), 0); // Error occured during receiving if (len < 0) { @@ -118,19 +118,19 @@ void tcp_server_task(void *pvParameters) // Data received else { -// #ifdef CONFIG_EXAMPLE_IPV6 -// // Get the sender's ip address as string -// if (sourceAddr.sin6_family == PF_INET) -// { -// inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); -// } -// else if (sourceAddr.sin6_family == PF_INET6) -// { -// inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); -// } -// #else -// inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); -// #endif + // #ifdef CONFIG_EXAMPLE_IPV6 + // // Get the sender's ip address as string + // if (sourceAddr.sin6_family == PF_INET) + // { + // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + // } + // else if (sourceAddr.sin6_family == PF_INET6) + // { + // inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + // } + // #else + // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + // #endif switch (kState) { @@ -155,6 +155,8 @@ void tcp_server_task(void *pvParameters) os_printf("Shutting down socket and restarting...\r\n"); //shutdown(kSock, 0); close(kSock); + if (kState == EMULATING) + kState = ACCEPTING; //shutdown(listen_sock, 0); //close(listen_sock); diff --git a/main/usbip_server.c b/main/usbip_server.c index 9c41eef..1eb2b75 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -11,6 +11,7 @@ #include "USBd_config.h" #include "DAP_handle.h" #include "USB_handle.h" +#include "USBd_config.h" // attach helper function static int read_stage1_command(uint8_t *buffer, uint32_t length); @@ -24,14 +25,13 @@ static void send_interface_info(); // emulate helper function static void pack(void *data, int size); static void unpack(void *data, int size); -static int handle_submit(usbip_stage2_header *header); +static int handle_submit(usbip_stage2_header *header, uint32_t length); static int read_stage2_command(usbip_stage2_header *header, uint32_t length); static void handle_unlink(usbip_stage2_header *header); // unlink helper function static void send_stage2_unlink(usbip_stage2_header *req_header); -static void fast_submit_reply(usbip_stage2_header *req_header); int attach(uint8_t *buffer, uint32_t length) @@ -182,6 +182,12 @@ static void send_interface_info() int emulate(uint8_t *buffer, uint32_t length) { // usbip_stage2_header header; + #if (USE_WINUSB == 0) + if(fast_reply(buffer, length)) + { + return 0; + } + #endif int command = read_stage2_command((usbip_stage2_header *)buffer, length); if (command < 0) { @@ -191,7 +197,7 @@ int emulate(uint8_t *buffer, uint32_t length) switch (command) { case USBIP_STAGE2_REQ_SUBMIT: - handle_submit((usbip_stage2_header *)buffer); + handle_submit((usbip_stage2_header *)buffer , length); break; case USBIP_STAGE2_REQ_UNLINK: @@ -200,7 +206,7 @@ int emulate(uint8_t *buffer, uint32_t length) default: os_printf("emulate unknown command:%d\r\n", command); - handle_submit((usbip_stage2_header *)buffer); + //handle_submit((usbip_stage2_header *)buffer, length); return -1; } return 0; @@ -269,7 +275,7 @@ static void unpack(void *data, int size) * @brief USB transaction processing * */ -static int handle_submit(usbip_stage2_header *header) +static int handle_submit(usbip_stage2_header *header, uint32_t length) { switch (header->base.ep) { @@ -283,7 +289,7 @@ static int handle_submit(usbip_stage2_header *header) if (header->base.direction == 0) { //os_printf("EP 01 DATA FROM HOST"); - handle_dap_data_request(header); + handle_dap_data_request(header ,length); } else { diff --git a/sdkconfig b/sdkconfig index 08378b1..4db752e 100644 --- a/sdkconfig +++ b/sdkconfig @@ -25,7 +25,7 @@ CONFIG_ESPTOOLPY_BAUD_921600B=y # CONFIG_ESPTOOLPY_BAUD_2MB is not set # CONFIG_ESPTOOLPY_BAUD_OTHER is not set CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 -CONFIG_ESPTOOLPY_BAUD=115200 +CONFIG_ESPTOOLPY_BAUD=921600 CONFIG_ESPTOOLPY_COMPRESSED=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y # CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set @@ -33,12 +33,12 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y # CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set CONFIG_ESPTOOLPY_FLASHMODE="dio" CONFIG_SPI_FLASH_MODE=0x0 -# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set -CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set # CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set -CONFIG_ESPTOOLPY_FLASHFREQ="40m" -CONFIG_SPI_FLASH_FREQ=0x0 +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +CONFIG_SPI_FLASH_FREQ=0xf # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set @@ -76,9 +76,9 @@ CONFIG_EXAMPLE_IPV4=y CONFIG_EXAMPLE_PORT=3333 # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y -CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE is not set # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y # CONFIG_COMPILER_CXX_EXCEPTIONS is not set CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y # CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set @@ -87,7 +87,7 @@ CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y # CONFIG_COMPILER_STACK_CHECK is not set # CONFIG_COMPILER_WARN_WRITE_STRINGS is not set CONFIG_APP_UPDATE_CHECK_APP_SUM=y -# CONFIG_APP_UPDATE_CHECK_APP_HASH is not set +CONFIG_APP_UPDATE_CHECK_APP_HASH=y # CONFIG_AWS_IOT_SDK is not set # CONFIG_USING_ESP_CONSOLE is not set CONFIG_ESP_TLS_USING_MBEDTLS=y @@ -107,8 +107,8 @@ CONFIG_ESP_FILENAME_MACRO_NO_PATH=y # CONFIG_ESP_FILENAME_MACRO_NULL is not set CONFIG_USING_NEW_ETS_VPRINTF=y # CONFIG_LINK_ETS_PRINTF_TO_IRAM is not set -# CONFIG_SOC_FULL_ICACHE is not set -CONFIG_SOC_IRAM_SIZE=0xC000 +CONFIG_SOC_FULL_ICACHE=y +CONFIG_SOC_IRAM_SIZE=0x8000 CONFIG_CONSOLE_UART_DEFAULT=y # CONFIG_CONSOLE_UART_CUSTOM is not set # CONFIG_CONSOLE_UART_NONE is not set @@ -130,7 +130,6 @@ CONFIG_TASK_WDT_TIMEOUT_S=15 CONFIG_RESET_REASON=y CONFIG_WIFI_PPT_TASKSTACK_SIZE=2048 CONFIG_EVENT_LOOP_STACK_SIZE=2048 -CONFIG_ESP8266_CORE_GLOBAL_DATA_LINK_IRAM=y # CONFIG_ESP8266_OTA_FROM_OLD is not set # CONFIG_ESP8266_BOOT_COPY_APP is not set CONFIG_ESP_ERR_TO_NAME_LOOKUP=y @@ -141,7 +140,7 @@ CONFIG_WIFI_TX_RATE_SEQUENCE_FROM_HIGH=y # CONFIG_ESP8266_WIFI_QOS_ENABLED is not set # CONFIG_ESP8266_WIFI_AMPDU_RX_ENABLED is not set # CONFIG_ESP8266_WIFI_AMSDU_ENABLED is not set -CONFIG_ESP8266_WIFI_RX_BUFFER_NUM=16 +CONFIG_ESP8266_WIFI_RX_BUFFER_NUM=26 CONFIG_ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM=4 CONFIG_ESP8266_WIFI_RX_PKT_NUM=7 CONFIG_ESP8266_WIFI_TX_PKT_NUM=6 @@ -151,8 +150,8 @@ CONFIG_ESP8266_WIFI_CONNECT_OPEN_ROUTER_WHEN_PWD_IS_SET=y CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y # CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set CONFIG_ESP_PHY_INIT_DATA_VDD33_CONST=33 -CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER=20 -# CONFIG_ESP8266_HSPI_HIGH_THROUGHPUT is not set +CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER=21 +CONFIG_ESP8266_HSPI_HIGH_THROUGHPUT=y CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y CONFIG_HTTP_BUF_SIZE=512 CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 @@ -166,33 +165,31 @@ CONFIG_FREERTOS_MAX_HOOK=2 CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 CONFIG_FREERTOS_ISR_STACKSIZE=512 # CONFIG_FREERTOS_EXTENED_HOOKS is not set -CONFIG_FREERTOS_GLOBAL_DATA_LINK_IRAM=y -# CONFIG_FREERTOS_CODE_LINK_TO_IRAM is not set +CONFIG_FREERTOS_CODE_LINK_TO_IRAM=y CONFIG_FREERTOS_TIMER_STACKSIZE=2048 CONFIG_TASK_SWITCH_FASTER=y # CONFIG_USE_QUEUE_SETS is not set # CONFIG_ENABLE_FREERTOS_SLEEP is not set # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set # CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set -# CONFIG_HEAP_DISABLE_IRAM is not set +CONFIG_HEAP_DISABLE_IRAM=y # CONFIG_LOG_DEFAULT_LEVEL_NONE is not set -# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y # CONFIG_LOG_DEFAULT_LEVEL_WARN is not set -CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set # CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set # CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set -CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_DEFAULT_LEVEL=1 CONFIG_LOG_COLORS=y # CONFIG_LOG_SET_LEVEL is not set -# CONFIG_LWIP_USE_IRAM is not set -# CONFIG_LWIP_HIGH_THROUGHPUT is not set -CONFIG_LWIP_GLOBAL_DATA_LINK_IRAM=y -CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_USE_IRAM=y +CONFIG_LWIP_HIGH_THROUGHPUT=y +CONFIG_TCPIP_RECVMBOX_SIZE=64 CONFIG_LWIP_ARP_TABLE_SIZE=10 CONFIG_LWIP_ARP_MAXAGE=300 # CONFIG_LWIP_ESP_GRATUITOUS_ARP is not set CONFIG_LWIP_SOCKET_MULTITHREAD=y -# CONFIG_ENABLE_NONBLOCK_SPEEDUP is not set +CONFIG_ENABLE_NONBLOCK_SPEEDUP=y CONFIG_SET_SOLINGER_DEFAULT=y CONFIG_ESP_UDP_SYNC_SEND=y CONFIG_ESP_UDP_SYNC_RETRY_MAX=5 @@ -202,8 +199,8 @@ CONFIG_LWIP_SO_REUSE_RXTOALL=y # CONFIG_LWIP_SO_RCVBUF is not set CONFIG_LWIP_RECV_BUFSIZE_DEFAULT=11680 CONFIG_LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT=10000 -# CONFIG_LWIP_IP_FRAG is not set -# CONFIG_LWIP_IP_REASSEMBLY is not set +CONFIG_LWIP_IP_FRAG=y +CONFIG_LWIP_IP_REASSEMBLY=y CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 # CONFIG_LWIP_IP_SOF_BROADCAST is not set # CONFIG_LWIP_IP_SOF_BROADCAST_RECV is not set @@ -221,7 +218,7 @@ CONFIG_LWIP_IGMP=y CONFIG_ESP_DNS=y CONFIG_DNS_MAX_SERVERS=3 # CONFIG_LWIP_NETIF_LOOPBACK is not set -# CONFIG_TCP_HIGH_SPEED_RETRANSMISSION is not set +CONFIG_TCP_HIGH_SPEED_RETRANSMISSION=y CONFIG_LWIP_MAX_ACTIVE_TCP=5 CONFIG_LWIP_MAX_LISTENING_TCP=8 CONFIG_TCP_MAXRTX=12 @@ -229,7 +226,7 @@ CONFIG_TCP_SYNMAXRTX=6 CONFIG_TCP_MSS=1460 CONFIG_TCP_SND_BUF_DEFAULT=2920 CONFIG_TCP_WND_DEFAULT=5840 -CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_RECVMBOX_SIZE=16 CONFIG_TCP_QUEUE_OOSEQ=y CONFIG_TCP_OVERSIZE_MSS=y # CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set @@ -237,7 +234,7 @@ CONFIG_TCP_OVERSIZE_MSS=y # CONFIG_LWIP_TCP_TIMESTAMPS is not set CONFIG_LWIP_MAX_UDP_PCBS=4 CONFIG_UDP_RECVMBOX_SIZE=6 -CONFIG_TCPIP_TASK_STACK_SIZE=2048 +CONFIG_TCPIP_TASK_STACK_SIZE=4096 CONFIG_LWIP_MAX_RAW_PCBS=4 # CONFIG_LWIP_IPV6 is not set # CONFIG_LWIP_STATS is not set @@ -343,7 +340,6 @@ CONFIG_OPENSSL_ASSERT_DO_NOTHING=y # CONFIG_ENABLE_PTHREAD is not set # CONFIG_USING_SPIFFS is not set CONFIG_IP_LOST_TIMER_INTERVAL=120 -CONFIG_TCPIP_ADAPTER_GLOBAL_DATA_LINK_IRAM=y # CONFIG_util_assert is not set CONFIG_ESP_SHA=y CONFIG_ESP_AES=y @@ -372,9 +368,9 @@ CONFIG_MONITOR_BAUD_OTHER_VAL=74880 CONFIG_MONITOR_BAUD=74880 # CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set CONFIG_OPTIMIZATION_LEVEL_RELEASE=y -CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED is not set # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=y # CONFIG_CXX_EXCEPTIONS is not set CONFIG_STACK_CHECK_NONE=y # CONFIG_STACK_CHECK_NORM is not set From 3ffc698550012e3466a1851fed4f6f6b508d5b7b Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 4 Feb 2020 20:58:16 +0800 Subject: [PATCH 15/21] fix: Fix duplicate definitions & Remove redundant build configurations --- components/DAP/include/DAP.h | 2 -- main/Kconfig.projbuild | 37 ------------------------------------ sdkconfig | 5 ----- 3 files changed, 44 deletions(-) delete mode 100644 main/Kconfig.projbuild diff --git a/components/DAP/include/DAP.h b/components/DAP/include/DAP.h index b467714..65e0459 100644 --- a/components/DAP/include/DAP.h +++ b/components/DAP/include/DAP.h @@ -285,8 +285,6 @@ extern void DAP_Setup (void); #define DELAY_SLOW_CYCLES 3U // Number of cycles for one iteration #endif -#define USE_ASSEMBLY 0 - #define USE_ASSEMBLY 1 #if (USE_ASSEMBLY == 0) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild deleted file mode 100644 index c1209ac..0000000 --- a/main/Kconfig.projbuild +++ /dev/null @@ -1,37 +0,0 @@ -menu "Example Configuration" - -config WIFI_SSID - string "WiFi SSID" - default "myssid" - help - SSID (network name) for the example to connect to. - -config WIFI_PASSWORD - string "WiFi Password" - default "mypassword" - help - WiFi password (WPA or WPA2) for the example to use. - Can be left blank if the network has no security set. - -choice EXAMPLE_IP_MODE - prompt "IP Version" - help - Example can use either IPV4 or IPV6. - -config EXAMPLE_IPV4 - bool "IPV4" - -config EXAMPLE_IPV6 - bool "IPV6" - select LWIP_IPV6 - -endchoice - -config EXAMPLE_PORT - int "Port" - range 0 65535 - default 3333 - help - Local port the example server will listen on. - -endmenu diff --git a/sdkconfig b/sdkconfig index 4db752e..e20f324 100644 --- a/sdkconfig +++ b/sdkconfig @@ -69,11 +69,6 @@ CONFIG_PARTITION_TABLE_SINGLE_APP=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" -CONFIG_WIFI_SSID="myssid" -CONFIG_WIFI_PASSWORD="mypassword" -CONFIG_EXAMPLE_IPV4=y -# CONFIG_EXAMPLE_IPV6 is not set -CONFIG_EXAMPLE_PORT=3333 # CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE is not set From 33977e20ddbe3d94c5895645049bf992a20f6cda Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 4 Feb 2020 21:43:25 +0800 Subject: [PATCH 16/21] feat: Add CI --- .travis.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..cdd9b30 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +language: c +sudo: required +before_install: +- sudo apt install -y gcc git wget make libncurses-dev flex bison gperf python python-serial +- wget https://dl.espressif.com/dl/xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz + +install: +- tar -xzf ./xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz +- git clone --recursive https://github.com/espressif/ESP8266_RTOS_SDK.git +- python -m pip install --user -r ./ESP8266_RTOS_SDK/requirements.txt + +before_script: +- sudo IDF_PATH=$PWD/ESP8266_RTOS_SDK +- sudo PATH="$PATH:$PWD/xtensa-lx106-elf/bin" + +script: +- ./idf.py fullclean +- ./idf.py build + +deploy: + provider: releases + api_key: ${GITHUB_TOKEN} + file: + - ./build/esp8266_dap.bin + skip_cleanup: true + on: + tags: true \ No newline at end of file From de763c3aee3b1b95cc112a10c30dd3ac407a3c3a Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 4 Feb 2020 22:23:01 +0800 Subject: [PATCH 17/21] fix: Try to remove unsupported dependencies --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cdd9b30..7ce7992 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ language: c sudo: required before_install: -- sudo apt install -y gcc git wget make libncurses-dev flex bison gperf python python-serial +- sudo apt install -y gcc git wget make libncurses-dev flex bison python python-serial - wget https://dl.espressif.com/dl/xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz install: From 0cb03cc0dba404f7872bd7936e0fd2790ea0180a Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 4 Feb 2020 22:26:21 +0800 Subject: [PATCH 18/21] fix: Fix some rookie mistakes --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7ce7992..97b8c37 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,8 @@ install: - python -m pip install --user -r ./ESP8266_RTOS_SDK/requirements.txt before_script: -- sudo IDF_PATH=$PWD/ESP8266_RTOS_SDK -- sudo PATH="$PATH:$PWD/xtensa-lx106-elf/bin" +- sudo export IDF_PATH=$PWD/ESP8266_RTOS_SDK +- sudo export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" script: - ./idf.py fullclean From e42c57d820242cab362fdeab25892cf5a4385351 Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 4 Feb 2020 22:29:54 +0800 Subject: [PATCH 19/21] fix: Fix some rookie mistakes --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 97b8c37..494cf9d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,8 @@ install: - python -m pip install --user -r ./ESP8266_RTOS_SDK/requirements.txt before_script: -- sudo export IDF_PATH=$PWD/ESP8266_RTOS_SDK -- sudo export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" +- export IDF_PATH=$PWD/ESP8266_RTOS_SDK +- export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" script: - ./idf.py fullclean From 6b81d9c30a6ee5701aff1a912d70518f9dd752a7 Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 4 Feb 2020 22:32:32 +0800 Subject: [PATCH 20/21] fix: Fix some rookie mistakes --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 494cf9d..45b689f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,8 @@ before_script: - export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" script: -- ./idf.py fullclean -- ./idf.py build +- python ./idf.py fullclean +- python ./idf.py build deploy: provider: releases From fc1a16d7de7f9d129e877a2d0fb475c1ee04d0d2 Mon Sep 17 00:00:00 2001 From: windowsair Date: Wed, 5 Feb 2020 18:53:10 +0800 Subject: [PATCH 21/21] docs: Update doc --- LICENSE | 21 +++++ README.md | 156 +++++++++++++++++++++++++++++++++++++- main/main.c | 4 +- main/wifi_configuration.h | 4 +- 4 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e14fa0d --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 windowsair + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 4a1abdf..b8f4a0d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,159 @@ -# Attention +

+

Wireless ESP8266 DAP

+ +[![Build Status](https://travis-ci.com/windowsair/wireless-esp8266-dap.svg?branch=master)](https://travis-ci.com/windowsair/wireless-esp8266-dap) master +[![Build Status](https://travis-ci.com/windowsair/wireless-esp8266-dap.svg?branch=develop)](https://travis-ci.com/windowsair/wireless-esp8266-dap) develop + +[![](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square)](https://github.com/windowsair/wireless-esp8266-dap/LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blue.svg?style=flat-square)](https://github.com/windowsair/wireless-esp8266-dap/pulls) [![%e2%9d%a4](https://img.shields.io/badge/made%20with-%e2%9d%a4-ff69b4.svg?style=flat-square)](https://github.com/windowsair/wireless-esp8266-dap) + + +## Introduce + +Wireless debugging with ***only one ESP8266*** ! + +Realized by USBIP and CMSIS-DAP protocol stack. + +> 👉 5m distance, 100kb size firmware flash test: + +

+ +## Feature + +1. Debug Communication Mode + - [x] SWJ + - [x] JTAG + +2. USB Communication Mode + - [x] USB-HID + - [ ] WCID & WinUSB + +3. Debug Trace + - [ ] UART Serial Wire Output(SWO) + - [ ] SWO Streaming Trace + +4. More.. + - [x] Custom maximum debug clock(more than 10MHz) + - [ ] ... + + + +## Link your board + +1. WIFI + +The default connected WIFI SSID is `DAP` , password `12345678` + +You can change `WIFI_SSID` and ` WIFI_PASS` in [wifi_configuration.h](main/wifi_configuration.h) + +2. Debugger + +- SWD + +| SWD | | +|----------------|--------| +| SWCLK | GPIO5 | +| SWDIO | GPIO4 | +| LED\_CONNECTED | GPIO2 | +| LED\_RUNNING | GPIO15 | +| TVCC | 3V3 | +| GND | GND | + +- JTAG + +| JTAG | | +|--------------------|---------| +| TCK | GPIO5 | +| TMS | GPIO4 | +| TDI | GPIO13 | +| TDO | GPIO12 | +| nTRST \(optional\) | GPIO0\* | +| nRESET | GPIO14 | +| LED\_CONNECTED | GPIO2 | +| LED\_RUNNING | GPIO15 | +| TVCC | 3V3 | +| GND | GND | + +You can modify these pin definitions in [DAP_config.h](components/DAP/config/DAP_config.h) + +> Tips: Try to avoid using `GPIO0`(working mode switch) and `GPIO16`(RTC) + +## Build + +1. Get ESP8266 RTOS Software Development Kit + +See: [ESP8266_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK "ESP8266_RTOS_SDK") + +2. Build & Flash + +Build with ESP-IDF build system. +More information can be found at the following link: [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html "Build System") + +The following example shows a possible way to build on Windows: + +```bash +# Build +python ./idf.py build +# Flash +python ./idf.py -p /dev/ttyS5 flash +``` + +> We also provided sample firmware quick evaluation. See [Releases](https://github.com/windowsair/wireless-esp8266-dap/releases) + + +## Usage + +1. Get USBIP project + +- Windows: [usbip-windows](https://github.com/george-hopkins/usbip-windows "usbip-windows") . Or you can find it already built here: https://github.com/barbalion/usbip-win-client +- Linux: Distributed as part of the kernel + +2. Start esp8266 and connect it to the device to be debugged + +3. Connect it with usbip: + +```bash +.\usbip.exe -D -a 1-1 +``` + +If all goes well, you should see your device connected. +![image](https://user-images.githubusercontent.com/17078589/73833411-eb3f6d80-4844-11ea-8501-02a008f6119d.png) + +![target](https://user-images.githubusercontent.com/17078589/73830040-eb3c6f00-483e-11ea-85ee-c40b68a836b2.png) + + + +## Develop + +> Credits to: +> - https://github.com/thevoidnn/esp8266-wifi-cmsis-dap for adapter firmware based on CMSIS-DAP v1.0 +> - https://github.com/ARM-software/CMSIS_5 for CMSIS + + +In this repo you can find the complete implementation of the USB protocol stack including USB-HID, WCID, WinUSB. Although WinUSB-based mode currently does not work on USBIP :disappointed_relieved: . They are very easy and can help you quickly build your own DAP on other hardware platforms. + + +Currently using USB-HID for transmission is still slightly slower, If you have any ideas, welcome: +- [New issues](https://github.com/windowsair/wireless-esp8266-dap/issues) +- [New pull](https://github.com/windowsair/wireless-esp8266-dap/pulls) + + +### Issue + +2-4 + +Due to the limitation of USB-HID (I'm not sure if this is a problem with USBIP or Windows), now each URB packet can only reach 255 bytes (About 1MBps bandwidth), which has not reached the upper limit of ESP8266 transmission bandwidth. + +I now have an idea to construct a Man-in-the-middle between the two to forward traffic, thereby increasing the bandwidth of each transmission. + +1-31 At present, the adaptation to WCID, WinUSB, etc. has all been completed. However, when transmitting data on the endpoint, we received an error message from USBIP. This is most likely a problem with the USBIP project itself. Due to the completeness of the USBIP protocol document, we have not yet understood its role in the Bulk transmission process, which may also lead to errors in subsequent processes. -We will continue to try to make it work under USB HID. Once the USBIP problem is solved, we will immediately transfer it to work under WinUSB \ No newline at end of file +We will continue to try to make it work on USB HID. Once the USBIP problem is solved, we will immediately transfer it to work on WinUSB + + + +## License +[MIT LICENSE](LICENSE) \ No newline at end of file diff --git a/main/main.c b/main/main.c index 6369f17..bc92117 100644 --- a/main/main.c +++ b/main/main.c @@ -103,8 +103,8 @@ static void initialise_wifi(void) ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); wifi_config_t wifi_config = { .sta = { - .ssid = EXAMPLE_WIFI_SSID, - .password = EXAMPLE_WIFI_PASS, + .ssid = WIFI_SSID, + .password = WIFI_PASS, }, }; os_printf("Setting WiFi configuration SSID %s...\r\n", wifi_config.sta.ssid); diff --git a/main/wifi_configuration.h b/main/wifi_configuration.h index 407261e..5f84b6d 100644 --- a/main/wifi_configuration.h +++ b/main/wifi_configuration.h @@ -10,8 +10,8 @@ #ifndef __WIFI_CONFIGURATION__ #define __WIFI_CONFIGURATION__ -#define EXAMPLE_WIFI_SSID "DAP" -#define EXAMPLE_WIFI_PASS "12345678" +#define WIFI_SSID "DAP" +#define WIFI_PASS "12345678" #define PORT 3240