Merge branch 'release/v0.1.2'
This commit is contained in:
		
						commit
						e396d11d0f
					
				
							
								
								
									
										108
									
								
								README.md
								
								
								
								
							
							
						
						
									
										108
									
								
								README.md
								
								
								
								
							|  | @ -1,10 +1,12 @@ | |||
| <p align="center"><img src="https://user-images.githubusercontent.com/17078589/73821108-300bda00-482e-11ea-89f6-011a50037a12.png"/></p> | ||||
| <h1 align="center">Wireless ESP8266 DAP</h1> | ||||
| <p align="center"><img src="https://user-images.githubusercontent.com/17078589/107881245-7d7d5580-6f1e-11eb-9f66-6ac589e5f95c.png"/></p> | ||||
| 
 | ||||
| [](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Amaster) master | ||||
|  | ||||
| 
 | ||||
| 
 | ||||
| [](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Amaster) master  | ||||
| [](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Adevelop) develop | ||||
| 
 | ||||
| [](https://github.com/windowsair/wireless-esp8266-dap/LICENSE) [](https://github.com/windowsair/wireless-esp8266-dap/pulls) [](https://github.com/windowsair/wireless-esp8266-dap) | ||||
| [](https://github.com/windowsair/wireless-esp8266-dap/LICENSE) [](https://github.com/windowsair/wireless-esp8266-dap/pulls) [](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: | ||||
| 
 | ||||
| <p align="center"><img src="https://user-images.githubusercontent.com/17078589/73829782-808b3380-483e-11ea-8389-1570bc4200af.gif"/></p> | ||||
| <p align="center"><img src="https://user-images.githubusercontent.com/17078589/107896674-e5a95700-6f71-11eb-90f7-bf7362045537.gif"/></p> | ||||
| 
 | ||||
| ## 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 | ||||
|  | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
|  | @ -118,8 +135,7 @@ 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 | ||||
| - 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 <your-esp8266-ip-address>  1-1 | ||||
| 
 | ||||
| # 👉 Recommend | ||||
| # HID Mode Or WinUSB Mode | ||||
| # for usbip-win 0.3.0 kmdf ude | ||||
| .\usbip.exe attach_ude -r <your-esp8266-ip-address> -b 1-1 | ||||
|  | @ -139,31 +156,38 @@ python ./idf.py -p /dev/ttyS5 flash | |||
| 
 | ||||
| If all goes well, you should see your device connected. | ||||
| 
 | ||||
|  | ||||
|  | ||||
| 
 | ||||
| 
 | ||||
| Then test it under MDK: | ||||
| Here, we use MDK for testing: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| 
 | ||||
| ------ | ||||
| 
 | ||||
| 
 | ||||
| ## 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) | ||||
|  | @ -25,6 +25,19 @@ | |||
|  * | ||||
|  *---------------------------------------------------------------------------*/ | ||||
| 
 | ||||
| /**
 | ||||
|  * @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__ | ||||
| 
 | ||||
|  | @ -36,6 +49,7 @@ | |||
| #include "timer_struct.h" | ||||
| #include "esp8266/pin_mux_register.h" | ||||
| 
 | ||||
| #include "gpio_op.h" | ||||
| #include "spi_switch.h" | ||||
| #include "dap_configuration.h" | ||||
| //**************************************************************************************************
 | ||||
|  | @ -65,8 +79,8 @@ 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 16000000 ///< Specifies the max Debug Clock in Hz.
 | ||||
| 
 | ||||
| //#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
 | ||||
|  | @ -181,14 +195,14 @@ __STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) | |||
| 
 | ||||
| ///@}
 | ||||
| 
 | ||||
| // Modify your pins here
 | ||||
| 
 | ||||
| // ATTENTION: DO NOT USE RTC GPIO16
 | ||||
| #define PIN_SWDIO 12 | ||||
| // 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 4 | ||||
| #define PIN_TDI 0 | ||||
| #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
 | ||||
|  | @ -242,25 +256,23 @@ __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; | ||||
|   // 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.pullup = 0; | ||||
|   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; | ||||
|  | @ -280,6 +292,7 @@ __STATIC_INLINE void PORT_JTAG_SETUP(void) | |||
|   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); | ||||
|  | @ -294,56 +307,10 @@ __STATIC_INLINE void PORT_JTAG_SETUP(void) | |||
|  */ | ||||
| __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);
 | ||||
| 
 | ||||
|   // 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(); | ||||
|   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); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -355,38 +322,7 @@ __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_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 -------------------------------------
 | ||||
|  | @ -431,7 +367,8 @@ __STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) | |||
|  */ | ||||
| __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) | ||||
| { | ||||
|   return ((GPIO.in >> PIN_SWDIO) & 0x1) ? 1 : 0; | ||||
|   // Note that we only use mosi in GPIO mode
 | ||||
|   return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -461,7 +398,8 @@ __STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) | |||
|  */ | ||||
| __STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) | ||||
| { | ||||
|   return ((GPIO.in >> PIN_SWDIO) & 0x1) ? 1 : 0; | ||||
|   // Note that we only use mosi in GPIO mode
 | ||||
|   return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -498,8 +436,6 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) | |||
|  */ | ||||
| __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;
 | ||||
|  | @ -514,7 +450,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) | |||
|  */ | ||||
| __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) | ||||
| { | ||||
|   // Need fast response
 | ||||
|   // may be unuse.
 | ||||
|   // set \ref gpio_set_dircetion -> INPUT
 | ||||
|   // esp8266 input is always connected
 | ||||
|   // GPIO.enable_w1tc |= (0x1 << PIN_SWDIO_MOSI);
 | ||||
|  | @ -565,7 +501,7 @@ __STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) | |||
|  */ | ||||
| __STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) | ||||
| { | ||||
|   return ((GPIO.in >> PIN_TDO) & 0x1) ? 1 : 0; | ||||
|   return READ_PERI_REG(RTC_GPIO_IN_DATA) & 0x1; | ||||
| } | ||||
| 
 | ||||
| // nTRST Pin I/O -------------------------------------------
 | ||||
|  | @ -737,21 +673,21 @@ Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled an | |||
| */ | ||||
| __STATIC_INLINE void DAP_SETUP(void) | ||||
| { | ||||
|   DAP_SPI_Init(); | ||||
|   DAP_SPI_Disable(); | ||||
|   // 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); | ||||
| 
 | ||||
| 
 | ||||
|   // 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); | ||||
| 
 | ||||
|   GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_CONNECTED); | ||||
|   GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_RUNNING); | ||||
| 
 | ||||
|   LED_CONNECTED_OUT(0); | ||||
|   gpio_set_direction(PIN_LED_RUNNING, GPIO_MODE_DEF_OUTPUT); | ||||
|   LED_RUNNING_OUT(0); | ||||
| 
 | ||||
|   PORT_OFF(); | ||||
|  |  | |||
|  | @ -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" | ||||
| { | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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!" | ||||
|  | @ -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; | ||||
|   } | ||||
| 
 | ||||
|   // Note that the maximum IO frequency of esp8266 is less than 2MHz
 | ||||
| 
 | ||||
|   if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { | ||||
|   // 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; | ||||
|  |  | |||
|  | @ -25,6 +25,21 @@ | |||
|  * | ||||
|  *---------------------------------------------------------------------------*/ | ||||
| 
 | ||||
| /**
 | ||||
|  * @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" | ||||
| 
 | ||||
|  | @ -37,31 +52,44 @@ | |||
| 
 | ||||
| // 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();                      \ | ||||
|   PIN_DELAY();                          \ | ||||
|   if (need_delay) { PIN_DELAY(); }      \ | ||||
|   PIN_SWCLK_SET();                      \ | ||||
|   PIN_DELAY() | ||||
|   if (need_delay) { PIN_DELAY(); } | ||||
| 
 | ||||
| #define SW_WRITE_BIT(bit)               \ | ||||
|   PIN_SWDIO_OUT(bit);                   \ | ||||
|   PIN_SWCLK_CLR();                      \ | ||||
|   PIN_DELAY();                          \ | ||||
|   if (need_delay) { PIN_DELAY(); }      \ | ||||
|   PIN_SWCLK_SET();                      \ | ||||
|   PIN_DELAY() | ||||
|   if (need_delay) { PIN_DELAY(); } | ||||
| 
 | ||||
| #define SW_READ_BIT(bit)                \ | ||||
|   PIN_SWCLK_CLR();                      \ | ||||
|   PIN_DELAY();                          \ | ||||
|   if (need_delay) { PIN_DELAY(); }      \ | ||||
|   bit = PIN_SWDIO_IN();                 \ | ||||
|   PIN_SWCLK_SET();                      \ | ||||
|   PIN_DELAY() | ||||
|   if (need_delay) { PIN_DELAY(); } | ||||
| 
 | ||||
| //#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
 | ||||
| #define PIN_DELAY() PIN_DELAY_FAST() | ||||
| 
 | ||||
| 
 | ||||
| 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
 | ||||
|  | @ -70,11 +98,44 @@ | |||
| //   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 (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); | ||||
| } | ||||
|  | @ -88,6 +149,16 @@ void SWJ_Sequence (uint32_t count, const uint8_t *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; | ||||
|  | @ -96,7 +167,9 @@ void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { | |||
|   if (n == 0U) { | ||||
|     n = 64U; | ||||
|   } | ||||
|   // n = 1 ~ 64
 | ||||
| 
 | ||||
|   // LSB
 | ||||
|   if (info & SWD_SEQUENCE_DIN) { | ||||
|     while (n) { | ||||
|       val = 0U; | ||||
|  | @ -118,6 +191,22 @@ void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { | |||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -128,15 +217,8 @@ void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { | |||
| //   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) {          | ||||
| 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; | ||||
|  | @ -145,13 +227,12 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { | |||
| 
 | ||||
|   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 */ | ||||
| 
 | ||||
|  | @ -201,8 +282,6 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { | |||
|     } | ||||
|   #endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   if (request & DAP_TRANSFER_RnW) { | ||||
|     /* Read data */ | ||||
| 
 | ||||
|  | @ -228,7 +307,6 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { | |||
|       printf("WAIT\r\n"); | ||||
|       #endif | ||||
| 
 | ||||
|         continue; | ||||
|       // return DAP_TRANSFER_WAIT;
 | ||||
|     } | ||||
|     else { | ||||
|  | @ -241,7 +319,9 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { | |||
| 
 | ||||
|       DAP_SPI_Disable(); | ||||
|       PIN_SWDIO_TMS_SET(); | ||||
|       #if (PRINT_SWD_PROTOCOL == 1) | ||||
|       printf("Protocol Error: Read\r\n"); | ||||
|       #endif | ||||
|     } | ||||
| 
 | ||||
|     return ((uint8_t)ack); | ||||
|  | @ -273,8 +353,6 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { | |||
|       printf("WAIT\r\n"); | ||||
|       #endif | ||||
| 
 | ||||
|         continue; | ||||
| 
 | ||||
|     } | ||||
|     else { | ||||
|       //// FIXME: bug
 | ||||
|  | @ -287,27 +365,146 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { | |||
| 
 | ||||
|       DAP_SPI_Disable(); | ||||
|       PIN_SWDIO_TMS_SET(); | ||||
| 
 | ||||
|       #if (PRINT_SWD_PROTOCOL == 1) | ||||
|       printf("Protocol Error: Write\r\n"); | ||||
|       #endif | ||||
|     } | ||||
| 
 | ||||
|     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) | ||||
| 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
 | ||||
|  | @ -315,10 +512,15 @@ SWD_TransferFunction(Slow) | |||
| //   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); | ||||
|   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); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 <stdio.h> | ||||
| 
 | ||||
| #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) | ||||
|  | @ -40,8 +63,21 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf) | |||
|         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,6 +87,41 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * @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 | ||||
|  * | ||||
|  | @ -95,7 +166,6 @@ __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; | ||||
| 
 | ||||
|  | @ -144,6 +214,7 @@ __FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity) | |||
|  */ | ||||
| __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; | ||||
|  |  | |||
|  | @ -2,10 +2,12 @@ | |||
|  * @file spi_switch.c | ||||
|  * @author windowsair | ||||
|  * @brief Switching between SPI mode and IO mode | ||||
|  * @version 0.1 | ||||
|  * @date 2020-11-25 | ||||
|  * @change: 2020-11-25 first version | ||||
|  *          2021-2-11 Transmission mode switching test passed | ||||
|  * @version 0.2 | ||||
|  * @date 2021-2-11 | ||||
|  * | ||||
|  * @copyright Copyright (c) 2020 | ||||
|  * @copyright Copyright (c) 2021 | ||||
|  * | ||||
|  */ | ||||
| #include <stdbool.h> | ||||
|  | @ -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(); | ||||
| } | ||||
| 
 | ||||
| __FORCEINLINE void DAP_SPI_Deinit() | ||||
| { | ||||
| 
 | ||||
|     CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_MTCK_U, (PERIPHS_IO_MUX_FUNC << PERIPHS_IO_MUX_FUNC_S)); | ||||
| 
 | ||||
|     ; | ||||
|     //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); | ||||
|     // 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);
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue