0
0
Fork 0

feat: Enhance SPI and GPIO compatibility.

This commit is contained in:
windowsair 2021-02-15 20:46:19 +08:00
parent 3f0d196bce
commit b4691546d1
9 changed files with 1553 additions and 1212 deletions

108
README.md
View File

@ -1,10 +1,12 @@
<p align="center"><img src="https://user-images.githubusercontent.com/17078589/73821108-300bda00-482e-11ea-89f6-011a50037a12.png"/></p> <p align="center"><img src="https://user-images.githubusercontent.com/17078589/107881245-7d7d5580-6f1e-11eb-9f66-6ac589e5f95c.png"/></p>
<h1 align="center">Wireless ESP8266 DAP</h1>
[![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 [![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 ## Introduce
@ -13,19 +15,20 @@ Wireless debugging with ***only one ESP8266*** !
Realized by USBIP and CMSIS-DAP protocol stack. 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 ## Feature
1. Debug Communication Mode 1. Debug Communication Mode & Debug Port
- [x] SWD - [x] SWD(SW-DP)
- [x] JTAG - [x] JTAG(JTAG-DP)
- [x] SWJ-DP
2. USB Communication Mode 2. USB Communication Mode
- [x] USB-HID (Default) - [x] USB-HID
- [x] WCID & WinUSB (Experimental) - [x] WCID & WinUSB (Default)
3. Debug Trace 3. Debug Trace
- [ ] UART Serial Wire Output(SWO) - [ ] UART Serial Wire Output(SWO)
@ -53,8 +56,9 @@ You can change `WIFI_SSID` and ` WIFI_PASS` in [wifi_configuration.h](main/wifi_
| SWD | | | SWD | |
|----------------|--------| |----------------|--------|
| SWCLK | GPIO5 | | SWCLK | GPIO14 |
| SWDIO | GPIO4 | | SWDIO | GPIO12 |
| SWDIO_MOSI | GPIO13 |
| LED\_CONNECTED | GPIO2 | | LED\_CONNECTED | GPIO2 |
| LED\_RUNNING | GPIO15 | | LED\_RUNNING | GPIO15 |
| TVCC | 3V3 | | TVCC | 3V3 |
@ -66,30 +70,43 @@ You can change `WIFI_SSID` and ` WIFI_PASS` in [wifi_configuration.h](main/wifi_
| JTAG | | | JTAG | |
|--------------------|---------| |--------------------|---------|
| TCK | GPIO5 | | TCK | GPIO14 |
| TMS | GPIO4 | | TMS | GPIO13 |
| TDI | GPIO13 | | TDI | GPIO4 |
| TDO | GPIO12 | | TDO | GPIO16 |
| nTRST \(optional\) | GPIO0\* | | nTRST \(optional\) | GPIO0\* |
| nRESET | GPIO14 | | nRESET | GPIO5 |
| LED\_CONNECTED | GPIO2 | | LED\_CONNECTED | GPIO2 |
| LED\_RUNNING | GPIO15 | | LED\_RUNNING | GPIO15 |
| TVCC | 3V3 | | TVCC | 3V3 |
| GND | GND | | 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 ### Build with Github Action Online
See: [Build with Github Action](https://github.com/windowsair/wireless-esp8266-dap/wiki/Build-with-Github-Action) 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 1. Get ESP8266 RTOS Software Development Kit
@ -118,8 +135,7 @@ python ./idf.py -p /dev/ttyS5 flash
1. Get USBIP project 1. Get USBIP project
- Windows: [usbip-win](https://github.com/cezanne/usbip-win) . - 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 Linux kernel, but we have not yet tested on Linux platform, and the following instructions are all under Windows platform.
- Linux: Distributed as part of the kernel
2. Start esp8266 and connect it to the device to be debugged 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 # or usbip old version
.\usbip.exe -D -a <your-esp8266-ip-address> 1-1 .\usbip.exe -D -a <your-esp8266-ip-address> 1-1
# 👉 Recommend
# HID Mode Or WinUSB Mode # HID Mode Or WinUSB Mode
# for usbip-win 0.3.0 kmdf ude # for usbip-win 0.3.0 kmdf ude
.\usbip.exe attach_ude -r <your-esp8266-ip-address> -b 1-1 .\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. 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) ![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 ## Develop
0. Check other branches to know the latest development progress. 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) 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. 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 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 ## License
[MIT LICENSE](LICENSE) [MIT LICENSE](LICENSE)

View File

@ -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__ #ifndef __DAP_CONFIG_H__
#define __DAP_CONFIG_H__ #define __DAP_CONFIG_H__
@ -36,6 +49,7 @@
#include "timer_struct.h" #include "timer_struct.h"
#include "esp8266/pin_mux_register.h" #include "esp8266/pin_mux_register.h"
#include "gpio_op.h"
#include "spi_switch.h" #include "spi_switch.h"
#include "dap_configuration.h" #include "dap_configuration.h"
//************************************************************************************************** //**************************************************************************************************
@ -65,8 +79,8 @@ This information includes:
#define CPU_CLOCK 160000000 ///< Specifies the CPU Clock in Hz. #define CPU_CLOCK 160000000 ///< Specifies the CPU Clock in Hz.
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<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. /// 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 /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O
@ -181,15 +195,15 @@ __STATIC_INLINE uint8_t DAP_GetSerNumString(char *str)
///@} ///@}
// Modify your pins here
// ATTENTION: DO NOT USE RTC GPIO16 // Note: DO NOT modify these pins: PIN_SWDIO PIN_SWDIO_MOSI PIN_SWCLK
#define PIN_SWDIO 12 // Modify the following pins carefully: PIN_TDO
#define PIN_SWDIO 12 // SPI MISO
#define PIN_SWDIO_MOSI 13 // SPI MOSI #define PIN_SWDIO_MOSI 13 // SPI MOSI
#define PIN_SWCLK 14 #define PIN_SWCLK 14
#define PIN_TDO 4 #define PIN_TDO 16 // device TDO -> Host Data Input (use RTC pin 16)
#define PIN_TDI 0 #define PIN_TDI 4
#define PIN_nTRST 0 // optional #define PIN_nTRST 0 // optional
#define PIN_nRESET 5 #define PIN_nRESET 5
// LED_BUILTIN // LED_BUILTIN
#define PIN_LED_CONNECTED 2 #define PIN_LED_CONNECTED 2
@ -242,25 +256,23 @@ __STATIC_INLINE void PORT_JTAG_SETUP(void)
{ {
gpio_pin_reg_t pin_reg; 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); // set TCK, TMS pin
GPIO.enable_w1tc |= (0x1 << PIN_TDO); DAP_SPI_Deinit();
GPIO.pin[PIN_TDO].driver = 0;
// 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.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); WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDO), pin_reg.val);
// gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); // gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT);
GPIO.enable_w1ts |= (0x1 << PIN_TDI); GPIO.enable_w1ts |= (0x1 << PIN_TDI);
GPIO.pin[PIN_TDI].driver = 0; 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.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nTRST));
pin_reg.pullup = 1; pin_reg.pullup = 1;
WRITE_PERI_REG(GPIO_PIN_REG(PIN_nTRST), pin_reg.val); WRITE_PERI_REG(GPIO_PIN_REG(PIN_nTRST), pin_reg.val);
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nRESET)); pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nRESET));
pin_reg.pullup = 1; pin_reg.pullup = 1;
WRITE_PERI_REG(GPIO_PIN_REG(PIN_nRESET), pin_reg.val); 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) __STATIC_INLINE void PORT_SWD_SETUP(void)
{ {
gpio_pin_reg_t pin_reg; // 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();
// 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(); 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) __STATIC_INLINE void PORT_OFF(void)
{ {
// Will be called when the DAP disconnected // 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(); 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 ------------------------------------- // 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) __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) __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) __STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void)
{ {
// Need fast response
//// TODO: low speed
// set \ref gpio_set_direction -> OUTPUT // set \ref gpio_set_direction -> OUTPUT
// GPIO.enable_w1ts |= (0x1 << PIN_SWDIO_MOSI); // GPIO.enable_w1ts |= (0x1 << PIN_SWDIO_MOSI);
// GPIO.pin[PIN_SWDIO_MOSI].driver = 0; // 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) __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void)
{ {
// Need fast response // may be unuse.
// set \ref gpio_set_dircetion -> INPUT // set \ref gpio_set_dircetion -> INPUT
// esp8266 input is always connected // esp8266 input is always connected
// GPIO.enable_w1tc |= (0x1 << PIN_SWDIO_MOSI); // 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) __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 ------------------------------------------- // 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) __STATIC_INLINE void DAP_SETUP(void)
{ {
DAP_SPI_Init(); // Connecting non-SWD pins to GPIO
DAP_SPI_Disable(); 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) // 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); LED_CONNECTED_OUT(0);
gpio_set_direction(PIN_LED_RUNNING, GPIO_MODE_DEF_OUTPUT);
LED_RUNNING_OUT(0); LED_RUNNING_OUT(0);
PORT_OFF(); PORT_OFF();

View File

@ -233,6 +233,14 @@ extern DAP_Data_t DAP_Data; // DAP Data
extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag 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 #ifdef __cplusplus
extern "C" extern "C"
{ {

View File

@ -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

View File

@ -5,6 +5,7 @@
void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf); 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_Send_Header(const uint8_t packetHeaderData, uint8_t *ack, uint8_t TrnAfterACK);
void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity); void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity);

View File

@ -29,6 +29,8 @@
#include "DAP_config.h" #include "DAP_config.h"
#include "DAP.h" #include "DAP.h"
#include "spi_switch.h"
#if (DAP_PACKET_SIZE < 64U) #if (DAP_PACKET_SIZE < 64U)
#error "Minimum Packet Size is 64!" #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); return ((6U << 16) | 1U);
} }
extern uint8_t SWD_TransferSpeed;
// Process SWJ Clock command and prepare response // Process SWJ Clock command and prepare response
// request: pointer to request data // 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; *response = DAP_ERROR;
return ((4U << 16) | 1U); 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.fast_clock = 1U;
DAP_Data.clock_delay = 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 { } else {
// clock < 2MHz -> Use GPIO with delay
DAP_SPI_Deinit();
DAP_Data.fast_clock = 0U; 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) { if (delay > IO_PORT_WRITE_CYCLES) {
delay -= IO_PORT_WRITE_CYCLES; delay -= IO_PORT_WRITE_CYCLES;
delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES; delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES;

View File

@ -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_config.h"
#include "DAP.h" #include "DAP.h"
@ -37,31 +52,44 @@
// SW Macros // SW Macros
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET #define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR #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() \ #define SW_CLOCK_CYCLE() \
PIN_SWCLK_CLR(); \ PIN_SWCLK_CLR(); \
PIN_DELAY(); \ if (need_delay) { PIN_DELAY(); } \
PIN_SWCLK_SET(); \ PIN_SWCLK_SET(); \
PIN_DELAY() if (need_delay) { PIN_DELAY(); }
#define SW_WRITE_BIT(bit) \ #define SW_WRITE_BIT(bit) \
PIN_SWDIO_OUT(bit); \ PIN_SWDIO_OUT(bit); \
PIN_SWCLK_CLR(); \ PIN_SWCLK_CLR(); \
PIN_DELAY(); \ if (need_delay) { PIN_DELAY(); } \
PIN_SWCLK_SET(); \ PIN_SWCLK_SET(); \
PIN_DELAY() if (need_delay) { PIN_DELAY(); }
#define SW_READ_BIT(bit) \ #define SW_READ_BIT(bit) \
PIN_SWCLK_CLR(); \ PIN_SWCLK_CLR(); \
PIN_DELAY(); \ if (need_delay) { PIN_DELAY(); } \
bit = PIN_SWDIO_IN(); \ bit = PIN_SWDIO_IN(); \
PIN_SWCLK_SET(); \ 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 // Generate SWJ Sequence
@ -70,11 +98,44 @@
// return: none // return: none
#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) #if ((DAP_SWD != 0) || (DAP_JTAG != 0))
void SWJ_Sequence (uint32_t count, const uint8_t *data) { void SWJ_Sequence (uint32_t count, const uint8_t *data) {
if (count != 8 && count != 16 && count!= 51) // if (count != 8 && count != 16 && count!= 51)
{ // {
printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count); // printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count);
return; // 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_Enable();
DAP_SPI_WriteBits(count, data); DAP_SPI_WriteBits(count, data);
} }
@ -88,6 +149,16 @@ void SWJ_Sequence (uint32_t count, const uint8_t *data) {
// return: none // return: none
#if (DAP_SWD != 0) #if (DAP_SWD != 0)
void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { 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 val;
uint32_t bit; uint32_t bit;
uint32_t n, k; uint32_t n, k;
@ -96,7 +167,9 @@ void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
if (n == 0U) { if (n == 0U) {
n = 64U; n = 64U;
} }
// n = 1 ~ 64
// LSB
if (info & SWD_SEQUENCE_DIN) { if (info & SWD_SEQUENCE_DIN) {
while (n) { while (n) {
val = 0U; 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 #endif
@ -128,15 +217,8 @@ void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
// request: A[3:2] RnW APnDP // request: A[3:2] RnW APnDP
// data: DATA[31:0] // data: DATA[31:0]
// return: ACK[2:0] // return: ACK[2:0]
static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) {
//// TODO: low speed // SPI transfer mode does not require operations such as PIN_DELAY
#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; uint8_t ack;
// uint32_t bit; // uint32_t bit;
uint32_t val; uint32_t val;
@ -145,169 +227,284 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) {
uint32_t n; uint32_t n;
int retryCount = 0;
const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */ const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */
uint8_t requestByte; /* LSB */ uint8_t requestByte; /* LSB */
DAP_SPI_Enable(); 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) requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U);
switch (requestByte) /* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */
{
case 0xA5U: #if (PRINT_SWD_PROTOCOL == 1)
printf("IDCODE\r\n"); switch (requestByte)
break; {
case 0xA9U: case 0xA5U:
printf("W CTRL/STAT\r\n"); printf("IDCODE\r\n");
break; break;
case 0xBDU: case 0xA9U:
printf("RDBUFF\r\n"); printf("W CTRL/STAT\r\n");
break; break;
case 0x8DU: case 0xBDU:
printf("R CTRL/STAT\r\n"); printf("RDBUFF\r\n");
break; break;
case 0x81U: case 0x8DU:
printf("W ABORT\r\n"); printf("R CTRL/STAT\r\n");
break; break;
case 0xB1U: case 0x81U:
printf("W SELECT\r\n"); printf("W ABORT\r\n");
break; break;
case 0xBBU: case 0xB1U:
printf("W APc\r\n"); printf("W SELECT\r\n");
break; break;
case 0x9FU: case 0xBBU:
printf("R APc\r\n"); printf("W APc\r\n");
break; break;
case 0x8BU: case 0x9FU:
printf("W AP4\r\n"); printf("R APc\r\n");
break; break;
case 0xA3U: case 0x8BU:
printf("W AP0\r\n"); printf("W AP4\r\n");
break; break;
case 0X87U: case 0xA3U:
printf("R AP0\r\n"); printf("W AP0\r\n");
break; break;
case 0xB7U: case 0X87U:
printf("R AP8\r\n"); printf("R AP0\r\n");
break; break;
default: case 0xB7U:
//W AP8 printf("R AP8\r\n");
printf("Unknown:%08x\r\n", requestByte); break;
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;
} }
#endif if (data) { *data = val; }
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
if (request & DAP_TRANSFER_RnW) { DAP_Data.timestamp = TIMESTAMP_GET();
/* 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 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 { else {
/* Write data */ /* Protocol error */
parity = ParityEvenUint32(*data); DAP_SPI_Disable();
DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK PIN_SWDIO_TMS_SET();
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(); DAP_SPI_Enable();
PIN_SWDIO_TMS_SET(); DAP_SPI_Protocol_Error_Read();
return ((uint8_t)ack); 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();
} }
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { /* Idle cycles */
/* already turnaround. */ n = DAP_Data.transfer.idle_cycles;
if (n) { DAP_SPI_Generate_Cycle(n); }
/* TODO: overrun transfer -> for read */ DAP_SPI_Disable();
#if (PRINT_SWD_PROTOCOL == 1) PIN_SWDIO_TMS_SET();
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); 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
} }
} while (retryCount++ < 99); 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; return DAP_TRANSFER_ERROR;
} }
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_FAST()
SWD_TransferFunction(Fast)
#undef PIN_DELAY static uint8_t SWD_Transfer_GPIO (uint32_t request, uint32_t *data, uint8_t need_delay) {
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) uint32_t ack;
SWD_TransferFunction(Slow) 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 // SWD Transfer I/O
@ -315,10 +512,15 @@ SWD_TransferFunction(Slow)
// data: DATA[31:0] // data: DATA[31:0]
// return: ACK[2:0] // return: ACK[2:0]
uint8_t SWD_Transfer(uint32_t request, uint32_t *data) { uint8_t SWD_Transfer(uint32_t request, uint32_t *data) {
if (DAP_Data.fast_clock) { switch (SWD_TransferSpeed) {
return SWD_TransferFast(request, data); case kTransfer_SPI:
} else { return SWD_Transfer_SPI(request, data);
return SWD_TransferSlow(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);
} }
} }

View File

@ -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 <stdio.h>
#include "esp8266/spi_struct.h" #include "esp8266/spi_struct.h"
@ -6,12 +18,23 @@
#define DAP_SPI SPI1 #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 * @brief Write bits. LSB & little-endian
* Note: No check. The pointer must be valid. * 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 * @param buf Data Buf
*/ */
void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *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) switch (count)
{ {
case 8: 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; break;
case 16: 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; break;
case 33: // 32bits data & 1 bit parity 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[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[1] = (buf[4] << 0) | (0x000U << 8) | (0x000U << 16) | (0x000U << 24);
break; break;
case 51: // for line reset 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[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[1] = (buf[4] << 0) | (buf[5] << 8) | (buf[2] << 16) | (0x000U << 24);
break; break;
default: 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 // 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 * @brief Step1: Packet Request
* *
@ -72,7 +143,7 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *
DAP_SPI.user1.usr_miso_bitlen = 1U + 3U + TrnAfterACK - 1U; DAP_SPI.user1.usr_miso_bitlen = 1U + 3U + TrnAfterACK - 1U;
// copy data to reg // 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 // Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
@ -90,17 +161,16 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *
* @param resData data from target * @param resData data from target
* @param resParity parity 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; uint64_t dataBuf;
uint32_t *pU32Data = (uint32_t *)&dataBuf; uint32_t *pU32Data = (uint32_t *)&dataBuf;
DAP_SPI.user.usr_mosi = 0; DAP_SPI.user.usr_mosi = 0;
DAP_SPI.user.usr_miso = 1; DAP_SPI.user.usr_miso = 1;
// 1 bit Trn(End) + 3bits ACK + 32bis data + 1bit parity - 1(prescribed) // 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 // Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
@ -110,7 +180,7 @@ __FORCEINLINE void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity)
pU32Data[0] = DAP_SPI.data_buf[0]; pU32Data[0] = DAP_SPI.data_buf[0];
pU32Data[1] = DAP_SPI.data_buf[1]; 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 *resParity = (dataBuf >> (0U + 32U)) & 1U; // 3bits ACK + 32bis data
} }
@ -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) __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_mosi = 1;
DAP_SPI.user.usr_miso = 0; DAP_SPI.user.usr_miso = 0;
DAP_SPI.user1.usr_mosi_bitlen = num - 1U; DAP_SPI.user1.usr_mosi_bitlen = num - 1U;

View File

@ -2,10 +2,12 @@
* @file spi_switch.c * @file spi_switch.c
* @author windowsair * @author windowsair
* @brief Switching between SPI mode and IO mode * @brief Switching between SPI mode and IO mode
* @version 0.1 * @change: 2020-11-25 first version
* @date 2020-11-25 * 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> #include <stdbool.h>
@ -110,6 +112,8 @@ void DAP_SPI_Init()
pin_reg.pullup = 0; pin_reg.pullup = 0;
WRITE_PERI_REG(GPIO_PIN_REG(12), pin_reg.val); WRITE_PERI_REG(GPIO_PIN_REG(12), pin_reg.val);
// Set spi clk div // Set spi clk div
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK); 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; 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 * @brief Use SPI acclerate
* *
*/ */
void DAP_SPI_Enable() 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) PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out)
} }
/** /**
* @brief Disable SPI * @brief Disable SPI
* * Drive capability not yet known
*/ */
__FORCEINLINE void DAP_SPI_Disable() __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));
__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 // may be unuse
gpio_pin_reg_t pin_reg; // gpio_pin_reg_t pin_reg;
GPIO.enable_w1ts |= (0x1 << 13); // GPIO.enable_w1ts |= (0x1 << 13);
GPIO.pin[13].driver = 0; // OD Output // GPIO.pin[13].driver = 0; // OD Output
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13)); // pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13));
pin_reg.pullup = 1; // pin_reg.pullup = 1;
WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val); // WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val);
} }