diff --git a/README.md b/README.md index 943ef50..d05c649 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -

-

Wireless ESP8266 DAP

+

-[![Build Status](https://github.com/windowsair/wireless-esp8266-dap/workflows/build/badge.svg?branch=master)](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Amaster) master +![image](https://user-images.githubusercontent.com/17078589/107857220-05ecef00-6e68-11eb-9fa0-506b32052dba.png) + + +[![Build Status](https://github.com/windowsair/wireless-esp8266-dap/workflows/build/badge.svg?branch=master)](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Amaster) masterγ€€ [![Build Status](https://github.com/windowsair/wireless-esp8266-dap/workflows/build/badge.svg?branch=develop)](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Adevelop) 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) +[![](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 @@ -13,19 +15,20 @@ Wireless debugging with ***only one ESP8266*** ! Realized by USBIP and CMSIS-DAP protocol stack. -> πŸ‘‰ 5m distance, 100kb size firmware flash test: +> πŸ‘‰ 5m distance, 100kb size firmware(Hex) flash test: -

+

## Feature -1. Debug Communication Mode - - [x] SWD - - [x] JTAG +1. Debug Communication Mode & Debug Port + - [x] SWD(SW-DP) + - [x] JTAG(JTAG-DP) + - [x] SWJ-DP 2. USB Communication Mode - - [x] USB-HID (Default) - - [x] WCID & WinUSB (Experimental) + - [x] USB-HID + - [x] WCID & WinUSB (Default) 3. Debug Trace - [ ] UART Serial Wire Output(SWO) @@ -53,8 +56,9 @@ You can change `WIFI_SSID` and ` WIFI_PASS` in [wifi_configuration.h](main/wifi_ | SWD | | |----------------|--------| -| SWCLK | GPIO5 | -| SWDIO | GPIO4 | +| SWCLK | GPIO14 | +| SWDIO | GPIO12 | +| SWDIO_MOSI | GPIO13 | | LED\_CONNECTED | GPIO2 | | LED\_RUNNING | GPIO15 | | TVCC | 3V3 | @@ -66,30 +70,43 @@ You can change `WIFI_SSID` and ` WIFI_PASS` in [wifi_configuration.h](main/wifi_ | JTAG | | |--------------------|---------| -| TCK | GPIO5 | -| TMS | GPIO4 | -| TDI | GPIO13 | -| TDO | GPIO12 | +| TCK | GPIO14 | +| TMS | GPIO13 | +| TDI | GPIO4 | +| TDO | GPIO16 | | nTRST \(optional\) | GPIO0\* | -| nRESET | GPIO14 | +| nRESET | GPIO5 | | 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) +In order to use SPI acceleration, you need to physically connect `SWDIO(GPIO12)` to `SWDIO_MOSI(GPIO13)`. -## Build +Here, we give a simple example for reference: -You can build locally or use Github Action to build online +![sch](https://user-images.githubusercontent.com/17078589/107851862-f9589e80-6e47-11eb-9eca-e80760822a6a.png) + +Alternatively, you can connect directly with wires as we gave at the beginning, without additional circuits. + + +> If you need to modify the LED or JTAG pins, please refer to the instructions in [DAP_config.h](components/DAP/config/DAP_config.h) to modify them carefully. + + +------ + + +## Build And Flash + +You can build locally or use Github Action to build online and then download firmware to flash. ### Build with Github Action Online See: [Build with Github Action](https://github.com/windowsair/wireless-esp8266-dap/wiki/Build-with-Github-Action) -### General build + +### General build and Flash 1. Get ESP8266 RTOS Software Development Kit @@ -117,9 +134,8 @@ python ./idf.py -p /dev/ttyS5 flash 1. Get USBIP project -- Windows: [usbip-win](https://github.com/cezanne/usbip-win) . -> The pre-compiled version on SourceForge is also available, for HID mode only, but it may be faster. -- Linux: Distributed as part of the kernel +- Windows: [usbip-win](https://github.com/cezanne/usbip-win) . +- Linux: Distributed as part of the Linux kernel, but we have not yet tested on Linux platform, and the following instructions are all under Windows platform. 2. Start esp8266 and connect it to the device to be debugged @@ -131,6 +147,7 @@ python ./idf.py -p /dev/ttyS5 flash # or usbip old version .\usbip.exe -D -a 1-1 +# πŸ‘‰ Recommend # HID Mode Or WinUSB Mode # for usbip-win 0.3.0 kmdf ude .\usbip.exe attach_ude -r -b 1-1 @@ -139,31 +156,38 @@ python ./idf.py -p /dev/ttyS5 flash If all goes well, you should see your device connected. -![image](https://user-images.githubusercontent.com/17078589/73833411-eb3f6d80-4844-11ea-8501-02a008f6119d.png) +![image](https://user-images.githubusercontent.com/17078589/107849548-f903d780-6e36-11eb-846f-3eaf0c0dc089.png) -Then test it under MDK: +Here, we use MDK for testing: ![target](https://user-images.githubusercontent.com/17078589/73830040-eb3c6f00-483e-11ea-85ee-c40b68a836b2.png) +------ + + +## Speed Strategy + +The maximum rate of esp8266 pure IO is about 2MHz. +When you select max clock, we will take the following actions: + +- `clock < 2Mhz` : Similar to the clock speed you choose. +- `2MHz <= clock < 10MHz` : Use the fastest pure IO speed. +- `clock >= 10MHz` : SPI acceleration using 40MHz clock. + +> Note that the most significant speed constraint of this project is still the TCP connection speed. ## Develop 0. Check other branches to know the latest development progress. -1. Use WinUSB Mode: +1. Use WinUSB Mode(enabled by default): change `USE_WINUSB` macor in [USBd_config.h](components/USBIP/USBd_config.h) -> 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 -> - https://github.com/cezanne/usbip-win for usbip windows - - 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. @@ -198,6 +222,22 @@ Due to the completeness of the USBIP protocol document, we have not yet understo 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 +------ + +# Credit + + +Credits to the following project, people and organizations: + +> - 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 +> - https://github.com/cezanne/usbip-win for usbip windows + + +- @HeavenSpree +- @Zy19930907 +- @caiguang1997 + ## License [MIT LICENSE](LICENSE) \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index fcf2d24..c3b724d 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -1,774 +1,710 @@ -/* - * 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 -#include -#include "cmsis_compiler.h" -#include "gpio.h" -#include "gpio_struct.h" -#include "timer_struct.h" -#include "esp8266/pin_mux_register.h" - -#include "spi_switch.h" -#include "dap_configuration.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 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 16000000 ///< 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 -/// 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 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 255 ///< 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 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. -// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 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 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 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). -// <<<<<<<<<<<<<<<<<<<<<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; - strcpy(str, "windowsair"); - return (sizeof("windowsair")); -} - -/** - * @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; - strcpy(str, "CMSIS-DAP v2"); - return (sizeof("CMSIS-DAP v2")); -} - -/** - * @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) -{ - strcpy(str, "1234"); - return (sizeof("1234")); -} - -///@} - -// Modify your pins here - -// ATTENTION: DO NOT USE RTC GPIO16 -#define PIN_SWDIO 12 -#define PIN_SWDIO_MOSI 13 // SPI MOSI -#define PIN_SWCLK 14 -#define PIN_TDO 4 -#define PIN_TDI 0 -#define PIN_nTRST 0 // optional -#define PIN_nRESET 5 -// LED_BUILTIN -#define PIN_LED_CONNECTED 2 -// 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_pin_reg_t pin_reg; - - // 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_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); -} - -/** - * @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_pin_reg_t pin_reg; - - - // PIN_SWCLK -> OUTPUT - // PIN_SWDIO -> 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); - - DAP_SPI_Disable(); - GPIO.out_w1tc |= (0x1 << PIN_SWCLK); - GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI); - - - - // 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); -} - -/** - * @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); - // 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_SWDIO].driver = 0; - // GPIO.enable_w1tc |= (0x1 << PIN_SWDIO_MOSI); - DAP_SPI_Disable(); - GPIO.out_w1tc |= (0x1 << PIN_SWCLK); - GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI); - - - 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 ------------------------------------- - -/** - * @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 0; -} - -/** - * @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) ? 1 : 0; -} - -/** - * @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_MOSI); -} - -/** - * @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_MOSI); -} - -/** - * @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) ? 1 : 0; -} - -/** - * @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_MOSI); - - } - else - { - //reset bit - GPIO.out_w1tc |= (0x1 << PIN_SWDIO_MOSI); - - } -} - -/** - * @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 - //// TODO: low speed - // set \ref gpio_set_direction -> OUTPUT - // GPIO.enable_w1ts |= (0x1 << PIN_SWDIO_MOSI); - // GPIO.pin[PIN_SWDIO_MOSI].driver = 0; - do {}while (0); - -} - -/** - * @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_MOSI); - // GPIO.pin[PIN_SWDIO_MOSI].driver = 0; - GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI); -} - -// 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) ? 1 : 0; -} - -/** - * @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) & 0x1) ? 1 : 0; -} - -// 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 0; // not available -} - -/** - * @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) -{ - // Vendor reset sequence - ; // not available -} - -// 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) ? 1 : 0; -} - -/** - * @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) -{ - // Vendor reset sequence - //// FIXME: unavailable - 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 23-bit countdown timer - return (0x7FFFFF - (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) -{ - DAP_SPI_Init(); - DAP_SPI_Disable(); - - - // 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); - - PORT_OFF(); -} - -/** 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__ */ +/* + * 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) + * + *---------------------------------------------------------------------------*/ + +/** + * @file DAP_config.h + * @author windowsair + * @brief Adaptation of GPIO and SPI pin + * @change: 2021-2-10 Support GPIO and SPI + * @version 0.1 + * @date 2021-2-10 + * + * @copyright Copyright (c) 2021 + * + */ + + +#ifndef __DAP_CONFIG_H__ +#define __DAP_CONFIG_H__ + +#include +#include +#include "cmsis_compiler.h" +#include "gpio.h" +#include "gpio_struct.h" +#include "timer_struct.h" +#include "esp8266/pin_mux_register.h" + +#include "gpio_op.h" +#include "spi_switch.h" +#include "dap_configuration.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 160000000 ///< Specifies the CPU Clock in Hz. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz + + +//#define MAX_USER_CLOCK 16000000 ///< 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 +/// 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 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 255 ///< 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 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. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 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 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 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). +// <<<<<<<<<<<<<<<<<<<<<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; + strcpy(str, "windowsair"); + return (sizeof("windowsair")); +} + +/** + * @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; + strcpy(str, "CMSIS-DAP v2"); + return (sizeof("CMSIS-DAP v2")); +} + +/** + * @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) +{ + strcpy(str, "1234"); + return (sizeof("1234")); +} + +///@} + + +// Note: DO NOT modify these pins: PIN_SWDIO PIN_SWDIO_MOSI PIN_SWCLK +// Modify the following pins carefully: PIN_TDO +#define PIN_SWDIO 12 // SPI MISO +#define PIN_SWDIO_MOSI 13 // SPI MOSI +#define PIN_SWCLK 14 +#define PIN_TDO 16 // device TDO -> Host Data Input (use RTC pin 16) +#define PIN_TDI 4 +#define PIN_nTRST 0 // optional +#define PIN_nRESET 5 +// LED_BUILTIN +#define PIN_LED_CONNECTED 2 +// 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_pin_reg_t pin_reg; + + + // set TCK, TMS pin + DAP_SPI_Deinit(); + + + // use RTC pin 16 + // output disable + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, ((READ_PERI_REG(PAD_XPD_DCDC_CONF) & (uint32_t)0xffffffbc)) | (uint32_t)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection + CLEAR_PERI_REG_MASK(RTC_GPIO_CONF, 0x1); // mux configuration for out enable + CLEAR_PERI_REG_MASK(RTC_GPIO_ENABLE, 0x1); // out disable + // pulldown disable + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDO)); + pin_reg.rtc_pin.pulldown = 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); +} + +/** + * @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) +{ + // At this stage we do not consider whether to use SPI or GPIO. + // We will switch to the specific mode when setting the transfer rate. + DAP_SPI_Init(); + DAP_SPI_Disable(); +} + +/** + * @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 + DAP_SPI_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 0; +} + +/** + * @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) +{ + // Note that we only use mosi in GPIO mode + return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; +} + +/** + * @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_MOSI); +} + +/** + * @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_MOSI); +} + +/** + * @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) +{ + // Note that we only use mosi in GPIO mode + return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; +} + +/** + * @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_MOSI); + + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_SWDIO_MOSI); + + } +} + +/** + * @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) +{ + // set \ref gpio_set_direction -> OUTPUT + // GPIO.enable_w1ts |= (0x1 << PIN_SWDIO_MOSI); + // GPIO.pin[PIN_SWDIO_MOSI].driver = 0; + do {}while (0); + +} + +/** + * @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) +{ + // may be unuse. + // set \ref gpio_set_dircetion -> INPUT + // esp8266 input is always connected + // GPIO.enable_w1tc |= (0x1 << PIN_SWDIO_MOSI); + // GPIO.pin[PIN_SWDIO_MOSI].driver = 0; + GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI); +} + +// 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) ? 1 : 0; +} + +/** + * @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 READ_PERI_REG(RTC_GPIO_IN_DATA) & 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 0; // not available +} + +/** + * @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) +{ + // Vendor reset sequence + ; // not available +} + +// 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) ? 1 : 0; +} + +/** + * @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) +{ + // Vendor reset sequence + //// FIXME: unavailable + 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 23-bit countdown timer + return (0x7FFFFF - (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) +{ + // Connecting non-SWD pins to GPIO + GPIO_FUNCTION_SET(PIN_TDO); + GPIO_FUNCTION_SET(PIN_TDI); + GPIO_FUNCTION_SET(PIN_nTRST); + GPIO_FUNCTION_SET(PIN_nRESET); + GPIO_FUNCTION_SET(PIN_LED_CONNECTED); + GPIO_FUNCTION_SET(PIN_LED_RUNNING); + + + // Configure: LED as output (turned off) + + GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_CONNECTED); + GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_RUNNING); + + LED_CONNECTED_OUT(0); + LED_RUNNING_OUT(0); + + PORT_OFF(); +} + +/** 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 index 65e0459..e7260d3 100644 --- a/components/DAP/include/DAP.h +++ b/components/DAP/include/DAP.h @@ -233,6 +233,14 @@ extern DAP_Data_t DAP_Data; // DAP Data extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag +enum transfer_type { + kTransfer_GPIO_normal, + kTransfer_GPIO_fast, + kTransfer_SPI +}; + +extern uint8_t SWD_TransferSpeed; + #ifdef __cplusplus extern "C" { diff --git a/components/DAP/include/gpio_op.h b/components/DAP/include/gpio_op.h new file mode 100644 index 0000000..30b214d --- /dev/null +++ b/components/DAP/include/gpio_op.h @@ -0,0 +1,46 @@ +#ifndef __GPIO_OP_H__ +#define __GPIO_OP_H__ + +#include "cmsis_compiler.h" +#include "gpio.h" +#include "gpio_struct.h" +#include "timer_struct.h" +#include "esp8266/pin_mux_register.h" + + +__STATIC_INLINE void GPIO_FUNCTION_SET(int io_num) +{ + gpio_pin_reg_t pin_reg; + + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(io_num)); + + // It should be noted that GPIO0, 2, 4, and 5 need to set the func register to 0, + // and the other GPIO needs to be set to 3 so that IO can be GPIO function. + if ((0x1 << io_num) & (GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5)) { + pin_reg.rtc_pin.func_low_bit = 0; + pin_reg.rtc_pin.func_high_bit = 0; + } else { + pin_reg.func_low_bit = 3; + pin_reg.func_high_bit = 0; + } + + WRITE_PERI_REG(GPIO_PIN_REG(io_num), pin_reg.val); +} + + +static void GPIO_SET_DIRECTION_NORMAL_OUT(int io_num) +{ + GPIO.enable_w1ts |= (0x1 << io_num); + // PP out + GPIO.pin[io_num].driver = 0; +} + + +// static void GPIO_SET_DIRECTION_NORMAL_IN(int io_num) +// { +// GPIO.enable_w1tc |= (0x1 << io_num); +// } + + + +#endif \ No newline at end of file diff --git a/components/DAP/include/spi_op.h b/components/DAP/include/spi_op.h index abfe12d..85ae927 100644 --- a/components/DAP/include/spi_op.h +++ b/components/DAP/include/spi_op.h @@ -5,6 +5,7 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf); +void DAP_SPI_ReadBits(const uint8_t count, uint8_t *buf); void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *ack, uint8_t TrnAfterACK); void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity); diff --git a/components/DAP/source/DAP.c b/components/DAP/source/DAP.c index 03f048c..973f0fb 100644 --- a/components/DAP/source/DAP.c +++ b/components/DAP/source/DAP.c @@ -29,6 +29,8 @@ #include "DAP_config.h" #include "DAP.h" +#include "spi_switch.h" + #if (DAP_PACKET_SIZE < 64U) #error "Minimum Packet Size is 64!" @@ -109,7 +111,7 @@ static uint8_t DAP_Info(uint8_t id, uint8_t *info) { length = 1U; break; case DAP_ID_TIMESTAMP_CLOCK: -#if (TIMESTAMP_CLOCK != 0U) +#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); @@ -207,7 +209,7 @@ static uint32_t DAP_Connect(const uint8_t *request, uint8_t *response) { } else { port = *request; } - + switch (port) { #if (DAP_SWD != 0) case DAP_PORT_SWD: @@ -266,9 +268,9 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) { uint32_t select; uint32_t wait; uint32_t timestamp; - + value = (uint32_t) *(request+0); - select = (uint32_t) *(request+1); + select = (uint32_t) *(request+1); wait = (uint32_t)(*(request+2) << 0) | (uint32_t)(*(request+3) << 8) | (uint32_t)(*(request+4) << 16) | @@ -300,7 +302,7 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) { if (wait != 0U) { #if (TIMESTAMP_CLOCK != 0U) - if (wait > 3000000U) { + if (wait > 3000000U) { wait = 3000000U; } #if (TIMESTAMP_CLOCK >= 1000000U) @@ -357,6 +359,7 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) { return ((6U << 16) | 1U); } +extern uint8_t SWD_TransferSpeed; // Process SWJ Clock command and prepare response // request: pointer to request data @@ -377,18 +380,30 @@ 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)) { + // Note that the maximum IO frequency of esp8266 is less than 2MHz + + // clock >= 10MHz -> use 40MHz SPI + if (clock >= 10000000) { + DAP_SPI_Init(); DAP_Data.fast_clock = 1U; DAP_Data.clock_delay = 1U; + SWD_TransferSpeed = kTransfer_SPI; + } else if (clock >= 2000000) { + // clock >= 2MHz -> Use GPIO with no program delay + DAP_SPI_Deinit(); + DAP_Data.fast_clock = 1U; + DAP_Data.clock_delay = 1U; + SWD_TransferSpeed = kTransfer_GPIO_fast; } else { + // clock < 2MHz -> Use GPIO with delay + DAP_SPI_Deinit(); DAP_Data.fast_clock = 0U; + SWD_TransferSpeed = kTransfer_GPIO_normal; - delay = ((CPU_CLOCK/2U) + (clock - 1U)) / clock; + #define CPU_CLOCK_FIXED 80000000 + + delay = ((CPU_CLOCK_FIXED/2U) + (clock - 1U)) / clock; if (delay > IO_PORT_WRITE_CYCLES) { delay -= IO_PORT_WRITE_CYCLES; delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES; @@ -417,7 +432,7 @@ static uint32_t DAP_SWJ_Sequence(const uint8_t *request, uint8_t *response) { uint32_t count; count = *request++; - if (count == 0U) { + if (count == 0U) { count = 256U; } @@ -446,7 +461,7 @@ static uint32_t DAP_SWD_Configure(const uint8_t *request, uint8_t *response) { 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; @@ -480,7 +495,7 @@ static uint32_t DAP_SWD_Sequence(const uint8_t *request, uint8_t *response) { while (sequence_count--) { sequence_info = *request++; count = sequence_info & SWD_SEQUENCE_CLK; - if (count == 0U) { + if (count == 0U) { count = 64U; } count = (count + 7U) / 8U; @@ -630,7 +645,7 @@ static uint32_t DAP_JTAG_IDCode(const uint8_t *request, uint8_t *response) { id_error: #endif *response = DAP_ERROR; - return ((1U << 16) | 1U); + return ((1U << 16) | 1U); } @@ -644,11 +659,11 @@ 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) | + DAP_Data.transfer.match_retry = (uint16_t) *(request+3) | (uint16_t)(*(request+4) << 8); *response = DAP_OK; - return ((5U << 16) | 1U); + return ((5U << 16) | 1U); } @@ -711,7 +726,7 @@ static uint32_t DAP_SWD_Transfer(const uint8_t *request, uint8_t *response) { } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); post_read = 0U; } - if (response_value != DAP_TRANSFER_OK) { + if (response_value != DAP_TRANSFER_OK) { break; } // Store previous AP data @@ -1386,14 +1401,14 @@ static uint32_t DAP_JTAG_TransferBlock(const uint8_t *request, uint8_t *response // Device index (JTAP TAP) DAP_Data.jtag_dev.index = *request++; - if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { goto end; } - request_count = (uint32_t)(*(request+0) << 0) | + request_count = (uint32_t)(*(request+0) << 0) | (uint32_t)(*(request+1) << 8); request += 2; - if (request_count == 0U) { + if (request_count == 0U) { goto end; } @@ -1549,7 +1564,7 @@ static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) { DAP_Data.jtag_dev.index = *request; if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { *response = DAP_ERROR; - return (1U); + return (1U); } // Select JTAG chain @@ -1565,7 +1580,7 @@ static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) { JTAG_WriteAbort(data); *response = DAP_OK; - return (1U); + return (1U); } #endif @@ -1741,7 +1756,7 @@ uint32_t DAP_ExecuteCommand(const uint8_t *request, uint8_t *response) { n = DAP_ProcessCommand(request, response); num += n; request += (uint16_t)(n >> 16); - response += (uint16_t) n; + response += (uint16_t) n; } return (num); } diff --git a/components/DAP/source/SW_DP.c b/components/DAP/source/SW_DP.c index 600809d..9a2088f 100644 --- a/components/DAP/source/SW_DP.c +++ b/components/DAP/source/SW_DP.c @@ -1,326 +1,528 @@ -/* - * 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" - -#include "spi_op.h" -#include "spi_switch.h" -#include "dap_utility.h" - -// Debug -#define PRINT_SWD_PROTOCOL 0 - -// 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) -#define PIN_DELAY() PIN_DELAY_FAST() - - -// 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) { - if (count != 8 && count != 16 && count!= 51) - { - printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count); - return; - } - DAP_SPI_Enable(); - DAP_SPI_WriteBits(count, data); -} -#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] - -//// TODO: low speed -#define SWD_TransferFunction(speed) /* Speed may be useless, because all use this function */ \ -static uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \ - SWD_Transfer_Common(request,data); \ - return 1; \ -} - -static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { - uint8_t ack; - // uint32_t bit; - uint32_t val; - uint8_t parity; - uint8_t computedParity; - - uint32_t n; - - int retryCount = 0; - const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */ - uint8_t requestByte; /* LSB */ - - - DAP_SPI_Enable(); - do { - requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U); - /* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */ - - #if (PRINT_SWD_PROTOCOL == 1) - switch (requestByte) - { - case 0xA5U: - printf("IDCODE\r\n"); - break; - case 0xA9U: - printf("W CTRL/STAT\r\n"); - break; - case 0xBDU: - printf("RDBUFF\r\n"); - break; - case 0x8DU: - printf("R CTRL/STAT\r\n"); - break; - case 0x81U: - printf("W ABORT\r\n"); - break; - case 0xB1U: - printf("W SELECT\r\n"); - break; - case 0xBBU: - printf("W APc\r\n"); - break; - case 0x9FU: - printf("R APc\r\n"); - break; - case 0x8BU: - printf("W AP4\r\n"); - break; - case 0xA3U: - printf("W AP0\r\n"); - break; - case 0X87U: - printf("R AP0\r\n"); - break; - case 0xB7U: - printf("R AP8\r\n"); - break; - default: - //W AP8 - printf("Unknown:%08x\r\n", requestByte); - break; - } - #endif - - - - if (request & DAP_TRANSFER_RnW) { - /* Read data */ - - DAP_SPI_Send_Header(requestByte, &ack, 0); // 0 Trn After ACK - if (ack == DAP_TRANSFER_OK) { - DAP_SPI_Read_Data(&val, &parity); - computedParity = ParityEvenUint32(val); - - if ((computedParity ^ parity) & 1U) { - ack = DAP_TRANSFER_ERROR; - } - if (data) { *data = val; } - - /* Capture Timestamp */ - if (request & DAP_TRANSFER_TIMESTAMP) { - DAP_Data.timestamp = TIMESTAMP_GET(); - } - - } - else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { - DAP_SPI_Generate_Cycle(1); - #if (PRINT_SWD_PROTOCOL == 1) - printf("WAIT\r\n"); - #endif - - continue; - // return DAP_TRANSFER_WAIT; - } - else { - /* Protocol error */ - DAP_SPI_Disable(); - PIN_SWDIO_TMS_SET(); - - DAP_SPI_Enable(); - DAP_SPI_Protocol_Error_Read(); - - DAP_SPI_Disable(); - PIN_SWDIO_TMS_SET(); - printf("Protocol Error: Read\r\n"); - } - - return ((uint8_t)ack); - } - else { - /* Write data */ - parity = ParityEvenUint32(*data); - DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK - if (ack == DAP_TRANSFER_OK) { - DAP_SPI_Write_Data(*data, parity); - /* Capture Timestamp */ - if (request & DAP_TRANSFER_TIMESTAMP) { - DAP_Data.timestamp = TIMESTAMP_GET(); - } - /* Idle cycles */ - n = DAP_Data.transfer.idle_cycles; - if (n) { DAP_SPI_Generate_Cycle(n); } - - DAP_SPI_Disable(); - PIN_SWDIO_TMS_SET(); - - return ((uint8_t)ack); - } - else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { - /* already turnaround. */ - - /* TODO: overrun transfer -> for read */ - #if (PRINT_SWD_PROTOCOL == 1) - printf("WAIT\r\n"); - #endif - - continue; - - } - else { - //// FIXME: bug - /* Protocol error */ - DAP_SPI_Disable(); - PIN_SWDIO_TMS_SET(); - - DAP_SPI_Enable(); - DAP_SPI_Protocol_Error_Write(); - - DAP_SPI_Disable(); - PIN_SWDIO_TMS_SET(); - printf("Protocol Error: Write\r\n"); - } - - return ((uint8_t)ack); - - } - } while (retryCount++ < 99); - - return DAP_TRANSFER_ERROR; - - -} - - -#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) */ +/* + * 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 + * + *---------------------------------------------------------------------------*/ + +/** + * @file SW_DP.c + * @author windowsair + * @brief Adaptation of GPIO and SPI + * @change: + * 2021-2-10 Support GPIO and SPI for SWD sequence / SWJ sequence / SWD transfer + * Note: SWD sequence not yet tested + * @version 0.1 + * @date 2021-2-10 + * + * @copyright Copyright (c) 2021 + * + */ + + +#include "DAP_config.h" +#include "DAP.h" + +#include "spi_op.h" +#include "spi_switch.h" +#include "dap_utility.h" + +// Debug +#define PRINT_SWD_PROTOCOL 0 + +// SW Macros + +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) + +#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET +#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR + +// Space for time in the original version, +// and time for space in our implementation + +#define SW_CLOCK_CYCLE() \ + PIN_SWCLK_CLR(); \ + if (need_delay) { PIN_DELAY(); } \ + PIN_SWCLK_SET(); \ + if (need_delay) { PIN_DELAY(); } + +#define SW_WRITE_BIT(bit) \ + PIN_SWDIO_OUT(bit); \ + PIN_SWCLK_CLR(); \ + if (need_delay) { PIN_DELAY(); } \ + PIN_SWCLK_SET(); \ + if (need_delay) { PIN_DELAY(); } + +#define SW_READ_BIT(bit) \ + PIN_SWCLK_CLR(); \ + if (need_delay) { PIN_DELAY(); } \ + bit = PIN_SWDIO_IN(); \ + PIN_SWCLK_SET(); \ + if (need_delay) { PIN_DELAY(); } + + + +uint8_t SWD_TransferSpeed = kTransfer_GPIO_normal; + + +void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay); +void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data); + +void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi); +void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi); + + +// 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) { + // if (count != 8 && count != 16 && count!= 51) + // { + // printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count); + // return; + // } + + if(SWD_TransferSpeed == kTransfer_SPI) { + SWJ_Sequence_SPI(count, data); + } else { + SWJ_Sequence_GPIO(count, data, 1); + } + +} + + +void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay) { + 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--; + } +} + +void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data) { + DAP_SPI_Enable(); + DAP_SPI_WriteBits(count, data); +} +#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) { + if (SWD_TransferSpeed == kTransfer_SPI) { + SWD_Sequence_SPI(info, swdo, swdi); + } else { + SWD_Sequence_GPIO(info, swdo, swdi); + } +} + +void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { + const uint8_t need_delay = 1; + + uint32_t val; + uint32_t bit; + uint32_t n, k; + + n = info & SWD_SEQUENCE_CLK; + if (n == 0U) { + n = 64U; + } + // n = 1 ~ 64 + + // LSB + 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; + } + } + } +} + +void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { + uint32_t n; + n = info & SWD_SEQUENCE_CLK; + if (n == 0U) { + n = 64U; + } + // n = 1 ~ 64 + + if (info & SWD_SEQUENCE_DIN) { + DAP_SPI_ReadBits(n, swdi); + } else { + DAP_SPI_WriteBits(n, swdo); + } +} + +#endif + + +#if (DAP_SWD != 0) + + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) { + // SPI transfer mode does not require operations such as PIN_DELAY + uint8_t ack; + // uint32_t bit; + uint32_t val; + uint8_t parity; + uint8_t computedParity; + + uint32_t n; + + const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */ + uint8_t requestByte; /* LSB */ + + + DAP_SPI_Enable(); + + requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U); + /* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */ + + #if (PRINT_SWD_PROTOCOL == 1) + switch (requestByte) + { + case 0xA5U: + printf("IDCODE\r\n"); + break; + case 0xA9U: + printf("W CTRL/STAT\r\n"); + break; + case 0xBDU: + printf("RDBUFF\r\n"); + break; + case 0x8DU: + printf("R CTRL/STAT\r\n"); + break; + case 0x81U: + printf("W ABORT\r\n"); + break; + case 0xB1U: + printf("W SELECT\r\n"); + break; + case 0xBBU: + printf("W APc\r\n"); + break; + case 0x9FU: + printf("R APc\r\n"); + break; + case 0x8BU: + printf("W AP4\r\n"); + break; + case 0xA3U: + printf("W AP0\r\n"); + break; + case 0X87U: + printf("R AP0\r\n"); + break; + case 0xB7U: + printf("R AP8\r\n"); + break; + default: + //W AP8 + printf("Unknown:%08x\r\n", requestByte); + break; + } + #endif + + if (request & DAP_TRANSFER_RnW) { + /* Read data */ + + DAP_SPI_Send_Header(requestByte, &ack, 0); // 0 Trn After ACK + if (ack == DAP_TRANSFER_OK) { + DAP_SPI_Read_Data(&val, &parity); + computedParity = ParityEvenUint32(val); + + if ((computedParity ^ parity) & 1U) { + ack = DAP_TRANSFER_ERROR; + } + if (data) { *data = val; } + + /* Capture Timestamp */ + if (request & DAP_TRANSFER_TIMESTAMP) { + DAP_Data.timestamp = TIMESTAMP_GET(); + } + + } + else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { + DAP_SPI_Generate_Cycle(1); + #if (PRINT_SWD_PROTOCOL == 1) + printf("WAIT\r\n"); + #endif + + // return DAP_TRANSFER_WAIT; + } + else { + /* Protocol error */ + DAP_SPI_Disable(); + PIN_SWDIO_TMS_SET(); + + DAP_SPI_Enable(); + DAP_SPI_Protocol_Error_Read(); + + DAP_SPI_Disable(); + PIN_SWDIO_TMS_SET(); + #if (PRINT_SWD_PROTOCOL == 1) + printf("Protocol Error: Read\r\n"); + #endif + } + + return ((uint8_t)ack); + } + else { + /* Write data */ + parity = ParityEvenUint32(*data); + DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK + if (ack == DAP_TRANSFER_OK) { + DAP_SPI_Write_Data(*data, parity); + /* Capture Timestamp */ + if (request & DAP_TRANSFER_TIMESTAMP) { + DAP_Data.timestamp = TIMESTAMP_GET(); + } + /* Idle cycles */ + n = DAP_Data.transfer.idle_cycles; + if (n) { DAP_SPI_Generate_Cycle(n); } + + DAP_SPI_Disable(); + PIN_SWDIO_TMS_SET(); + + return ((uint8_t)ack); + } + else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { + /* already turnaround. */ + + /* TODO: overrun transfer -> for read */ + #if (PRINT_SWD_PROTOCOL == 1) + printf("WAIT\r\n"); + #endif + + } + else { + //// FIXME: bug + /* Protocol error */ + DAP_SPI_Disable(); + PIN_SWDIO_TMS_SET(); + + DAP_SPI_Enable(); + DAP_SPI_Protocol_Error_Write(); + + DAP_SPI_Disable(); + PIN_SWDIO_TMS_SET(); + + #if (PRINT_SWD_PROTOCOL == 1) + printf("Protocol Error: Write\r\n"); + #endif + } + + return ((uint8_t)ack); + + } + + return DAP_TRANSFER_ERROR; +} + + + +static uint8_t SWD_Transfer_GPIO (uint32_t request, uint32_t *data, uint8_t need_delay) { + 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); +} + + +// 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) { + switch (SWD_TransferSpeed) { + case kTransfer_SPI: + return SWD_Transfer_SPI(request, data); + case kTransfer_GPIO_fast: + return SWD_Transfer_GPIO(request, data, 0); + case kTransfer_GPIO_normal: + return SWD_Transfer_GPIO(request, data, 1); + default: + return SWD_Transfer_GPIO(request, data, 1); + } +} + + +#endif /* (DAP_SWD != 0) */ diff --git a/components/DAP/source/spi_op.c b/components/DAP/source/spi_op.c index 8deefaf..728c837 100644 --- a/components/DAP/source/spi_op.c +++ b/components/DAP/source/spi_op.c @@ -1,3 +1,15 @@ +/** + * @file spi_op.c + * @author windowsair + * @brief Using SPI for common transfer operations + * @change: 2020-11-25 first version + * 2021-2-11 Support SWD sequence + * @version 0.2 + * @date 2021-2-11 + * + * @copyright Copyright (c) 2021 + * + */ #include #include "esp8266/spi_struct.h" @@ -6,12 +18,23 @@ #define DAP_SPI SPI1 +/** + * @brief Calculate integer division and round up + * + * @param A + * @param B + * @return result + */ +__STATIC_FORCEINLINE int div_round_up(int A, int B) +{ + return (A + B - 1) / B; +} /** * @brief Write bits. LSB & little-endian * Note: No check. The pointer must be valid. - * @param count Number of bits to be written + * @param count Number of bits to be written (<= 64 bits, no length check) * @param buf Data Buf */ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf) @@ -26,22 +49,35 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf) switch (count) { case 8: - DAP_SPI.data_buf[0] = (buf[0] << 0) | (0U << 8) | (0U << 16) | (0U << 24); + DAP_SPI.data_buf[0] = (buf[0] << 0) | (0U << 8) | (0U << 16) | (0U << 24); break; case 16: - DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (0x000U << 16) | (0x000U << 24); + DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (0x000U << 16) | (0x000U << 24); break; case 33: // 32bits data & 1 bit parity - DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); - DAP_SPI.data_buf[1] = (buf[4] << 0) | (0x000U << 8) | (0x000U << 16) | (0x000U << 24); + DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); + DAP_SPI.data_buf[1] = (buf[4] << 0) | (0x000U << 8) | (0x000U << 16) | (0x000U << 24); break; case 51: // for line reset - DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); - DAP_SPI.data_buf[1] = (buf[4] << 0) | (buf[5] << 8) | (buf[2] << 16) | (0x000U << 24); + DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); + DAP_SPI.data_buf[1] = (buf[4] << 0) | (buf[5] << 8) | (buf[2] << 16) | (0x000U << 24); break; default: - printf("[ERROR] Using unaligned data!\r\n"); - break; + { + uint32_t data_buf[2]; + uint8_t *pData = (uint8_t *)data_buf; + int i; + + for (i = 0; i < div_round_up(count, 8); i++) + { + pData[i] = buf[i]; + } + // last byte use mask: + pData[i-1] = pData[i-1] & ((2U >> (count % 8)) - 1U); + + DAP_SPI.data_buf[0] = data_buf[0]; + DAP_SPI.data_buf[1] = data_buf[1]; + } } // Start transmission @@ -51,9 +87,44 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf) } + /** - * @brief Step1: Packet Request - * + * @brief Read bits. LSB & little-endian + * Note: No check. The pointer must be valid. + * @param count Number of bits to be read (<= 64 bits, no length check) + * @param buf Data Buf + */ +void DAP_SPI_ReadBits(const uint8_t count, uint8_t *buf) { + int i; + uint32_t data_buf[2]; + + uint8_t * pData = (uint8_t *)data_buf; + + DAP_SPI.user.usr_mosi = 0; + DAP_SPI.user.usr_miso = 1; + + DAP_SPI.user1.usr_miso_bitlen = count - 1U; + + // Start transmission + DAP_SPI.cmd.usr = 1; + // Wait for reading to complete + while (DAP_SPI.cmd.usr); + + data_buf[0] = DAP_SPI.data_buf[0]; + data_buf[1] = DAP_SPI.data_buf[1]; + + for (i = 0; i < div_round_up(count, 8); i++) + { + buf[i] = pData[i]; + } + // last byte use mask: + buf[i-1] = buf[i-1] & ((2 >> (count % 8)) - 1); +} + + +/** + * @brief Step1: Packet Request + * * @param packetHeaderData data from host * @param ack ack from target * @param TrnAfterACK num of trn after ack @@ -70,9 +141,9 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t * // 1 bit Trn(Before ACK) + 3bits ACK + TrnAferACK - 1(prescribed) DAP_SPI.user1.usr_miso_bitlen = 1U + 3U + TrnAfterACK - 1U; - + // copy data to reg - DAP_SPI.data_buf[0] = (packetHeaderData << 0) | (0U << 8) | (0U << 16) | (0U << 24); + DAP_SPI.data_buf[0] = (packetHeaderData << 0) | (0U << 8) | (0U << 16) | (0U << 24); // Start transmission DAP_SPI.cmd.usr = 1; @@ -86,21 +157,20 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t * /** * @brief Step2: Read Data - * + * * @param resData data from target * @param resParity parity from target */ -__FORCEINLINE void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity) +__FORCEINLINE void DAP_SPI_Read_Data(uint32_t *resData, uint8_t *resParity) { uint64_t dataBuf; uint32_t *pU32Data = (uint32_t *)&dataBuf; - DAP_SPI.user.usr_mosi = 0; DAP_SPI.user.usr_miso = 1; // 1 bit Trn(End) + 3bits ACK + 32bis data + 1bit parity - 1(prescribed) - DAP_SPI.user1.usr_miso_bitlen = 1U +32U + 1U - 1U; + DAP_SPI.user1.usr_miso_bitlen = 1U + 32U + 1U - 1U; // Start transmission DAP_SPI.cmd.usr = 1; @@ -110,13 +180,13 @@ __FORCEINLINE void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity) pU32Data[0] = DAP_SPI.data_buf[0]; pU32Data[1] = DAP_SPI.data_buf[1]; - *resData = (dataBuf >> 0U) & 0xFFFFFFFFU ; // 32bits Response Data + *resData = (dataBuf >> 0U) & 0xFFFFFFFFU; // 32bits Response Data *resParity = (dataBuf >> (0U + 32U)) & 1U; // 3bits ACK + 32bis data } /** * @brief Step2: Write Data - * + * * @param data data from host * @param parity parity from host */ @@ -126,7 +196,7 @@ __FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity) DAP_SPI.user.usr_miso = 0; DAP_SPI.user1.usr_mosi_bitlen = 32U + 1U - 1U; // 32bis data + 1bit parity - 1(prescribed) - + // copy data to reg DAP_SPI.data_buf[0] = data; DAP_SPI.data_buf[1] = parity; @@ -139,11 +209,12 @@ __FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity) /** * @brief Generate Clock Cycle - * + * * @param num Cycle Num */ __FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num) { + //// TODO: It may take long time to generate just one clock DAP_SPI.user.usr_mosi = 1; DAP_SPI.user.usr_miso = 0; DAP_SPI.user1.usr_mosi_bitlen = num - 1U; @@ -157,7 +228,7 @@ __FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num) /** * @brief Generate Protocol Error Cycle - * + * */ __FORCEINLINE void DAP_SPI_Protocol_Error_Read() { @@ -167,7 +238,7 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Read() DAP_SPI.data_buf[0] = 0xFFFFFFFFU; DAP_SPI.data_buf[1] = 0xFFFFFFFFU; - + DAP_SPI.cmd.usr = 1; while (DAP_SPI.cmd.usr); } @@ -175,7 +246,7 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Read() /** * @brief Generate Protocol Error Cycle - * + * */ __FORCEINLINE void DAP_SPI_Protocol_Error_Write() { @@ -185,7 +256,7 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Write() DAP_SPI.data_buf[0] = 0xFFFFFFFFU; DAP_SPI.data_buf[1] = 0xFFFFFFFFU; - + DAP_SPI.cmd.usr = 1; while (DAP_SPI.cmd.usr); } diff --git a/components/DAP/source/spi_switch.c b/components/DAP/source/spi_switch.c index 855ecc4..09a7236 100644 --- a/components/DAP/source/spi_switch.c +++ b/components/DAP/source/spi_switch.c @@ -2,11 +2,13 @@ * @file spi_switch.c * @author windowsair * @brief Switching between SPI mode and IO mode - * @version 0.1 - * @date 2020-11-25 - * - * @copyright Copyright (c) 2020 - * + * @change: 2020-11-25 first version + * 2021-2-11 Transmission mode switching test passed + * @version 0.2 + * @date 2021-2-11 + * + * @copyright Copyright (c) 2021 + * */ #include @@ -31,7 +33,7 @@ typedef enum { /** * @brief Initialize on first use - * + * */ void DAP_SPI_Init() { @@ -59,7 +61,7 @@ void DAP_SPI_Init() DAP_SPI.ctrl2.mosi_delay_num = 0; DAP_SPI.ctrl2.miso_delay_num = 0; - // DIO & QIO SPI disable + // DIO & QIO SPI disable DAP_SPI.user.fwrite_dual = false; DAP_SPI.user.fwrite_quad = false; DAP_SPI.user.fwrite_dio = false; @@ -69,14 +71,14 @@ void DAP_SPI_Init() DAP_SPI.ctrl.fread_dio = false; DAP_SPI.ctrl.fread_qio = false; DAP_SPI.ctrl.fastrd_mode = true; - + // Enable soft reset DAP_SPI.slave.sync_reset = true; // Set the clock polarity and phase CPOL = CPHA = 0 DAP_SPI.pin.ck_idle_edge = 1; // HIGH while idle DAP_SPI.user.ck_out_edge = 0; - + // Set data bit order DAP_SPI.ctrl.wr_bit_order = 1; // SWD -> LSB @@ -88,7 +90,7 @@ void DAP_SPI_Init() // Set dummy DAP_SPI.user.usr_dummy = 0; - // Initialize HSPI IO + // Initialize HSPI IO gpio_pin_reg_t pin_reg; PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_HSPI_CLK); // GPIO14 is SPI CLK pin (Clock) @@ -96,10 +98,10 @@ void DAP_SPI_Init() pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(14)); pin_reg.pullup = 1; WRITE_PERI_REG(GPIO_PIN_REG(14), pin_reg.val); - + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out) GPIO.enable_w1ts |= (0x1 << 13); - GPIO.pin[13].driver = 0; // PP Output or OD output + GPIO.pin[13].driver = 0; // PP Output or OD output pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13)); pin_reg.pullup = 0; WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val); @@ -110,6 +112,8 @@ void DAP_SPI_Init() pin_reg.pullup = 0; WRITE_PERI_REG(GPIO_PIN_REG(12), pin_reg.val); + + // Set spi clk div CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK); @@ -124,35 +128,53 @@ void DAP_SPI_Init() DAP_SPI.user.usr_addr = 0; } +/** + * @brief Switch to GPIO + * Note: You may be able to pull the pin high in SPI mode, though you cannot set it to LOW + */ +__FORCEINLINE void DAP_SPI_Deinit() +{ + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); // MOSI + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); // MISO + + // disable MISO output connect + GPIO.enable_w1tc |= (0x1 << 12); + + gpio_pin_reg_t pin_reg; + GPIO.enable_w1ts |= (0x1 << 13); + GPIO.pin[13].driver = 1; // OD output + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val); +} + + /** * @brief Use SPI acclerate - * + * */ void DAP_SPI_Enable() { + // may be unuse PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out) } /** * @brief Disable SPI - * + * Drive capability not yet known */ __FORCEINLINE void DAP_SPI_Disable() { - DAP_SPI_Deinit(); + ; + //CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_MTCK_U, (PERIPHS_IO_MUX_FUNC << PERIPHS_IO_MUX_FUNC_S)); + // may be unuse + // gpio_pin_reg_t pin_reg; + // GPIO.enable_w1ts |= (0x1 << 13); + // GPIO.pin[13].driver = 0; // OD Output + // pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13)); + // pin_reg.pullup = 1; + // WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val); } -__FORCEINLINE void DAP_SPI_Deinit() -{ - - CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_MTCK_U, (PERIPHS_IO_MUX_FUNC << PERIPHS_IO_MUX_FUNC_S)); - - // may be unuse - gpio_pin_reg_t pin_reg; - GPIO.enable_w1ts |= (0x1 << 13); - GPIO.pin[13].driver = 0; // OD Output - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13)); - pin_reg.pullup = 1; - WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val); -} \ No newline at end of file