feat: Enhance SPI and GPIO compatibility.
This commit is contained in:
parent
3f0d196bce
commit
b4691546d1
110
README.md
110
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
|
||||
|
||||
|
@ -117,9 +134,8 @@ python ./idf.py -p /dev/ttyS5 flash
|
|||
|
||||
1. Get USBIP project
|
||||
|
||||
- Windows: [usbip-win](https://github.com/cezanne/usbip-win) .
|
||||
> The pre-compiled version on SourceForge is also available, for HID mode only, but it may be faster.
|
||||
- Linux: Distributed as part of the kernel
|
||||
- Windows: [usbip-win](https://github.com/cezanne/usbip-win) .
|
||||
- Linux: Distributed as part of the Linux kernel, but we have not yet tested on Linux platform, and the following instructions are all under Windows platform.
|
||||
|
||||
2. Start esp8266 and connect it to the device to be debugged
|
||||
|
||||
|
@ -131,6 +147,7 @@ python ./idf.py -p /dev/ttyS5 flash
|
|||
# or usbip old version
|
||||
.\usbip.exe -D -a <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)
|
File diff suppressed because it is too large
Load Diff
|
@ -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!"
|
||||
|
@ -109,7 +111,7 @@ static uint8_t DAP_Info(uint8_t id, uint8_t *info) {
|
|||
length = 1U;
|
||||
break;
|
||||
case DAP_ID_TIMESTAMP_CLOCK:
|
||||
#if (TIMESTAMP_CLOCK != 0U)
|
||||
#if (TIMESTAMP_CLOCK != 0U)
|
||||
info[0] = (uint8_t)(TIMESTAMP_CLOCK >> 0);
|
||||
info[1] = (uint8_t)(TIMESTAMP_CLOCK >> 8);
|
||||
info[2] = (uint8_t)(TIMESTAMP_CLOCK >> 16);
|
||||
|
@ -207,7 +209,7 @@ static uint32_t DAP_Connect(const uint8_t *request, uint8_t *response) {
|
|||
} else {
|
||||
port = *request;
|
||||
}
|
||||
|
||||
|
||||
switch (port) {
|
||||
#if (DAP_SWD != 0)
|
||||
case DAP_PORT_SWD:
|
||||
|
@ -266,9 +268,9 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) {
|
|||
uint32_t select;
|
||||
uint32_t wait;
|
||||
uint32_t timestamp;
|
||||
|
||||
|
||||
value = (uint32_t) *(request+0);
|
||||
select = (uint32_t) *(request+1);
|
||||
select = (uint32_t) *(request+1);
|
||||
wait = (uint32_t)(*(request+2) << 0) |
|
||||
(uint32_t)(*(request+3) << 8) |
|
||||
(uint32_t)(*(request+4) << 16) |
|
||||
|
@ -300,7 +302,7 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) {
|
|||
|
||||
if (wait != 0U) {
|
||||
#if (TIMESTAMP_CLOCK != 0U)
|
||||
if (wait > 3000000U) {
|
||||
if (wait > 3000000U) {
|
||||
wait = 3000000U;
|
||||
}
|
||||
#if (TIMESTAMP_CLOCK >= 1000000U)
|
||||
|
@ -357,6 +359,7 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) {
|
|||
return ((6U << 16) | 1U);
|
||||
}
|
||||
|
||||
extern uint8_t SWD_TransferSpeed;
|
||||
|
||||
// Process SWJ Clock command and prepare response
|
||||
// request: pointer to request data
|
||||
|
@ -377,18 +380,30 @@ static uint32_t DAP_SWJ_Clock(const uint8_t *request, uint8_t *response) {
|
|||
*response = DAP_ERROR;
|
||||
return ((4U << 16) | 1U);
|
||||
}
|
||||
if(clock == 10000000){
|
||||
clock = MAX_USER_CLOCK;
|
||||
}
|
||||
|
||||
|
||||
if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) {
|
||||
// Note that the maximum IO frequency of esp8266 is less than 2MHz
|
||||
|
||||
// clock >= 10MHz -> use 40MHz SPI
|
||||
if (clock >= 10000000) {
|
||||
DAP_SPI_Init();
|
||||
DAP_Data.fast_clock = 1U;
|
||||
DAP_Data.clock_delay = 1U;
|
||||
SWD_TransferSpeed = kTransfer_SPI;
|
||||
} else if (clock >= 2000000) {
|
||||
// clock >= 2MHz -> Use GPIO with no program delay
|
||||
DAP_SPI_Deinit();
|
||||
DAP_Data.fast_clock = 1U;
|
||||
DAP_Data.clock_delay = 1U;
|
||||
SWD_TransferSpeed = kTransfer_GPIO_fast;
|
||||
} else {
|
||||
// clock < 2MHz -> Use GPIO with delay
|
||||
DAP_SPI_Deinit();
|
||||
DAP_Data.fast_clock = 0U;
|
||||
SWD_TransferSpeed = kTransfer_GPIO_normal;
|
||||
|
||||
delay = ((CPU_CLOCK/2U) + (clock - 1U)) / clock;
|
||||
#define CPU_CLOCK_FIXED 80000000
|
||||
|
||||
delay = ((CPU_CLOCK_FIXED/2U) + (clock - 1U)) / clock;
|
||||
if (delay > IO_PORT_WRITE_CYCLES) {
|
||||
delay -= IO_PORT_WRITE_CYCLES;
|
||||
delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES;
|
||||
|
@ -417,7 +432,7 @@ static uint32_t DAP_SWJ_Sequence(const uint8_t *request, uint8_t *response) {
|
|||
uint32_t count;
|
||||
|
||||
count = *request++;
|
||||
if (count == 0U) {
|
||||
if (count == 0U) {
|
||||
count = 256U;
|
||||
}
|
||||
|
||||
|
@ -446,7 +461,7 @@ static uint32_t DAP_SWD_Configure(const uint8_t *request, uint8_t *response) {
|
|||
value = *request;
|
||||
DAP_Data.swd_conf.turnaround = (value & 0x03U) + 1U;
|
||||
DAP_Data.swd_conf.data_phase = (value & 0x04U) ? 1U : 0U;
|
||||
|
||||
|
||||
*response = DAP_OK;
|
||||
#else
|
||||
*response = DAP_ERROR;
|
||||
|
@ -480,7 +495,7 @@ static uint32_t DAP_SWD_Sequence(const uint8_t *request, uint8_t *response) {
|
|||
while (sequence_count--) {
|
||||
sequence_info = *request++;
|
||||
count = sequence_info & SWD_SEQUENCE_CLK;
|
||||
if (count == 0U) {
|
||||
if (count == 0U) {
|
||||
count = 64U;
|
||||
}
|
||||
count = (count + 7U) / 8U;
|
||||
|
@ -630,7 +645,7 @@ static uint32_t DAP_JTAG_IDCode(const uint8_t *request, uint8_t *response) {
|
|||
id_error:
|
||||
#endif
|
||||
*response = DAP_ERROR;
|
||||
return ((1U << 16) | 1U);
|
||||
return ((1U << 16) | 1U);
|
||||
}
|
||||
|
||||
|
||||
|
@ -644,11 +659,11 @@ static uint32_t DAP_TransferConfigure(const uint8_t *request, uint8_t *response)
|
|||
DAP_Data.transfer.idle_cycles = *(request+0);
|
||||
DAP_Data.transfer.retry_count = (uint16_t) *(request+1) |
|
||||
(uint16_t)(*(request+2) << 8);
|
||||
DAP_Data.transfer.match_retry = (uint16_t) *(request+3) |
|
||||
DAP_Data.transfer.match_retry = (uint16_t) *(request+3) |
|
||||
(uint16_t)(*(request+4) << 8);
|
||||
|
||||
*response = DAP_OK;
|
||||
return ((5U << 16) | 1U);
|
||||
return ((5U << 16) | 1U);
|
||||
}
|
||||
|
||||
|
||||
|
@ -711,7 +726,7 @@ static uint32_t DAP_SWD_Transfer(const uint8_t *request, uint8_t *response) {
|
|||
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
|
||||
post_read = 0U;
|
||||
}
|
||||
if (response_value != DAP_TRANSFER_OK) {
|
||||
if (response_value != DAP_TRANSFER_OK) {
|
||||
break;
|
||||
}
|
||||
// Store previous AP data
|
||||
|
@ -1386,14 +1401,14 @@ static uint32_t DAP_JTAG_TransferBlock(const uint8_t *request, uint8_t *response
|
|||
|
||||
// Device index (JTAP TAP)
|
||||
DAP_Data.jtag_dev.index = *request++;
|
||||
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
|
||||
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
request_count = (uint32_t)(*(request+0) << 0) |
|
||||
request_count = (uint32_t)(*(request+0) << 0) |
|
||||
(uint32_t)(*(request+1) << 8);
|
||||
request += 2;
|
||||
if (request_count == 0U) {
|
||||
if (request_count == 0U) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
@ -1549,7 +1564,7 @@ static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) {
|
|||
DAP_Data.jtag_dev.index = *request;
|
||||
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
|
||||
*response = DAP_ERROR;
|
||||
return (1U);
|
||||
return (1U);
|
||||
}
|
||||
|
||||
// Select JTAG chain
|
||||
|
@ -1565,7 +1580,7 @@ static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) {
|
|||
JTAG_WriteAbort(data);
|
||||
|
||||
*response = DAP_OK;
|
||||
return (1U);
|
||||
return (1U);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1741,7 +1756,7 @@ uint32_t DAP_ExecuteCommand(const uint8_t *request, uint8_t *response) {
|
|||
n = DAP_ProcessCommand(request, response);
|
||||
num += n;
|
||||
request += (uint16_t)(n >> 16);
|
||||
response += (uint16_t) n;
|
||||
response += (uint16_t) n;
|
||||
}
|
||||
return (num);
|
||||
}
|
||||
|
|
|
@ -1,326 +1,528 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* $Date: 1. December 2017
|
||||
* $Revision: V2.0.0
|
||||
*
|
||||
* Project: CMSIS-DAP Source
|
||||
* Title: SW_DP.c CMSIS-DAP SW DP I/O
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "DAP_config.h"
|
||||
#include "DAP.h"
|
||||
|
||||
#include "spi_op.h"
|
||||
#include "spi_switch.h"
|
||||
#include "dap_utility.h"
|
||||
|
||||
// Debug
|
||||
#define PRINT_SWD_PROTOCOL 0
|
||||
|
||||
// SW Macros
|
||||
|
||||
#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
|
||||
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR
|
||||
|
||||
#define SW_CLOCK_CYCLE() \
|
||||
PIN_SWCLK_CLR(); \
|
||||
PIN_DELAY(); \
|
||||
PIN_SWCLK_SET(); \
|
||||
PIN_DELAY()
|
||||
|
||||
#define SW_WRITE_BIT(bit) \
|
||||
PIN_SWDIO_OUT(bit); \
|
||||
PIN_SWCLK_CLR(); \
|
||||
PIN_DELAY(); \
|
||||
PIN_SWCLK_SET(); \
|
||||
PIN_DELAY()
|
||||
|
||||
#define SW_READ_BIT(bit) \
|
||||
PIN_SWCLK_CLR(); \
|
||||
PIN_DELAY(); \
|
||||
bit = PIN_SWDIO_IN(); \
|
||||
PIN_SWCLK_SET(); \
|
||||
PIN_DELAY()
|
||||
|
||||
//#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
|
||||
#define PIN_DELAY() PIN_DELAY_FAST()
|
||||
|
||||
|
||||
// Generate SWJ Sequence
|
||||
// count: sequence bit count
|
||||
// data: pointer to sequence bit data
|
||||
// return: none
|
||||
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
|
||||
void SWJ_Sequence (uint32_t count, const uint8_t *data) {
|
||||
if (count != 8 && count != 16 && count!= 51)
|
||||
{
|
||||
printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count);
|
||||
return;
|
||||
}
|
||||
DAP_SPI_Enable();
|
||||
DAP_SPI_WriteBits(count, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Generate SWD Sequence
|
||||
// info: sequence information
|
||||
// swdo: pointer to SWDIO generated data
|
||||
// swdi: pointer to SWDIO captured data
|
||||
// return: none
|
||||
#if (DAP_SWD != 0)
|
||||
void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
|
||||
uint32_t val;
|
||||
uint32_t bit;
|
||||
uint32_t n, k;
|
||||
|
||||
n = info & SWD_SEQUENCE_CLK;
|
||||
if (n == 0U) {
|
||||
n = 64U;
|
||||
}
|
||||
|
||||
if (info & SWD_SEQUENCE_DIN) {
|
||||
while (n) {
|
||||
val = 0U;
|
||||
for (k = 8U; k && n; k--, n--) {
|
||||
SW_READ_BIT(bit);
|
||||
val >>= 1;
|
||||
val |= bit << 7;
|
||||
}
|
||||
val >>= k;
|
||||
*swdi++ = (uint8_t)val;
|
||||
}
|
||||
} else {
|
||||
while (n) {
|
||||
val = *swdo++;
|
||||
for (k = 8U; k && n; k--, n--) {
|
||||
SW_WRITE_BIT(val);
|
||||
val >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if (DAP_SWD != 0)
|
||||
|
||||
|
||||
// SWD Transfer I/O
|
||||
// request: A[3:2] RnW APnDP
|
||||
// data: DATA[31:0]
|
||||
// return: ACK[2:0]
|
||||
|
||||
//// TODO: low speed
|
||||
#define SWD_TransferFunction(speed) /* Speed may be useless, because all use this function */ \
|
||||
static uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \
|
||||
SWD_Transfer_Common(request,data); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) {
|
||||
uint8_t ack;
|
||||
// uint32_t bit;
|
||||
uint32_t val;
|
||||
uint8_t parity;
|
||||
uint8_t computedParity;
|
||||
|
||||
uint32_t n;
|
||||
|
||||
int retryCount = 0;
|
||||
const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */
|
||||
uint8_t requestByte; /* LSB */
|
||||
|
||||
|
||||
DAP_SPI_Enable();
|
||||
do {
|
||||
requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U);
|
||||
/* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */
|
||||
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
switch (requestByte)
|
||||
{
|
||||
case 0xA5U:
|
||||
printf("IDCODE\r\n");
|
||||
break;
|
||||
case 0xA9U:
|
||||
printf("W CTRL/STAT\r\n");
|
||||
break;
|
||||
case 0xBDU:
|
||||
printf("RDBUFF\r\n");
|
||||
break;
|
||||
case 0x8DU:
|
||||
printf("R CTRL/STAT\r\n");
|
||||
break;
|
||||
case 0x81U:
|
||||
printf("W ABORT\r\n");
|
||||
break;
|
||||
case 0xB1U:
|
||||
printf("W SELECT\r\n");
|
||||
break;
|
||||
case 0xBBU:
|
||||
printf("W APc\r\n");
|
||||
break;
|
||||
case 0x9FU:
|
||||
printf("R APc\r\n");
|
||||
break;
|
||||
case 0x8BU:
|
||||
printf("W AP4\r\n");
|
||||
break;
|
||||
case 0xA3U:
|
||||
printf("W AP0\r\n");
|
||||
break;
|
||||
case 0X87U:
|
||||
printf("R AP0\r\n");
|
||||
break;
|
||||
case 0xB7U:
|
||||
printf("R AP8\r\n");
|
||||
break;
|
||||
default:
|
||||
//W AP8
|
||||
printf("Unknown:%08x\r\n", requestByte);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (request & DAP_TRANSFER_RnW) {
|
||||
/* Read data */
|
||||
|
||||
DAP_SPI_Send_Header(requestByte, &ack, 0); // 0 Trn After ACK
|
||||
if (ack == DAP_TRANSFER_OK) {
|
||||
DAP_SPI_Read_Data(&val, &parity);
|
||||
computedParity = ParityEvenUint32(val);
|
||||
|
||||
if ((computedParity ^ parity) & 1U) {
|
||||
ack = DAP_TRANSFER_ERROR;
|
||||
}
|
||||
if (data) { *data = val; }
|
||||
|
||||
/* Capture Timestamp */
|
||||
if (request & DAP_TRANSFER_TIMESTAMP) {
|
||||
DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
}
|
||||
|
||||
}
|
||||
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
|
||||
DAP_SPI_Generate_Cycle(1);
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
printf("WAIT\r\n");
|
||||
#endif
|
||||
|
||||
continue;
|
||||
// return DAP_TRANSFER_WAIT;
|
||||
}
|
||||
else {
|
||||
/* Protocol error */
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
|
||||
DAP_SPI_Enable();
|
||||
DAP_SPI_Protocol_Error_Read();
|
||||
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
printf("Protocol Error: Read\r\n");
|
||||
}
|
||||
|
||||
return ((uint8_t)ack);
|
||||
}
|
||||
else {
|
||||
/* Write data */
|
||||
parity = ParityEvenUint32(*data);
|
||||
DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK
|
||||
if (ack == DAP_TRANSFER_OK) {
|
||||
DAP_SPI_Write_Data(*data, parity);
|
||||
/* Capture Timestamp */
|
||||
if (request & DAP_TRANSFER_TIMESTAMP) {
|
||||
DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
}
|
||||
/* Idle cycles */
|
||||
n = DAP_Data.transfer.idle_cycles;
|
||||
if (n) { DAP_SPI_Generate_Cycle(n); }
|
||||
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
|
||||
return ((uint8_t)ack);
|
||||
}
|
||||
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
|
||||
/* already turnaround. */
|
||||
|
||||
/* TODO: overrun transfer -> for read */
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
printf("WAIT\r\n");
|
||||
#endif
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
else {
|
||||
//// FIXME: bug
|
||||
/* Protocol error */
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
|
||||
DAP_SPI_Enable();
|
||||
DAP_SPI_Protocol_Error_Write();
|
||||
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
printf("Protocol Error: Write\r\n");
|
||||
}
|
||||
|
||||
return ((uint8_t)ack);
|
||||
|
||||
}
|
||||
} while (retryCount++ < 99);
|
||||
|
||||
return DAP_TRANSFER_ERROR;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#undef PIN_DELAY
|
||||
#define PIN_DELAY() PIN_DELAY_FAST()
|
||||
SWD_TransferFunction(Fast)
|
||||
|
||||
#undef PIN_DELAY
|
||||
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
|
||||
SWD_TransferFunction(Slow)
|
||||
|
||||
|
||||
// SWD Transfer I/O
|
||||
// request: A[3:2] RnW APnDP
|
||||
// data: DATA[31:0]
|
||||
// return: ACK[2:0]
|
||||
uint8_t SWD_Transfer(uint32_t request, uint32_t *data) {
|
||||
if (DAP_Data.fast_clock) {
|
||||
return SWD_TransferFast(request, data);
|
||||
} else {
|
||||
return SWD_TransferSlow(request, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* (DAP_SWD != 0) */
|
||||
/*
|
||||
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* $Date: 1. December 2017
|
||||
* $Revision: V2.0.0
|
||||
*
|
||||
* Project: CMSIS-DAP Source
|
||||
* Title: SW_DP.c CMSIS-DAP SW DP I/O
|
||||
*
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @file SW_DP.c
|
||||
* @author windowsair
|
||||
* @brief Adaptation of GPIO and SPI
|
||||
* @change:
|
||||
* 2021-2-10 Support GPIO and SPI for SWD sequence / SWJ sequence / SWD transfer
|
||||
* Note: SWD sequence not yet tested
|
||||
* @version 0.1
|
||||
* @date 2021-2-10
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "DAP_config.h"
|
||||
#include "DAP.h"
|
||||
|
||||
#include "spi_op.h"
|
||||
#include "spi_switch.h"
|
||||
#include "dap_utility.h"
|
||||
|
||||
// Debug
|
||||
#define PRINT_SWD_PROTOCOL 0
|
||||
|
||||
// SW Macros
|
||||
|
||||
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
|
||||
|
||||
#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
|
||||
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR
|
||||
|
||||
// Space for time in the original version,
|
||||
// and time for space in our implementation
|
||||
|
||||
#define SW_CLOCK_CYCLE() \
|
||||
PIN_SWCLK_CLR(); \
|
||||
if (need_delay) { PIN_DELAY(); } \
|
||||
PIN_SWCLK_SET(); \
|
||||
if (need_delay) { PIN_DELAY(); }
|
||||
|
||||
#define SW_WRITE_BIT(bit) \
|
||||
PIN_SWDIO_OUT(bit); \
|
||||
PIN_SWCLK_CLR(); \
|
||||
if (need_delay) { PIN_DELAY(); } \
|
||||
PIN_SWCLK_SET(); \
|
||||
if (need_delay) { PIN_DELAY(); }
|
||||
|
||||
#define SW_READ_BIT(bit) \
|
||||
PIN_SWCLK_CLR(); \
|
||||
if (need_delay) { PIN_DELAY(); } \
|
||||
bit = PIN_SWDIO_IN(); \
|
||||
PIN_SWCLK_SET(); \
|
||||
if (need_delay) { PIN_DELAY(); }
|
||||
|
||||
|
||||
|
||||
uint8_t SWD_TransferSpeed = kTransfer_GPIO_normal;
|
||||
|
||||
|
||||
void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay);
|
||||
void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data);
|
||||
|
||||
void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi);
|
||||
void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi);
|
||||
|
||||
|
||||
// Generate SWJ Sequence
|
||||
// count: sequence bit count
|
||||
// data: pointer to sequence bit data
|
||||
// return: none
|
||||
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
|
||||
void SWJ_Sequence (uint32_t count, const uint8_t *data) {
|
||||
// if (count != 8 && count != 16 && count!= 51)
|
||||
// {
|
||||
// printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count);
|
||||
// return;
|
||||
// }
|
||||
|
||||
if(SWD_TransferSpeed == kTransfer_SPI) {
|
||||
SWJ_Sequence_SPI(count, data);
|
||||
} else {
|
||||
SWJ_Sequence_GPIO(count, data, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay) {
|
||||
uint32_t val;
|
||||
uint32_t n;
|
||||
|
||||
val = 0U;
|
||||
n = 0U;
|
||||
while (count--) {
|
||||
if (n == 0U) {
|
||||
val = *data++;
|
||||
n = 8U;
|
||||
}
|
||||
if (val & 1U) {
|
||||
PIN_SWDIO_TMS_SET();
|
||||
} else {
|
||||
PIN_SWDIO_TMS_CLR();
|
||||
}
|
||||
SW_CLOCK_CYCLE();
|
||||
val >>= 1;
|
||||
n--;
|
||||
}
|
||||
}
|
||||
|
||||
void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data) {
|
||||
DAP_SPI_Enable();
|
||||
DAP_SPI_WriteBits(count, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Generate SWD Sequence
|
||||
// info: sequence information
|
||||
// swdo: pointer to SWDIO generated data
|
||||
// swdi: pointer to SWDIO captured data
|
||||
// return: none
|
||||
#if (DAP_SWD != 0)
|
||||
void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
|
||||
if (SWD_TransferSpeed == kTransfer_SPI) {
|
||||
SWD_Sequence_SPI(info, swdo, swdi);
|
||||
} else {
|
||||
SWD_Sequence_GPIO(info, swdo, swdi);
|
||||
}
|
||||
}
|
||||
|
||||
void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
|
||||
const uint8_t need_delay = 1;
|
||||
|
||||
uint32_t val;
|
||||
uint32_t bit;
|
||||
uint32_t n, k;
|
||||
|
||||
n = info & SWD_SEQUENCE_CLK;
|
||||
if (n == 0U) {
|
||||
n = 64U;
|
||||
}
|
||||
// n = 1 ~ 64
|
||||
|
||||
// LSB
|
||||
if (info & SWD_SEQUENCE_DIN) {
|
||||
while (n) {
|
||||
val = 0U;
|
||||
for (k = 8U; k && n; k--, n--) {
|
||||
SW_READ_BIT(bit);
|
||||
val >>= 1;
|
||||
val |= bit << 7;
|
||||
}
|
||||
val >>= k;
|
||||
*swdi++ = (uint8_t)val;
|
||||
}
|
||||
} else {
|
||||
while (n) {
|
||||
val = *swdo++;
|
||||
for (k = 8U; k && n; k--, n--) {
|
||||
SW_WRITE_BIT(val);
|
||||
val >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
|
||||
uint32_t n;
|
||||
n = info & SWD_SEQUENCE_CLK;
|
||||
if (n == 0U) {
|
||||
n = 64U;
|
||||
}
|
||||
// n = 1 ~ 64
|
||||
|
||||
if (info & SWD_SEQUENCE_DIN) {
|
||||
DAP_SPI_ReadBits(n, swdi);
|
||||
} else {
|
||||
DAP_SPI_WriteBits(n, swdo);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if (DAP_SWD != 0)
|
||||
|
||||
|
||||
// SWD Transfer I/O
|
||||
// request: A[3:2] RnW APnDP
|
||||
// data: DATA[31:0]
|
||||
// return: ACK[2:0]
|
||||
static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) {
|
||||
// SPI transfer mode does not require operations such as PIN_DELAY
|
||||
uint8_t ack;
|
||||
// uint32_t bit;
|
||||
uint32_t val;
|
||||
uint8_t parity;
|
||||
uint8_t computedParity;
|
||||
|
||||
uint32_t n;
|
||||
|
||||
const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */
|
||||
uint8_t requestByte; /* LSB */
|
||||
|
||||
|
||||
DAP_SPI_Enable();
|
||||
|
||||
requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U);
|
||||
/* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */
|
||||
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
switch (requestByte)
|
||||
{
|
||||
case 0xA5U:
|
||||
printf("IDCODE\r\n");
|
||||
break;
|
||||
case 0xA9U:
|
||||
printf("W CTRL/STAT\r\n");
|
||||
break;
|
||||
case 0xBDU:
|
||||
printf("RDBUFF\r\n");
|
||||
break;
|
||||
case 0x8DU:
|
||||
printf("R CTRL/STAT\r\n");
|
||||
break;
|
||||
case 0x81U:
|
||||
printf("W ABORT\r\n");
|
||||
break;
|
||||
case 0xB1U:
|
||||
printf("W SELECT\r\n");
|
||||
break;
|
||||
case 0xBBU:
|
||||
printf("W APc\r\n");
|
||||
break;
|
||||
case 0x9FU:
|
||||
printf("R APc\r\n");
|
||||
break;
|
||||
case 0x8BU:
|
||||
printf("W AP4\r\n");
|
||||
break;
|
||||
case 0xA3U:
|
||||
printf("W AP0\r\n");
|
||||
break;
|
||||
case 0X87U:
|
||||
printf("R AP0\r\n");
|
||||
break;
|
||||
case 0xB7U:
|
||||
printf("R AP8\r\n");
|
||||
break;
|
||||
default:
|
||||
//W AP8
|
||||
printf("Unknown:%08x\r\n", requestByte);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (request & DAP_TRANSFER_RnW) {
|
||||
/* Read data */
|
||||
|
||||
DAP_SPI_Send_Header(requestByte, &ack, 0); // 0 Trn After ACK
|
||||
if (ack == DAP_TRANSFER_OK) {
|
||||
DAP_SPI_Read_Data(&val, &parity);
|
||||
computedParity = ParityEvenUint32(val);
|
||||
|
||||
if ((computedParity ^ parity) & 1U) {
|
||||
ack = DAP_TRANSFER_ERROR;
|
||||
}
|
||||
if (data) { *data = val; }
|
||||
|
||||
/* Capture Timestamp */
|
||||
if (request & DAP_TRANSFER_TIMESTAMP) {
|
||||
DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
}
|
||||
|
||||
}
|
||||
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
|
||||
DAP_SPI_Generate_Cycle(1);
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
printf("WAIT\r\n");
|
||||
#endif
|
||||
|
||||
// return DAP_TRANSFER_WAIT;
|
||||
}
|
||||
else {
|
||||
/* Protocol error */
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
|
||||
DAP_SPI_Enable();
|
||||
DAP_SPI_Protocol_Error_Read();
|
||||
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
printf("Protocol Error: Read\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return ((uint8_t)ack);
|
||||
}
|
||||
else {
|
||||
/* Write data */
|
||||
parity = ParityEvenUint32(*data);
|
||||
DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK
|
||||
if (ack == DAP_TRANSFER_OK) {
|
||||
DAP_SPI_Write_Data(*data, parity);
|
||||
/* Capture Timestamp */
|
||||
if (request & DAP_TRANSFER_TIMESTAMP) {
|
||||
DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
}
|
||||
/* Idle cycles */
|
||||
n = DAP_Data.transfer.idle_cycles;
|
||||
if (n) { DAP_SPI_Generate_Cycle(n); }
|
||||
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
|
||||
return ((uint8_t)ack);
|
||||
}
|
||||
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
|
||||
/* already turnaround. */
|
||||
|
||||
/* TODO: overrun transfer -> for read */
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
printf("WAIT\r\n");
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
//// FIXME: bug
|
||||
/* Protocol error */
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
|
||||
DAP_SPI_Enable();
|
||||
DAP_SPI_Protocol_Error_Write();
|
||||
|
||||
DAP_SPI_Disable();
|
||||
PIN_SWDIO_TMS_SET();
|
||||
|
||||
#if (PRINT_SWD_PROTOCOL == 1)
|
||||
printf("Protocol Error: Write\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return ((uint8_t)ack);
|
||||
|
||||
}
|
||||
|
||||
return DAP_TRANSFER_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint8_t SWD_Transfer_GPIO (uint32_t request, uint32_t *data, uint8_t need_delay) {
|
||||
uint32_t ack;
|
||||
uint32_t bit;
|
||||
uint32_t val;
|
||||
uint32_t parity;
|
||||
|
||||
uint32_t n;
|
||||
|
||||
/* Packet Request */
|
||||
parity = 0U;
|
||||
SW_WRITE_BIT(1U); /* Start Bit */
|
||||
bit = request >> 0;
|
||||
SW_WRITE_BIT(bit); /* APnDP Bit */
|
||||
parity += bit;
|
||||
bit = request >> 1;
|
||||
SW_WRITE_BIT(bit); /* RnW Bit */
|
||||
parity += bit;
|
||||
bit = request >> 2;
|
||||
SW_WRITE_BIT(bit); /* A2 Bit */
|
||||
parity += bit;
|
||||
bit = request >> 3;
|
||||
SW_WRITE_BIT(bit); /* A3 Bit */
|
||||
parity += bit;
|
||||
SW_WRITE_BIT(parity); /* Parity Bit */
|
||||
SW_WRITE_BIT(0U); /* Stop Bit */
|
||||
SW_WRITE_BIT(1U); /* Park Bit */
|
||||
|
||||
/* Turnaround */
|
||||
PIN_SWDIO_OUT_DISABLE();
|
||||
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
|
||||
SW_CLOCK_CYCLE();
|
||||
}
|
||||
|
||||
/* Acknowledge response */
|
||||
SW_READ_BIT(bit);
|
||||
ack = bit << 0;
|
||||
SW_READ_BIT(bit);
|
||||
ack |= bit << 1;
|
||||
SW_READ_BIT(bit);
|
||||
ack |= bit << 2;
|
||||
|
||||
if (ack == DAP_TRANSFER_OK) { /* OK response */
|
||||
/* Data transfer */
|
||||
if (request & DAP_TRANSFER_RnW) {
|
||||
/* Read data */
|
||||
val = 0U;
|
||||
parity = 0U;
|
||||
for (n = 32U; n; n--) {
|
||||
SW_READ_BIT(bit); /* Read RDATA[0:31] */
|
||||
parity += bit;
|
||||
val >>= 1;
|
||||
val |= bit << 31;
|
||||
}
|
||||
SW_READ_BIT(bit); /* Read Parity */
|
||||
if ((parity ^ bit) & 1U) {
|
||||
ack = DAP_TRANSFER_ERROR;
|
||||
}
|
||||
if (data) { *data = val; }
|
||||
/* Turnaround */
|
||||
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
|
||||
SW_CLOCK_CYCLE();
|
||||
}
|
||||
PIN_SWDIO_OUT_ENABLE();
|
||||
} else {
|
||||
/* Turnaround */
|
||||
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
|
||||
SW_CLOCK_CYCLE();
|
||||
}
|
||||
PIN_SWDIO_OUT_ENABLE();
|
||||
/* Write data */
|
||||
val = *data;
|
||||
parity = 0U;
|
||||
for (n = 32U; n; n--) {
|
||||
SW_WRITE_BIT(val); /* Write WDATA[0:31] */
|
||||
parity += val;
|
||||
val >>= 1;
|
||||
}
|
||||
SW_WRITE_BIT(parity); /* Write Parity Bit */
|
||||
}
|
||||
/* Capture Timestamp */
|
||||
if (request & DAP_TRANSFER_TIMESTAMP) {
|
||||
DAP_Data.timestamp = TIMESTAMP_GET();
|
||||
}
|
||||
/* Idle cycles */
|
||||
n = DAP_Data.transfer.idle_cycles;
|
||||
if (n) {
|
||||
PIN_SWDIO_OUT(0U);
|
||||
for (; n; n--) {
|
||||
SW_CLOCK_CYCLE();
|
||||
}
|
||||
}
|
||||
PIN_SWDIO_OUT(1U);
|
||||
return ((uint8_t)ack);
|
||||
}
|
||||
|
||||
if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
|
||||
/* WAIT or FAULT response */
|
||||
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) {
|
||||
for (n = 32U+1U; n; n--) {
|
||||
SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */
|
||||
}
|
||||
}
|
||||
/* Turnaround */
|
||||
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
|
||||
SW_CLOCK_CYCLE();
|
||||
}
|
||||
PIN_SWDIO_OUT_ENABLE();
|
||||
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) {
|
||||
PIN_SWDIO_OUT(0U);
|
||||
for (n = 32U+1U; n; n--) {
|
||||
SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */
|
||||
}
|
||||
}
|
||||
PIN_SWDIO_OUT(1U);
|
||||
return ((uint8_t)ack);
|
||||
}
|
||||
|
||||
/* Protocol error */
|
||||
for (n = DAP_Data.swd_conf.turnaround + 32U + 1U; n; n--) {
|
||||
SW_CLOCK_CYCLE(); /* Back off data phase */
|
||||
}
|
||||
PIN_SWDIO_OUT_ENABLE();
|
||||
PIN_SWDIO_OUT(1U);
|
||||
return ((uint8_t)ack);
|
||||
}
|
||||
|
||||
|
||||
// SWD Transfer I/O
|
||||
// request: A[3:2] RnW APnDP
|
||||
// data: DATA[31:0]
|
||||
// return: ACK[2:0]
|
||||
uint8_t SWD_Transfer(uint32_t request, uint32_t *data) {
|
||||
switch (SWD_TransferSpeed) {
|
||||
case kTransfer_SPI:
|
||||
return SWD_Transfer_SPI(request, data);
|
||||
case kTransfer_GPIO_fast:
|
||||
return SWD_Transfer_GPIO(request, data, 0);
|
||||
case kTransfer_GPIO_normal:
|
||||
return SWD_Transfer_GPIO(request, data, 1);
|
||||
default:
|
||||
return SWD_Transfer_GPIO(request, data, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* (DAP_SWD != 0) */
|
||||
|
|
|
@ -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)
|
||||
|
@ -26,22 +49,35 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf)
|
|||
switch (count)
|
||||
{
|
||||
case 8:
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (0U << 8) | (0U << 16) | (0U << 24);
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (0U << 8) | (0U << 16) | (0U << 24);
|
||||
break;
|
||||
case 16:
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (0x000U << 16) | (0x000U << 24);
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (0x000U << 16) | (0x000U << 24);
|
||||
break;
|
||||
case 33: // 32bits data & 1 bit parity
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
DAP_SPI.data_buf[1] = (buf[4] << 0) | (0x000U << 8) | (0x000U << 16) | (0x000U << 24);
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
DAP_SPI.data_buf[1] = (buf[4] << 0) | (0x000U << 8) | (0x000U << 16) | (0x000U << 24);
|
||||
break;
|
||||
case 51: // for line reset
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
DAP_SPI.data_buf[1] = (buf[4] << 0) | (buf[5] << 8) | (buf[2] << 16) | (0x000U << 24);
|
||||
DAP_SPI.data_buf[0] = (buf[0] << 0) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
DAP_SPI.data_buf[1] = (buf[4] << 0) | (buf[5] << 8) | (buf[2] << 16) | (0x000U << 24);
|
||||
break;
|
||||
default:
|
||||
printf("[ERROR] Using unaligned data!\r\n");
|
||||
break;
|
||||
{
|
||||
uint32_t data_buf[2];
|
||||
uint8_t *pData = (uint8_t *)data_buf;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < div_round_up(count, 8); i++)
|
||||
{
|
||||
pData[i] = buf[i];
|
||||
}
|
||||
// last byte use mask:
|
||||
pData[i-1] = pData[i-1] & ((2U >> (count % 8)) - 1U);
|
||||
|
||||
DAP_SPI.data_buf[0] = data_buf[0];
|
||||
DAP_SPI.data_buf[1] = data_buf[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Start transmission
|
||||
|
@ -51,9 +87,44 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Step1: Packet Request
|
||||
*
|
||||
* @brief Read bits. LSB & little-endian
|
||||
* Note: No check. The pointer must be valid.
|
||||
* @param count Number of bits to be read (<= 64 bits, no length check)
|
||||
* @param buf Data Buf
|
||||
*/
|
||||
void DAP_SPI_ReadBits(const uint8_t count, uint8_t *buf) {
|
||||
int i;
|
||||
uint32_t data_buf[2];
|
||||
|
||||
uint8_t * pData = (uint8_t *)data_buf;
|
||||
|
||||
DAP_SPI.user.usr_mosi = 0;
|
||||
DAP_SPI.user.usr_miso = 1;
|
||||
|
||||
DAP_SPI.user1.usr_miso_bitlen = count - 1U;
|
||||
|
||||
// Start transmission
|
||||
DAP_SPI.cmd.usr = 1;
|
||||
// Wait for reading to complete
|
||||
while (DAP_SPI.cmd.usr);
|
||||
|
||||
data_buf[0] = DAP_SPI.data_buf[0];
|
||||
data_buf[1] = DAP_SPI.data_buf[1];
|
||||
|
||||
for (i = 0; i < div_round_up(count, 8); i++)
|
||||
{
|
||||
buf[i] = pData[i];
|
||||
}
|
||||
// last byte use mask:
|
||||
buf[i-1] = buf[i-1] & ((2 >> (count % 8)) - 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Step1: Packet Request
|
||||
*
|
||||
* @param packetHeaderData data from host
|
||||
* @param ack ack from target
|
||||
* @param TrnAfterACK num of trn after ack
|
||||
|
@ -70,9 +141,9 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *
|
|||
|
||||
// 1 bit Trn(Before ACK) + 3bits ACK + TrnAferACK - 1(prescribed)
|
||||
DAP_SPI.user1.usr_miso_bitlen = 1U + 3U + TrnAfterACK - 1U;
|
||||
|
||||
|
||||
// copy data to reg
|
||||
DAP_SPI.data_buf[0] = (packetHeaderData << 0) | (0U << 8) | (0U << 16) | (0U << 24);
|
||||
DAP_SPI.data_buf[0] = (packetHeaderData << 0) | (0U << 8) | (0U << 16) | (0U << 24);
|
||||
|
||||
// Start transmission
|
||||
DAP_SPI.cmd.usr = 1;
|
||||
|
@ -86,21 +157,20 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *
|
|||
|
||||
/**
|
||||
* @brief Step2: Read Data
|
||||
*
|
||||
*
|
||||
* @param resData data from target
|
||||
* @param resParity parity from target
|
||||
*/
|
||||
__FORCEINLINE void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity)
|
||||
__FORCEINLINE void DAP_SPI_Read_Data(uint32_t *resData, uint8_t *resParity)
|
||||
{
|
||||
uint64_t dataBuf;
|
||||
uint32_t *pU32Data = (uint32_t *)&dataBuf;
|
||||
|
||||
|
||||
DAP_SPI.user.usr_mosi = 0;
|
||||
DAP_SPI.user.usr_miso = 1;
|
||||
|
||||
// 1 bit Trn(End) + 3bits ACK + 32bis data + 1bit parity - 1(prescribed)
|
||||
DAP_SPI.user1.usr_miso_bitlen = 1U +32U + 1U - 1U;
|
||||
DAP_SPI.user1.usr_miso_bitlen = 1U + 32U + 1U - 1U;
|
||||
|
||||
// Start transmission
|
||||
DAP_SPI.cmd.usr = 1;
|
||||
|
@ -110,13 +180,13 @@ __FORCEINLINE void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity)
|
|||
pU32Data[0] = DAP_SPI.data_buf[0];
|
||||
pU32Data[1] = DAP_SPI.data_buf[1];
|
||||
|
||||
*resData = (dataBuf >> 0U) & 0xFFFFFFFFU ; // 32bits Response Data
|
||||
*resData = (dataBuf >> 0U) & 0xFFFFFFFFU; // 32bits Response Data
|
||||
*resParity = (dataBuf >> (0U + 32U)) & 1U; // 3bits ACK + 32bis data
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Step2: Write Data
|
||||
*
|
||||
*
|
||||
* @param data data from host
|
||||
* @param parity parity from host
|
||||
*/
|
||||
|
@ -126,7 +196,7 @@ __FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity)
|
|||
DAP_SPI.user.usr_miso = 0;
|
||||
|
||||
DAP_SPI.user1.usr_mosi_bitlen = 32U + 1U - 1U; // 32bis data + 1bit parity - 1(prescribed)
|
||||
|
||||
|
||||
// copy data to reg
|
||||
DAP_SPI.data_buf[0] = data;
|
||||
DAP_SPI.data_buf[1] = parity;
|
||||
|
@ -139,11 +209,12 @@ __FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity)
|
|||
|
||||
/**
|
||||
* @brief Generate Clock Cycle
|
||||
*
|
||||
*
|
||||
* @param num Cycle Num
|
||||
*/
|
||||
__FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num)
|
||||
{
|
||||
//// TODO: It may take long time to generate just one clock
|
||||
DAP_SPI.user.usr_mosi = 1;
|
||||
DAP_SPI.user.usr_miso = 0;
|
||||
DAP_SPI.user1.usr_mosi_bitlen = num - 1U;
|
||||
|
@ -157,7 +228,7 @@ __FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num)
|
|||
|
||||
/**
|
||||
* @brief Generate Protocol Error Cycle
|
||||
*
|
||||
*
|
||||
*/
|
||||
__FORCEINLINE void DAP_SPI_Protocol_Error_Read()
|
||||
{
|
||||
|
@ -167,7 +238,7 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Read()
|
|||
|
||||
DAP_SPI.data_buf[0] = 0xFFFFFFFFU;
|
||||
DAP_SPI.data_buf[1] = 0xFFFFFFFFU;
|
||||
|
||||
|
||||
DAP_SPI.cmd.usr = 1;
|
||||
while (DAP_SPI.cmd.usr);
|
||||
}
|
||||
|
@ -175,7 +246,7 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Read()
|
|||
|
||||
/**
|
||||
* @brief Generate Protocol Error Cycle
|
||||
*
|
||||
*
|
||||
*/
|
||||
__FORCEINLINE void DAP_SPI_Protocol_Error_Write()
|
||||
{
|
||||
|
@ -185,7 +256,7 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Write()
|
|||
|
||||
DAP_SPI.data_buf[0] = 0xFFFFFFFFU;
|
||||
DAP_SPI.data_buf[1] = 0xFFFFFFFFU;
|
||||
|
||||
|
||||
DAP_SPI.cmd.usr = 1;
|
||||
while (DAP_SPI.cmd.usr);
|
||||
}
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
* @file spi_switch.c
|
||||
* @author windowsair
|
||||
* @brief Switching between SPI mode and IO mode
|
||||
* @version 0.1
|
||||
* @date 2020-11-25
|
||||
*
|
||||
* @copyright Copyright (c) 2020
|
||||
*
|
||||
* @change: 2020-11-25 first version
|
||||
* 2021-2-11 Transmission mode switching test passed
|
||||
* @version 0.2
|
||||
* @date 2021-2-11
|
||||
*
|
||||
* @copyright Copyright (c) 2021
|
||||
*
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
|
||||
|
@ -31,7 +33,7 @@ typedef enum {
|
|||
|
||||
/**
|
||||
* @brief Initialize on first use
|
||||
*
|
||||
*
|
||||
*/
|
||||
void DAP_SPI_Init()
|
||||
{
|
||||
|
@ -59,7 +61,7 @@ void DAP_SPI_Init()
|
|||
DAP_SPI.ctrl2.mosi_delay_num = 0;
|
||||
DAP_SPI.ctrl2.miso_delay_num = 0;
|
||||
|
||||
// DIO & QIO SPI disable
|
||||
// DIO & QIO SPI disable
|
||||
DAP_SPI.user.fwrite_dual = false;
|
||||
DAP_SPI.user.fwrite_quad = false;
|
||||
DAP_SPI.user.fwrite_dio = false;
|
||||
|
@ -69,14 +71,14 @@ void DAP_SPI_Init()
|
|||
DAP_SPI.ctrl.fread_dio = false;
|
||||
DAP_SPI.ctrl.fread_qio = false;
|
||||
DAP_SPI.ctrl.fastrd_mode = true;
|
||||
|
||||
|
||||
// Enable soft reset
|
||||
DAP_SPI.slave.sync_reset = true;
|
||||
|
||||
// Set the clock polarity and phase CPOL = CPHA = 0
|
||||
DAP_SPI.pin.ck_idle_edge = 1; // HIGH while idle
|
||||
DAP_SPI.user.ck_out_edge = 0;
|
||||
|
||||
|
||||
|
||||
// Set data bit order
|
||||
DAP_SPI.ctrl.wr_bit_order = 1; // SWD -> LSB
|
||||
|
@ -88,7 +90,7 @@ void DAP_SPI_Init()
|
|||
// Set dummy
|
||||
DAP_SPI.user.usr_dummy = 0;
|
||||
|
||||
// Initialize HSPI IO
|
||||
// Initialize HSPI IO
|
||||
gpio_pin_reg_t pin_reg;
|
||||
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_HSPI_CLK); // GPIO14 is SPI CLK pin (Clock)
|
||||
|
@ -96,10 +98,10 @@ void DAP_SPI_Init()
|
|||
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(14));
|
||||
pin_reg.pullup = 1;
|
||||
WRITE_PERI_REG(GPIO_PIN_REG(14), pin_reg.val);
|
||||
|
||||
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out)
|
||||
GPIO.enable_w1ts |= (0x1 << 13);
|
||||
GPIO.pin[13].driver = 0; // PP Output or OD output
|
||||
GPIO.pin[13].driver = 0; // PP Output or OD output
|
||||
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13));
|
||||
pin_reg.pullup = 0;
|
||||
WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val);
|
||||
|
@ -110,6 +112,8 @@ void DAP_SPI_Init()
|
|||
pin_reg.pullup = 0;
|
||||
WRITE_PERI_REG(GPIO_PIN_REG(12), pin_reg.val);
|
||||
|
||||
|
||||
|
||||
// Set spi clk div
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK);
|
||||
|
||||
|
@ -124,35 +128,53 @@ void DAP_SPI_Init()
|
|||
DAP_SPI.user.usr_addr = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switch to GPIO
|
||||
* Note: You may be able to pull the pin high in SPI mode, though you cannot set it to LOW
|
||||
*/
|
||||
__FORCEINLINE void DAP_SPI_Deinit()
|
||||
{
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); // MOSI
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); // MISO
|
||||
|
||||
// disable MISO output connect
|
||||
GPIO.enable_w1tc |= (0x1 << 12);
|
||||
|
||||
gpio_pin_reg_t pin_reg;
|
||||
GPIO.enable_w1ts |= (0x1 << 13);
|
||||
GPIO.pin[13].driver = 1; // OD output
|
||||
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13));
|
||||
pin_reg.pullup = 0;
|
||||
WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Use SPI acclerate
|
||||
*
|
||||
*
|
||||
*/
|
||||
void DAP_SPI_Enable()
|
||||
{
|
||||
// may be unuse
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disable SPI
|
||||
*
|
||||
* Drive capability not yet known
|
||||
*/
|
||||
__FORCEINLINE void DAP_SPI_Disable()
|
||||
{
|
||||
DAP_SPI_Deinit();
|
||||
;
|
||||
//CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_MTCK_U, (PERIPHS_IO_MUX_FUNC << PERIPHS_IO_MUX_FUNC_S));
|
||||
// may be unuse
|
||||
// gpio_pin_reg_t pin_reg;
|
||||
// GPIO.enable_w1ts |= (0x1 << 13);
|
||||
// GPIO.pin[13].driver = 0; // OD Output
|
||||
// pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13));
|
||||
// pin_reg.pullup = 1;
|
||||
// WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val);
|
||||
}
|
||||
|
||||
__FORCEINLINE void DAP_SPI_Deinit()
|
||||
{
|
||||
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_MTCK_U, (PERIPHS_IO_MUX_FUNC << PERIPHS_IO_MUX_FUNC_S));
|
||||
|
||||
// may be unuse
|
||||
gpio_pin_reg_t pin_reg;
|
||||
GPIO.enable_w1ts |= (0x1 << 13);
|
||||
GPIO.pin[13].driver = 0; // OD Output
|
||||
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13));
|
||||
pin_reg.pullup = 1;
|
||||
WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val);
|
||||
}
|
Loading…
Reference in New Issue