feat: Enhance SPI and GPIO compatibility.
This commit is contained in:
parent
3f0d196bce
commit
b4691546d1
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
|
||||
*
|
||||
|
@ -90,17 +161,16 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *
|
|||
* @param resData data from target
|
||||
* @param resParity parity from target
|
||||
*/
|
||||
__FORCEINLINE void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity)
|
||||
__FORCEINLINE void DAP_SPI_Read_Data(uint32_t *resData, uint8_t *resParity)
|
||||
{
|
||||
uint64_t dataBuf;
|
||||
uint32_t *pU32Data = (uint32_t *)&dataBuf;
|
||||
|
||||
|
||||
DAP_SPI.user.usr_mosi = 0;
|
||||
DAP_SPI.user.usr_miso = 1;
|
||||
|
||||
// 1 bit Trn(End) + 3bits ACK + 32bis data + 1bit parity - 1(prescribed)
|
||||
DAP_SPI.user1.usr_miso_bitlen = 1U +32U + 1U - 1U;
|
||||
DAP_SPI.user1.usr_miso_bitlen = 1U + 32U + 1U - 1U;
|
||||
|
||||
// Start transmission
|
||||
DAP_SPI.cmd.usr = 1;
|
||||
|
@ -110,7 +180,7 @@ __FORCEINLINE void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity)
|
|||
pU32Data[0] = DAP_SPI.data_buf[0];
|
||||
pU32Data[1] = DAP_SPI.data_buf[1];
|
||||
|
||||
*resData = (dataBuf >> 0U) & 0xFFFFFFFFU ; // 32bits Response Data
|
||||
*resData = (dataBuf >> 0U) & 0xFFFFFFFFU; // 32bits Response Data
|
||||
*resParity = (dataBuf >> (0U + 32U)) & 1U; // 3bits ACK + 32bis data
|
||||
}
|
||||
|
||||
|
@ -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