0
0
Fork 0

feat: Try to use SPI to implement SWD protocol

This commit is contained in:
windowsair 2020-12-07 00:15:01 +08:00
parent 95e9ede1dd
commit a7165d69ab
14 changed files with 1273 additions and 765 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.vscode/
build/
tmp/

View File

@ -1,5 +1,6 @@
set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp8266/include/esp8266/ $ENV{IDF_PATH}//components/esp_ringbuf/include/")
set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c ./source/uart_modify.c")
set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c ./source/uart_modify.c ./source/spi_op.c ./source/spi_switch.c ./source/dap_utility.c")
register_component()

View File

@ -36,6 +36,8 @@
#include "timer_struct.h"
#include "esp8266/pin_mux_register.h"
#include "spi_switch.h"
//**************************************************************************************************
/**
\defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information
@ -64,7 +66,7 @@ This information includes:
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz
// This value is used to replace the largest 10MHZ speed clock in Keil
#define MAX_USER_CLOCK 10000000 ///< 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
@ -189,12 +191,13 @@ __STATIC_INLINE uint8_t DAP_GetSerNumString(char *str)
// Modify your pins here
// ATTENTION: DO NOT USE RTC GPIO16
#define PIN_SWDIO 4
#define PIN_SWCLK 5
#define PIN_TDO 13
#define PIN_TDI 12
#define PIN_SWDIO 12
#define PIN_SWDIO_MOSI 13 // SPI MOSI
#define PIN_SWCLK 14
#define PIN_TDO 4
#define PIN_TDI 0
#define PIN_nTRST 0 // optional
#define PIN_nRESET 14
#define PIN_nRESET 5
// LED_BUILTIN
#define PIN_LED_CONNECTED 2
// LED_BUILTIN
@ -300,18 +303,25 @@ __STATIC_INLINE void PORT_SWD_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);
// PIN_SWCLK -> OUTPUT
// PIN_SWDIO -> OUTPUT
// GPIO.enable_w1ts |= (0x1 << PIN_SWCLK);
// GPIO.pin[PIN_SWCLK].driver = 0;
// pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWCLK));
// pin_reg.pullup = 0;
// WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWCLK), pin_reg.val);
// GPIO.enable_w1ts |= (0x1 << PIN_SWDIO);
// GPIO.pin[PIN_SWDIO].driver = 0;
// pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWDIO));
// pin_reg.pullup = 0;
// WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWDIO), pin_reg.val);
DAP_SPI_Disable();
GPIO.out_w1tc |= (0x1 << PIN_SWCLK);
GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI);
// gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT);
GPIO.enable_w1tc |= (0x1 << PIN_TDO);
@ -360,11 +370,18 @@ __STATIC_INLINE void PORT_OFF(void)
// 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_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_SWDIO].driver = 0;
GPIO.enable_w1tc |= (0x1 << PIN_SWDIO);
GPIO.pin[PIN_TDO].driver = 0;
GPIO.enable_w1tc |= (0x1 << PIN_TDO);
@ -431,7 +448,7 @@ __STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void)
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void)
{
GPIO.out_w1ts |= (0x1 << PIN_SWDIO);
GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI);
}
/**
@ -441,7 +458,7 @@ __STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void)
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void)
{
GPIO.out_w1tc |= (0x1 << PIN_SWDIO);
GPIO.out_w1tc |= (0x1 << PIN_SWDIO_MOSI);
}
/**
@ -470,13 +487,13 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit)
if ((bit & 1U) == 1)
{
//set bit
GPIO.out_w1ts |= (0x1 << PIN_SWDIO);
GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI);
}
else
{
//reset bit
GPIO.out_w1tc |= (0x1 << PIN_SWDIO);
GPIO.out_w1tc |= (0x1 << PIN_SWDIO_MOSI);
}
}
@ -489,10 +506,12 @@ __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);
GPIO.pin[PIN_SWDIO].driver = 0;
// GPIO.enable_w1ts |= (0x1 << PIN_SWDIO_MOSI);
// GPIO.pin[PIN_SWDIO_MOSI].driver = 0;
do {}while (0);
}
/**
@ -505,8 +524,9 @@ __STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void)
// Need fast response
// set \ref gpio_set_dircetion -> INPUT
// esp8266 input is always connected
GPIO.enable_w1tc |= (0x1 << PIN_SWDIO);
GPIO.pin[PIN_SWDIO].driver = 0;
// GPIO.enable_w1tc |= (0x1 << PIN_SWDIO_MOSI);
// GPIO.pin[PIN_SWDIO_MOSI].driver = 0;
GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI);
}
// TDI Pin I/O ---------------------------------------------
@ -576,17 +596,7 @@ __STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void)
*/
__STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit)
{
// ////TODO: What does this mean? ? ?
// if ((bit & 1U) == 1)
// {
// //set bit
// GPIO.out_w1ts |= (0x1 << PIN_nTRST);
// }
// else
// {
// //reset bit
// GPIO.out_w1tc |= (0x1 << PIN_nTRST);
// }
// Vendor reset sequence
; // not available
}
@ -611,7 +621,8 @@ __STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void)
*/
__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit)
{
////TODO: What does this mean? ? ?
// Vendor reset sequence
//// FIXME: unavailable
if ((bit & 1U) == 1)
{
//set bit
@ -733,9 +744,13 @@ 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();
// 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_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);
@ -745,6 +760,8 @@ __STATIC_INLINE void DAP_SETUP(void)
LED_CONNECTED_OUT(0);
gpio_set_direction(PIN_LED_RUNNING, GPIO_MODE_DEF_OUTPUT);
LED_RUNNING_OUT(0);
PORT_OFF();
}
/** Reset Target Device with custom specific I/O pin or command sequence.

View File

@ -7,6 +7,9 @@
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline __attribute__((always_inline))
#endif
#ifndef __FORCEINLINE
#define __FORCEINLINE inline __attribute__((always_inline))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif

View File

@ -0,0 +1,33 @@
#ifndef __DAP_UTILITY_H__
#define __DAP_UTILITY_H__
#include <stdint.h>
#ifndef __STATIC_FORCEINLINE
#define __STATIC_FORCEINLINE static inline __attribute__((always_inline))
#endif
#ifndef __STATIC_INLINE
#define __STATIC_INLINE static inline __attribute__((always_inline))
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
extern const uint8_t kParityByteTable[256];
__STATIC_FORCEINLINE uint8_t ParityEvenUint32(uint32_t v)
{
v ^= v >> 16;
v ^= v >> 8;
v ^= v >> 4;
v &= 0xf;
return (0x6996 >> v) & 1;
}
__STATIC_FORCEINLINE uint8_t ParityEvenUint8(uint8_t v)
{
return kParityByteTable[v];
}
#endif

View File

@ -0,0 +1,19 @@
#ifndef __SPI_OP_H__
#define __SPI_OP_H__
#include <stdint.h>
void DAP_SPI_WriteBits(const uint8_t count, const 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);
void DAP_SPI_Write_Data(uint32_t data, uint8_t parity);
void DAP_SPI_Generate_Cycle(uint8_t num);
void DAP_SPI_Protocol_Error_Read();
void DAP_SPI_Protocol_Error_Write();
#endif

View File

@ -0,0 +1,10 @@
#ifndef __SPI_SWITCH_H__
#define __SPI_SWITCH_H__
void DAP_SPI_Init();
void DAP_SPI_Deinit();
void DAP_SPI_Enable();
void DAP_SPI_Disable();
#endif

View File

@ -28,6 +28,12 @@
#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
@ -54,7 +60,8 @@
PIN_SWCLK_SET(); \
PIN_DELAY()
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
//#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
#define PIN_DELAY() PIN_DELAY_FAST()
// Generate SWJ Sequence
@ -63,25 +70,13 @@
// return: none
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
void SWJ_Sequence (uint32_t count, const uint8_t *data) {
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--;
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
@ -133,131 +128,175 @@ 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]
#define SWD_TransferFunction(speed) /**/ \
//// 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) { \
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_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);
}

View File

@ -0,0 +1,10 @@
#include "dap_utility.h"
const uint8_t kParityByteTable[256] =
{
#define P2(n) n, n^1, n^1, n
#define P4(n) P2(n), P2(n^1), P2(n^1), P2(n)
#define P6(n) P4(n), P4(n^1), P4(n^1), P4(n)
P6(0), P6(1), P6(1), P6(0)
};

View File

@ -0,0 +1,191 @@
#include <stdio.h>
#include "esp8266/spi_struct.h"
#include "cmsis_compiler.h"
#include "spi_op.h"
#define DAP_SPI SPI1
/**
* @brief Write bits. LSB & little-endian
* Note: No check. The pointer must be valid.
* @param count Number of bits to be written
* @param buf Data Buf
*/
void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf)
{
DAP_SPI.user.usr_command = 0;
DAP_SPI.user.usr_addr = 0;
// have data to send
DAP_SPI.user.usr_mosi = 1;
DAP_SPI.user1.usr_mosi_bitlen = count - 1;
// copy data to reg
switch (count)
{
case 8:
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);
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);
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);
break;
default:
printf("[ERROR] Using unaligned data!\r\n");
break;
}
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr);
}
/**
* @brief Step1: Packet Request
*
* @param packetHeaderData data from host
* @param ack ack from target
* @param TrnAfterACK num of trn after ack
*/
__FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *ack, uint8_t TrnAfterACK)
{
uint32_t dataBuf;
// have data to send
DAP_SPI.user.usr_mosi = 1;
DAP_SPI.user1.usr_mosi_bitlen = 8 - 1;
DAP_SPI.user.usr_miso = 1;
// 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);
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr);
dataBuf = DAP_SPI.data_buf[0];
*ack = (dataBuf >> 1) & 0b111;
}
/**
* @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)
{
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;
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr);
pU32Data[0] = DAP_SPI.data_buf[0];
pU32Data[1] = DAP_SPI.data_buf[1];
*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
*/
__FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity)
{
DAP_SPI.user.usr_mosi = 1;
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;
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr);
}
/**
* @brief Generate Clock Cycle
*
* @param num Cycle Num
*/
__FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num)
{
DAP_SPI.user.usr_mosi = 1;
DAP_SPI.user.usr_miso = 0;
DAP_SPI.user1.usr_mosi_bitlen = num - 1U;
DAP_SPI.data_buf[0] = 0x00000000U;
DAP_SPI.cmd.usr = 1;
while (DAP_SPI.cmd.usr);
}
/**
* @brief Generate Protocol Error Cycle
*
*/
__FORCEINLINE void DAP_SPI_Protocol_Error_Read()
{
DAP_SPI.user.usr_mosi = 1;
DAP_SPI.user.usr_miso = 0;
DAP_SPI.user1.usr_mosi_bitlen = 32U + 1U - 1; // 32bit ignore data + 1 bit - 1(prescribed)
DAP_SPI.data_buf[0] = 0xFFFFFFFFU;
DAP_SPI.data_buf[1] = 0xFFFFFFFFU;
DAP_SPI.cmd.usr = 1;
while (DAP_SPI.cmd.usr);
}
/**
* @brief Generate Protocol Error Cycle
*
*/
__FORCEINLINE void DAP_SPI_Protocol_Error_Write()
{
DAP_SPI.user.usr_mosi = 1;
DAP_SPI.user.usr_miso = 0;
DAP_SPI.user1.usr_mosi_bitlen = 1U + 32U + 1U - 1; // 1bit Trn + 32bit ignore data + 1 bit - 1(prescribed)
DAP_SPI.data_buf[0] = 0xFFFFFFFFU;
DAP_SPI.data_buf[1] = 0xFFFFFFFFU;
DAP_SPI.cmd.usr = 1;
while (DAP_SPI.cmd.usr);
}

View File

@ -0,0 +1,158 @@
/**
* @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
*
*/
#include <stdbool.h>
#include "esp8266/spi_struct.h"
#include "esp8266/pin_mux_register.h"
#include "esp8266/gpio_struct.h"
#include "cmsis_compiler.h"
#include "spi_switch.h"
#define DAP_SPI SPI1
#define ENTER_CRITICAL() portENTER_CRITICAL()
#define EXIT_CRITICAL() portEXIT_CRITICAL()
typedef enum {
SPI_40MHz_DIV = 2,
// SPI_80MHz_DIV = 1, //// FIXME: high speed clock
} spi_clk_div_t;
/**
* @brief Initialize on first use
*
*/
void DAP_SPI_Init()
{
// Disable flash operation mode
DAP_SPI.user.flash_mode = false;
// Set to Master mode
DAP_SPI.pin.slave_mode = false;
DAP_SPI.slave.slave_mode = false;
// Master uses the entire hardware buffer to improve transmission speed
// If the following fields are enabled, only a part of the buffer is used
DAP_SPI.user.usr_mosi_highpart = false;
DAP_SPI.user.usr_miso_highpart = false;
// Disable cs pin
DAP_SPI.user.cs_setup = false;
DAP_SPI.user.cs_hold = false;
// Duplex transmit
DAP_SPI.user.duplex = true;
// SCLK delay setting
DAP_SPI.user.ck_i_edge = true;
DAP_SPI.ctrl2.mosi_delay_num = 0;
DAP_SPI.ctrl2.miso_delay_num = 0;
// DIO & QIO SPI disable
DAP_SPI.user.fwrite_dual = false;
DAP_SPI.user.fwrite_quad = false;
DAP_SPI.user.fwrite_dio = false;
DAP_SPI.user.fwrite_qio = false;
DAP_SPI.ctrl.fread_dual = false;
DAP_SPI.ctrl.fread_quad = false;
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
DAP_SPI.ctrl.rd_bit_order = 1; // SWD -> LSB
// Set data byte order
DAP_SPI.user.wr_byte_order = 0; // SWD -> litte_endian && Risc V -> litte_endian
DAP_SPI.user.rd_byte_order = 0; // SWD -> litte_endian && Risc V -> litte_endian
// Set dummy
DAP_SPI.user.usr_dummy = 0;
// 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)
GPIO.enable_w1ts |= (0x1 << 14); // PP Output
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
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13));
pin_reg.pullup = 0;
WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_HSPIQ_MISO); // GPIO12 is SPI MISO pin (Master Data In)
// esp8266 in is always connected
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(12));
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);
DAP_SPI.clock.clk_equ_sysclk = false;
DAP_SPI.clock.clkdiv_pre = 0;
DAP_SPI.clock.clkcnt_n = SPI_40MHz_DIV - 1;
DAP_SPI.clock.clkcnt_h = SPI_40MHz_DIV / 2 - 1;
DAP_SPI.clock.clkcnt_l = SPI_40MHz_DIV - 1;
// Do not use command and addr
DAP_SPI.user.usr_command = 0;
DAP_SPI.user.usr_addr = 0;
}
/**
* @brief Use SPI acclerate
*
*/
void DAP_SPI_Enable()
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out)
}
/**
* @brief Disable SPI
*
*/
__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));
// 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);
}

View File

@ -29,6 +29,9 @@
extern int kSock;
extern TaskHandle_t kDAPTaskHandle;
int kRestartDAPHandle = 0;
////TODO: Merge this
#define DAP_PACKET_SIZE 255
@ -160,6 +163,22 @@ void DAP_Thread(void *argument)
while (1)
{
if (kRestartDAPHandle)
{
vRingbufferDelete(dap_dataIN_handle);
vRingbufferDelete(dap_dataOUT_handle);
dap_dataIN_handle = dap_dataOUT_handle = NULL;
dap_dataIN_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF);
dap_dataOUT_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF);
if (dap_dataIN_handle == NULL || dap_dataIN_handle == NULL)
{
os_printf("Can not create DAP ringbuf/mux!\r\n");
vTaskDelete(NULL);
}
kRestartDAPHandle = 0;
}
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
packetSize = 0;
item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize,

View File

@ -134,8 +134,8 @@ void app_main()
DAP_Setup(); // DAP Setup
xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL);
xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 20, NULL);
xTaskCreate(DAP_Thread, "DAP_Task", 2048, NULL, 22, &kDAPTaskHandle);
xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 14, NULL);
xTaskCreate(DAP_Thread, "DAP_Task", 2048, NULL, 10, &kDAPTaskHandle);
// SWO Trace Task
//xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL);
//xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL);

View File

@ -29,6 +29,9 @@
#include "wifi_configuration.h"
#include "usbip_server.h"
extern TaskHandle_t kDAPTaskHandle;
extern int kRestartDAPHandle;
uint8_t kState = ACCEPTING;
int kSock = -1;
@ -158,6 +161,10 @@ void tcp_server_task(void *pvParameters)
if (kState == EMULATING)
kState = ACCEPTING;
// Restart DAP Handle
kRestartDAPHandle = 1;
xTaskNotifyGive(kDAPTaskHandle);
//shutdown(listen_sock, 0);
//close(listen_sock);
//vTaskDelay(5);