From a7165d69ab9ff93b9a287f485aa0b04fbfcb0bfe Mon Sep 17 00:00:00 2001 From: windowsair Date: Mon, 7 Dec 2020 00:15:01 +0800 Subject: [PATCH 1/4] feat: Try to use SPI to implement SWD protocol --- .gitignore | 1 + components/DAP/CMakeLists.txt | 3 +- components/DAP/config/DAP_config.h | 107 +++-- components/DAP/include/cmsis_compiler.h | 3 + components/DAP/include/dap_utility.h | 33 ++ components/DAP/include/spi_op.h | 19 + components/DAP/include/spi_switch.h | 10 + components/DAP/source/SW_DP.c | 325 ++++++++------ components/DAP/source/dap_utility.c | 10 + components/DAP/source/spi_op.c | 191 ++++++++ components/DAP/source/spi_switch.c | 158 +++++++ main/DAP_handle.c | 553 ++++++++++++------------ main/main.c | 284 ++++++------ main/tcp_server.c | 341 ++++++++------- 14 files changed, 1273 insertions(+), 765 deletions(-) create mode 100644 components/DAP/include/dap_utility.h create mode 100644 components/DAP/include/spi_op.h create mode 100644 components/DAP/include/spi_switch.h create mode 100644 components/DAP/source/dap_utility.c create mode 100644 components/DAP/source/spi_op.c create mode 100644 components/DAP/source/spi_switch.c diff --git a/.gitignore b/.gitignore index e524d79..9a47b5a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode/ build/ +tmp/ \ No newline at end of file diff --git a/components/DAP/CMakeLists.txt b/components/DAP/CMakeLists.txt index 3eec5a2..c18752a 100644 --- a/components/DAP/CMakeLists.txt +++ b/components/DAP/CMakeLists.txt @@ -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() \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index 7121a2e..f502fb6 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -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); + + // 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); @@ -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. diff --git a/components/DAP/include/cmsis_compiler.h b/components/DAP/include/cmsis_compiler.h index aafbe21..9d032bb 100644 --- a/components/DAP/include/cmsis_compiler.h +++ b/components/DAP/include/cmsis_compiler.h @@ -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 diff --git a/components/DAP/include/dap_utility.h b/components/DAP/include/dap_utility.h new file mode 100644 index 0000000..ee25c6f --- /dev/null +++ b/components/DAP/include/dap_utility.h @@ -0,0 +1,33 @@ +#ifndef __DAP_UTILITY_H__ +#define __DAP_UTILITY_H__ + +#include + +#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 diff --git a/components/DAP/include/spi_op.h b/components/DAP/include/spi_op.h new file mode 100644 index 0000000..abfe12d --- /dev/null +++ b/components/DAP/include/spi_op.h @@ -0,0 +1,19 @@ +#ifndef __SPI_OP_H__ +#define __SPI_OP_H__ + +#include + + +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 diff --git a/components/DAP/include/spi_switch.h b/components/DAP/include/spi_switch.h new file mode 100644 index 0000000..3b7eb80 --- /dev/null +++ b/components/DAP/include/spi_switch.h @@ -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 diff --git a/components/DAP/source/SW_DP.c b/components/DAP/source/SW_DP.c index 803cf42..87de13e 100644 --- a/components/DAP/source/SW_DP.c +++ b/components/DAP/source/SW_DP.c @@ -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); + + + } diff --git a/components/DAP/source/dap_utility.c b/components/DAP/source/dap_utility.c new file mode 100644 index 0000000..94c0381 --- /dev/null +++ b/components/DAP/source/dap_utility.c @@ -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) +}; diff --git a/components/DAP/source/spi_op.c b/components/DAP/source/spi_op.c new file mode 100644 index 0000000..8deefaf --- /dev/null +++ b/components/DAP/source/spi_op.c @@ -0,0 +1,191 @@ +#include + +#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); +} diff --git a/components/DAP/source/spi_switch.c b/components/DAP/source/spi_switch.c new file mode 100644 index 0000000..855ecc4 --- /dev/null +++ b/components/DAP/source/spi_switch.c @@ -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 + +#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); +} \ No newline at end of file diff --git a/main/DAP_handle.c b/main/DAP_handle.c index 03c45f3..3efb856 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -1,268 +1,287 @@ -/** - * @file DAP_handle.c - * @brief Handle DAP packets and transaction push - * @version 0.3 - * @date 2020-02-04 first version - * 2020-11-11 support WinUSB mode - * - * @copyright Copyright (c) 2020 - * - */ - -#include -#include -#include "usbip_server.h" -#include "DAP_handle.h" -#include "DAP.h" -#include "esp_libc.h" -#include "USBd_config.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/ringbuf.h" -#include "freertos/semphr.h" - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -extern int kSock; -extern TaskHandle_t kDAPTaskHandle; -////TODO: Merge this -#define DAP_PACKET_SIZE 255 - -#if (USE_WINUSB == 1) -typedef struct -{ - uint32_t length; - uint8_t buf[DAP_PACKET_SIZE]; -} DAPPacetDataType; -#else -typedef struct -{ - uint8_t buf[DAP_PACKET_SIZE]; -} DAPPacetDataType; -#endif - - -#define DAP_HANDLE_SIZE (sizeof(DAPPacetDataType)) - -static DAPPacetDataType DAPDataProcessed; -static int dap_respond = 0; - - -// SWO Trace -static int swo_trace_respond = 0; -static uint8_t *swo_data_to_send; -static uint32_t num_swo_data; - -static RingbufHandle_t dap_dataIN_handle = NULL; -static RingbufHandle_t dap_dataOUT_handle = NULL; -static SemaphoreHandle_t data_response_mux = NULL; - -static void unpack(void *data, int size); - -void handle_dap_data_request(usbip_stage2_header *header, uint32_t length) -{ - uint8_t *data_in = (uint8_t *)header; - data_in = &(data_in[sizeof(usbip_stage2_header)]); - // Point to the beginning of the URB packet - -#if (USE_WINUSB == 1) - send_stage2_submit(header, 0, 0); - - // always send constant size buf -> cuz we don't care about the IN packet size - // and to unify the style, we set aside the length of the section - xRingbufferSend(dap_dataIN_handle, data_in - sizeof(uint32_t), DAP_HANDLE_SIZE, portMAX_DELAY); - xTaskNotifyGive(kDAPTaskHandle); - -#else - send_stage2_submit(header, 0, 0); - - xRingbufferSend(dap_dataIN_handle, data_in, DAP_HANDLE_SIZE, portMAX_DELAY); - xTaskNotifyGive(kDAPTaskHandle); - -#endif - - // dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); - // //handle_dap_data_response(header); - // send_stage2_submit(header, 0, 0); -} - -void handle_dap_data_response(usbip_stage2_header *header) -{ - return; - // int resLength = dap_respond & 0xFFFF; - // if (resLength) - // { - - // send_stage2_submit_data(header, 0, (void *)DAPDataProcessed.buf, resLength); - // dap_respond = 0; - // } - // else - // { - // send_stage2_submit(header, 0, 0); - // } -} - -void handle_swo_trace_response(usbip_stage2_header *header) -{ - // TODO: - send_stage2_submit(header, 0, 0); - return; - - if (swo_trace_respond) - { - swo_trace_respond = 0; - //send_stage2_submit_data(header, 0, (void *)DAPDataProcessed.buf, DAP_PACKET_SIZE); - } - else - { - send_stage2_submit(header, 0, 0); - } -} - -// SWO Data Queue Transfer -// buf: pointer to buffer with data -// num: number of bytes to transfer -void SWO_QueueTransfer(uint8_t *buf, uint32_t num) -{ - swo_data_to_send = buf; - num_swo_data = num; - swo_trace_respond = 1; -} - -// SWO Data Abort Transfer -void SWO_AbortTransfer(void) -{ - //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U)); - ////TODO: unlink might be useful ... -} - -void DAP_Thread(void *argument) -{ - dap_dataIN_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF); - dap_dataOUT_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF); - data_response_mux = xSemaphoreCreateMutex(); - size_t packetSize; - int resLength; - DAPPacetDataType *item; - - if (dap_dataIN_handle == NULL || dap_dataIN_handle == NULL || - data_response_mux == NULL) - { - os_printf("Can not create DAP ringbuf/mux!\r\n"); - vTaskDelete(NULL); - } - for (;;) - { - - while (1) - { - ulTaskNotifyTake(pdFALSE, portMAX_DELAY); - packetSize = 0; - item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize, - (1 / portTICK_RATE_MS), DAP_HANDLE_SIZE); - if (packetSize == 0) - { - break; - } - - else if (packetSize < DAP_HANDLE_SIZE) - { - os_printf("Wrong data in packet size:%d , data in remain: %d\r\n", packetSize, (int)xRingbufferGetMaxItemSize(dap_dataIN_handle)); - vRingbufferReturnItem(dap_dataIN_handle, (void *)item); - break; - // This may not happen because there is a semaphore acquisition - } - - if (item->buf[0] == ID_DAP_QueueCommands) - { - item->buf[0] = ID_DAP_ExecuteCommands; - } - - resLength = DAP_ProcessCommand((uint8_t *)item->buf, (uint8_t *)DAPDataProcessed.buf); // use first 4 byte to save length - resLength &= 0xFFFF; // res length in lower 16 bits - - vRingbufferReturnItem(dap_dataIN_handle, (void *)item); // process done. - - // now prepare to reply - #if (USE_WINUSB == 1) - DAPDataProcessed.length = resLength; - #endif - xRingbufferSend(dap_dataOUT_handle, (void *)&DAPDataProcessed, DAP_HANDLE_SIZE, portMAX_DELAY); - - if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) - { - ++dap_respond; - xSemaphoreGive(data_response_mux); - } - } - } -} - -int fast_reply(uint8_t *buf, uint32_t length) -{ - if (length == 48 && buf[3] == 1 && buf[15] == 1 && buf[19] == 1) - { - if (dap_respond > 0) - { - DAPPacetDataType *item; - size_t packetSize = 0; - item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataOUT_handle, &packetSize, - (10 / portTICK_RATE_MS), DAP_HANDLE_SIZE); - if (packetSize == DAP_HANDLE_SIZE) - { - unpack((uint32_t *)buf, sizeof(usbip_stage2_header)); - - #if (USE_WINUSB == 1) - uint32_t resLength = item->length; - send_stage2_submit_data((usbip_stage2_header *)buf, 0, item->buf, resLength); - #else - send_stage2_submit_data((usbip_stage2_header *)buf, 0, item->buf, DAP_HANDLE_SIZE); - #endif - - - if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) - { - --dap_respond; - xSemaphoreGive(data_response_mux); - } - - vRingbufferReturnItem(dap_dataOUT_handle, (void *)item); - return 1; - } - else if (packetSize > 0) - { - os_printf("Wrong data out packet size:%d!\r\n", packetSize); - } - ////TODO: fast reply - } - else - { - //// TODO: ep0 dir 0 ? - buf[0x3] = 0x3; // command - buf[0xF] = 0; // direction - buf[0x16] = 0; - buf[0x17] = 0; - buf[27] = 0; - buf[39] = 0; - send(kSock, buf, 48, 0); - return 1; - } - } - return 0; -} - -static void unpack(void *data, int size) -{ - // Ignore the setup field - int sz = (size / sizeof(uint32_t)) - 2; - uint32_t *ptr = (uint32_t *)data; - - for (int i = 0; i < sz; i++) - { - ptr[i] = ntohl(ptr[i]); - } +/** + * @file DAP_handle.c + * @brief Handle DAP packets and transaction push + * @version 0.3 + * @date 2020-02-04 first version + * 2020-11-11 support WinUSB mode + * + * @copyright Copyright (c) 2020 + * + */ + +#include +#include +#include "usbip_server.h" +#include "DAP_handle.h" +#include "DAP.h" +#include "esp_libc.h" +#include "USBd_config.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/ringbuf.h" +#include "freertos/semphr.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +extern int kSock; +extern TaskHandle_t kDAPTaskHandle; + +int kRestartDAPHandle = 0; + +////TODO: Merge this +#define DAP_PACKET_SIZE 255 + +#if (USE_WINUSB == 1) +typedef struct +{ + uint32_t length; + uint8_t buf[DAP_PACKET_SIZE]; +} DAPPacetDataType; +#else +typedef struct +{ + uint8_t buf[DAP_PACKET_SIZE]; +} DAPPacetDataType; +#endif + + +#define DAP_HANDLE_SIZE (sizeof(DAPPacetDataType)) + +static DAPPacetDataType DAPDataProcessed; +static int dap_respond = 0; + + +// SWO Trace +static int swo_trace_respond = 0; +static uint8_t *swo_data_to_send; +static uint32_t num_swo_data; + +static RingbufHandle_t dap_dataIN_handle = NULL; +static RingbufHandle_t dap_dataOUT_handle = NULL; +static SemaphoreHandle_t data_response_mux = NULL; + +static void unpack(void *data, int size); + +void handle_dap_data_request(usbip_stage2_header *header, uint32_t length) +{ + uint8_t *data_in = (uint8_t *)header; + data_in = &(data_in[sizeof(usbip_stage2_header)]); + // Point to the beginning of the URB packet + +#if (USE_WINUSB == 1) + send_stage2_submit(header, 0, 0); + + // always send constant size buf -> cuz we don't care about the IN packet size + // and to unify the style, we set aside the length of the section + xRingbufferSend(dap_dataIN_handle, data_in - sizeof(uint32_t), DAP_HANDLE_SIZE, portMAX_DELAY); + xTaskNotifyGive(kDAPTaskHandle); + +#else + send_stage2_submit(header, 0, 0); + + xRingbufferSend(dap_dataIN_handle, data_in, DAP_HANDLE_SIZE, portMAX_DELAY); + xTaskNotifyGive(kDAPTaskHandle); + +#endif + + // dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); + // //handle_dap_data_response(header); + // send_stage2_submit(header, 0, 0); +} + +void handle_dap_data_response(usbip_stage2_header *header) +{ + return; + // int resLength = dap_respond & 0xFFFF; + // if (resLength) + // { + + // send_stage2_submit_data(header, 0, (void *)DAPDataProcessed.buf, resLength); + // dap_respond = 0; + // } + // else + // { + // send_stage2_submit(header, 0, 0); + // } +} + +void handle_swo_trace_response(usbip_stage2_header *header) +{ + // TODO: + send_stage2_submit(header, 0, 0); + return; + + if (swo_trace_respond) + { + swo_trace_respond = 0; + //send_stage2_submit_data(header, 0, (void *)DAPDataProcessed.buf, DAP_PACKET_SIZE); + } + else + { + send_stage2_submit(header, 0, 0); + } +} + +// SWO Data Queue Transfer +// buf: pointer to buffer with data +// num: number of bytes to transfer +void SWO_QueueTransfer(uint8_t *buf, uint32_t num) +{ + swo_data_to_send = buf; + num_swo_data = num; + swo_trace_respond = 1; +} + +// SWO Data Abort Transfer +void SWO_AbortTransfer(void) +{ + //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U)); + ////TODO: unlink might be useful ... +} + +void DAP_Thread(void *argument) +{ + dap_dataIN_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF); + dap_dataOUT_handle = xRingbufferCreate(DAP_HANDLE_SIZE * 20, RINGBUF_TYPE_BYTEBUF); + data_response_mux = xSemaphoreCreateMutex(); + size_t packetSize; + int resLength; + DAPPacetDataType *item; + + if (dap_dataIN_handle == NULL || dap_dataIN_handle == NULL || + data_response_mux == NULL) + { + os_printf("Can not create DAP ringbuf/mux!\r\n"); + vTaskDelete(NULL); + } + for (;;) + { + + 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, + (1 / portTICK_RATE_MS), DAP_HANDLE_SIZE); + if (packetSize == 0) + { + break; + } + + else if (packetSize < DAP_HANDLE_SIZE) + { + os_printf("Wrong data in packet size:%d , data in remain: %d\r\n", packetSize, (int)xRingbufferGetMaxItemSize(dap_dataIN_handle)); + vRingbufferReturnItem(dap_dataIN_handle, (void *)item); + break; + // This may not happen because there is a semaphore acquisition + } + + if (item->buf[0] == ID_DAP_QueueCommands) + { + item->buf[0] = ID_DAP_ExecuteCommands; + } + + resLength = DAP_ProcessCommand((uint8_t *)item->buf, (uint8_t *)DAPDataProcessed.buf); // use first 4 byte to save length + resLength &= 0xFFFF; // res length in lower 16 bits + + vRingbufferReturnItem(dap_dataIN_handle, (void *)item); // process done. + + // now prepare to reply + #if (USE_WINUSB == 1) + DAPDataProcessed.length = resLength; + #endif + xRingbufferSend(dap_dataOUT_handle, (void *)&DAPDataProcessed, DAP_HANDLE_SIZE, portMAX_DELAY); + + if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) + { + ++dap_respond; + xSemaphoreGive(data_response_mux); + } + } + } +} + +int fast_reply(uint8_t *buf, uint32_t length) +{ + if (length == 48 && buf[3] == 1 && buf[15] == 1 && buf[19] == 1) + { + if (dap_respond > 0) + { + DAPPacetDataType *item; + size_t packetSize = 0; + item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataOUT_handle, &packetSize, + (10 / portTICK_RATE_MS), DAP_HANDLE_SIZE); + if (packetSize == DAP_HANDLE_SIZE) + { + unpack((uint32_t *)buf, sizeof(usbip_stage2_header)); + + #if (USE_WINUSB == 1) + uint32_t resLength = item->length; + send_stage2_submit_data((usbip_stage2_header *)buf, 0, item->buf, resLength); + #else + send_stage2_submit_data((usbip_stage2_header *)buf, 0, item->buf, DAP_HANDLE_SIZE); + #endif + + + if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) + { + --dap_respond; + xSemaphoreGive(data_response_mux); + } + + vRingbufferReturnItem(dap_dataOUT_handle, (void *)item); + return 1; + } + else if (packetSize > 0) + { + os_printf("Wrong data out packet size:%d!\r\n", packetSize); + } + ////TODO: fast reply + } + else + { + //// TODO: ep0 dir 0 ? + buf[0x3] = 0x3; // command + buf[0xF] = 0; // direction + buf[0x16] = 0; + buf[0x17] = 0; + buf[27] = 0; + buf[39] = 0; + send(kSock, buf, 48, 0); + return 1; + } + } + return 0; +} + +static void unpack(void *data, int size) +{ + // Ignore the setup field + int sz = (size / sizeof(uint32_t)) - 2; + uint32_t *ptr = (uint32_t *)data; + + for (int i = 0; i < sz; i++) + { + ptr[i] = ntohl(ptr[i]); + } } \ No newline at end of file diff --git a/main/main.c b/main/main.c index f70a663..a8c3e85 100644 --- a/main/main.c +++ b/main/main.c @@ -1,142 +1,142 @@ -/* BSD Socket API Example - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -#include "tcp_server.h" -#include "timer.h" -#include "wifi_configuration.h" - - -extern void SWO_Thread(void *argument); -extern void usart_monitor_task(void *argument); -extern void DAP_Setup(void); -extern void DAP_Thread(void *argument); - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; -TaskHandle_t kDAPTaskHandle = NULL; - -const int IPV4_GOTIP_BIT = BIT0; -#ifdef CONFIG_EXAMPLE_IPV6 -const int IPV6_GOTIP_BIT = BIT1; -#endif - - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) - { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - os_printf("SYSTEM_EVENT_STA_START\r\n"); - break; - case SYSTEM_EVENT_STA_CONNECTED: -#ifdef CONFIG_EXAMPLE_IPV6 - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); -#endif - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - os_printf("SYSTEM EVENT STA GOT IP : %s\r\n", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); - break; - case SYSTEM_EVENT_STA_DISCONNECTED: - os_printf("Disconnect reason : %d\r\n", info->disconnected.reason); - if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) - { - /*Switch to 802.11 bgn mode */ - esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); - } - esp_wifi_connect(); - xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); -#endif - break; - case SYSTEM_EVENT_AP_STA_GOT_IP6: -#ifdef CONFIG_EXAMPLE_IPV6 - xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); - os_printf("SYSTEM_EVENT_STA_GOT_IP6\r\n"); - - char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); - os_printf("IPv6: %s\r\n", ip6); -#endif - default: - break; - } - return ESP_OK; -} - -static void initialise_wifi(void) -{ - tcpip_adapter_init(); - wifi_event_group = xEventGroupCreate(); - - ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); - wifi_config_t wifi_config = { - .sta = { - .ssid = WIFI_SSID, - .password = WIFI_PASS, - }, - }; - os_printf("Setting WiFi configuration SSID %s...\r\n", wifi_config.sta.ssid); - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_start()); -} - -static void wait_for_ip() -{ -#ifdef CONFIG_EXAMPLE_IPV6 - uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT; -#else - uint32_t bits = IPV4_GOTIP_BIT; -#endif - - os_printf("Waiting for AP connection...\r\n"); - xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); - os_printf("Connected to AP\r\n"); -} - - -void app_main() -{ - ESP_ERROR_CHECK(nvs_flash_init()); - initialise_wifi(); - wait_for_ip(); - 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); - // SWO Trace Task - //xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); - //xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); -} +/* BSD Socket API Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +#include "tcp_server.h" +#include "timer.h" +#include "wifi_configuration.h" + + +extern void SWO_Thread(void *argument); +extern void usart_monitor_task(void *argument); +extern void DAP_Setup(void); +extern void DAP_Thread(void *argument); + +/* FreeRTOS event group to signal when we are connected & ready to make a request */ +static EventGroupHandle_t wifi_event_group; +TaskHandle_t kDAPTaskHandle = NULL; + +const int IPV4_GOTIP_BIT = BIT0; +#ifdef CONFIG_EXAMPLE_IPV6 +const int IPV6_GOTIP_BIT = BIT1; +#endif + + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + /* For accessing reason codes in case of disconnection */ + system_event_info_t *info = &event->event_info; + + switch (event->event_id) + { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + os_printf("SYSTEM_EVENT_STA_START\r\n"); + break; + case SYSTEM_EVENT_STA_CONNECTED: +#ifdef CONFIG_EXAMPLE_IPV6 + /* enable ipv6 */ + tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); +#endif + break; + case SYSTEM_EVENT_STA_GOT_IP: + xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); + os_printf("SYSTEM EVENT STA GOT IP : %s\r\n", ip4addr_ntoa(&event->event_info.got_ip.ip_info.ip)); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + os_printf("Disconnect reason : %d\r\n", info->disconnected.reason); + if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) + { + /*Switch to 802.11 bgn mode */ + esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); + } + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, IPV4_GOTIP_BIT); +#ifdef CONFIG_EXAMPLE_IPV6 + xEventGroupClearBits(wifi_event_group, IPV6_GOTIP_BIT); +#endif + break; + case SYSTEM_EVENT_AP_STA_GOT_IP6: +#ifdef CONFIG_EXAMPLE_IPV6 + xEventGroupSetBits(wifi_event_group, IPV6_GOTIP_BIT); + os_printf("SYSTEM_EVENT_STA_GOT_IP6\r\n"); + + char *ip6 = ip6addr_ntoa(&event->event_info.got_ip6.ip6_info.ip); + os_printf("IPv6: %s\r\n", ip6); +#endif + default: + break; + } + return ESP_OK; +} + +static void initialise_wifi(void) +{ + tcpip_adapter_init(); + wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + wifi_config_t wifi_config = { + .sta = { + .ssid = WIFI_SSID, + .password = WIFI_PASS, + }, + }; + os_printf("Setting WiFi configuration SSID %s...\r\n", wifi_config.sta.ssid); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); +} + +static void wait_for_ip() +{ +#ifdef CONFIG_EXAMPLE_IPV6 + uint32_t bits = IPV4_GOTIP_BIT | IPV6_GOTIP_BIT; +#else + uint32_t bits = IPV4_GOTIP_BIT; +#endif + + os_printf("Waiting for AP connection...\r\n"); + xEventGroupWaitBits(wifi_event_group, bits, false, true, portMAX_DELAY); + os_printf("Connected to AP\r\n"); +} + + +void app_main() +{ + ESP_ERROR_CHECK(nvs_flash_init()); + initialise_wifi(); + wait_for_ip(); + DAP_Setup(); // DAP Setup + + xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL); + 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); +} diff --git a/main/tcp_server.c b/main/tcp_server.c index 8c481b1..aee67c0 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -1,168 +1,175 @@ -/** - * @file tcp_server.c - * @brief Handle main tcp tasks - * @version 0.1 - * @date 2020-01-22 - * - * @copyright Copyright (c) 2020 - * - */ -#include "tcp_server.h" - -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -#include "wifi_configuration.h" -#include "usbip_server.h" - -uint8_t kState = ACCEPTING; -int kSock = -1; - -void tcp_server_task(void *pvParameters) -{ - uint8_t tcp_rx_buffer[768]; - char addr_str[128]; - int addr_family; - int ip_protocol; - - while (1) - { - -#ifdef CONFIG_EXAMPLE_IPV4 - struct sockaddr_in destAddr; - destAddr.sin_addr.s_addr = htonl(INADDR_ANY); - destAddr.sin_family = AF_INET; - destAddr.sin_port = htons(PORT); - addr_family = AF_INET; - ip_protocol = IPPROTO_IP; - inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); -#else // IPV6 - struct sockaddr_in6 destAddr; - bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un)); - destAddr.sin6_family = AF_INET6; - destAddr.sin6_port = htons(PORT); - addr_family = AF_INET6; - ip_protocol = IPPROTO_IPV6; - inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); -#endif - - int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); - if (listen_sock < 0) - { - os_printf("Unable to create socket: errno %d\r\n", errno); - break; - } - os_printf("Socket created\r\n"); - - int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); - if (err != 0) - { - os_printf("Socket unable to bind: errno %d\r\n", errno); - break; - } - os_printf("Socket binded\r\n"); - - err = listen(listen_sock, 1); - if (err != 0) - { - os_printf("Error occured during listen: errno %d\r\n", errno); - break; - } - os_printf("Socket listening\r\n"); - -#ifdef CONFIG_EXAMPLE_IPV6 - struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 -#else - struct sockaddr_in sourceAddr; -#endif - uint32_t addrLen = sizeof(sourceAddr); - while (1) - { - kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); - if (kSock < 0) - { - os_printf("Unable to accept connection: errno %d\r\n", errno); - break; - } - os_printf("Socket accepted\r\n"); - - while (1) - { - int len = recv(kSock, tcp_rx_buffer, sizeof(tcp_rx_buffer), 0); - // Error occured during receiving - if (len < 0) - { - os_printf("recv failed: errno %d\r\n", errno); - break; - } - // Connection closed - else if (len == 0) - { - os_printf("Connection closed\r\n"); - break; - } - // Data received - else - { - // #ifdef CONFIG_EXAMPLE_IPV6 - // // Get the sender's ip address as string - // if (sourceAddr.sin6_family == PF_INET) - // { - // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - // } - // else if (sourceAddr.sin6_family == PF_INET6) - // { - // inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); - // } - // #else - // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); - // #endif - - switch (kState) - { - case ACCEPTING: - kState = ATTACHING; - - case ATTACHING: - attach(tcp_rx_buffer, len); - break; - - case EMULATING: - emulate(tcp_rx_buffer, len); - break; - default: - os_printf("unkonw kstate!\r\n"); - } - } - } - // kState = ACCEPTING; - if (kSock != -1) - { - os_printf("Shutting down socket and restarting...\r\n"); - //shutdown(kSock, 0); - close(kSock); - if (kState == EMULATING) - kState = ACCEPTING; - - //shutdown(listen_sock, 0); - //close(listen_sock); - //vTaskDelay(5); - } - } - } - vTaskDelete(NULL); +/** + * @file tcp_server.c + * @brief Handle main tcp tasks + * @version 0.1 + * @date 2020-01-22 + * + * @copyright Copyright (c) 2020 + * + */ +#include "tcp_server.h" + +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +#include "wifi_configuration.h" +#include "usbip_server.h" + +extern TaskHandle_t kDAPTaskHandle; +extern int kRestartDAPHandle; + +uint8_t kState = ACCEPTING; +int kSock = -1; + +void tcp_server_task(void *pvParameters) +{ + uint8_t tcp_rx_buffer[768]; + char addr_str[128]; + int addr_family; + int ip_protocol; + + while (1) + { + +#ifdef CONFIG_EXAMPLE_IPV4 + struct sockaddr_in destAddr; + destAddr.sin_addr.s_addr = htonl(INADDR_ANY); + destAddr.sin_family = AF_INET; + destAddr.sin_port = htons(PORT); + addr_family = AF_INET; + ip_protocol = IPPROTO_IP; + inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); +#else // IPV6 + struct sockaddr_in6 destAddr; + bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un)); + destAddr.sin6_family = AF_INET6; + destAddr.sin6_port = htons(PORT); + addr_family = AF_INET6; + ip_protocol = IPPROTO_IPV6; + inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); +#endif + + int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); + if (listen_sock < 0) + { + os_printf("Unable to create socket: errno %d\r\n", errno); + break; + } + os_printf("Socket created\r\n"); + + int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); + if (err != 0) + { + os_printf("Socket unable to bind: errno %d\r\n", errno); + break; + } + os_printf("Socket binded\r\n"); + + err = listen(listen_sock, 1); + if (err != 0) + { + os_printf("Error occured during listen: errno %d\r\n", errno); + break; + } + os_printf("Socket listening\r\n"); + +#ifdef CONFIG_EXAMPLE_IPV6 + struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6 +#else + struct sockaddr_in sourceAddr; +#endif + uint32_t addrLen = sizeof(sourceAddr); + while (1) + { + kSock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen); + if (kSock < 0) + { + os_printf("Unable to accept connection: errno %d\r\n", errno); + break; + } + os_printf("Socket accepted\r\n"); + + while (1) + { + int len = recv(kSock, tcp_rx_buffer, sizeof(tcp_rx_buffer), 0); + // Error occured during receiving + if (len < 0) + { + os_printf("recv failed: errno %d\r\n", errno); + break; + } + // Connection closed + else if (len == 0) + { + os_printf("Connection closed\r\n"); + break; + } + // Data received + else + { + // #ifdef CONFIG_EXAMPLE_IPV6 + // // Get the sender's ip address as string + // if (sourceAddr.sin6_family == PF_INET) + // { + // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + // } + // else if (sourceAddr.sin6_family == PF_INET6) + // { + // inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1); + // } + // #else + // inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1); + // #endif + + switch (kState) + { + case ACCEPTING: + kState = ATTACHING; + + case ATTACHING: + attach(tcp_rx_buffer, len); + break; + + case EMULATING: + emulate(tcp_rx_buffer, len); + break; + default: + os_printf("unkonw kstate!\r\n"); + } + } + } + // kState = ACCEPTING; + if (kSock != -1) + { + os_printf("Shutting down socket and restarting...\r\n"); + //shutdown(kSock, 0); + close(kSock); + if (kState == EMULATING) + kState = ACCEPTING; + + // Restart DAP Handle + kRestartDAPHandle = 1; + xTaskNotifyGive(kDAPTaskHandle); + + //shutdown(listen_sock, 0); + //close(listen_sock); + //vTaskDelay(5); + } + } + } + vTaskDelete(NULL); } \ No newline at end of file From 635999afa3ae0f0818b5b3d421714029b774f3ef Mon Sep 17 00:00:00 2001 From: windowsair Date: Mon, 7 Dec 2020 00:27:14 +0800 Subject: [PATCH 2/4] fix: Fix no return function --- components/DAP/source/SW_DP.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/DAP/source/SW_DP.c b/components/DAP/source/SW_DP.c index 87de13e..600809d 100644 --- a/components/DAP/source/SW_DP.c +++ b/components/DAP/source/SW_DP.c @@ -295,6 +295,7 @@ static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) { } } while (retryCount++ < 99); + return DAP_TRANSFER_ERROR; } From c6eaac3ae8f86fb45da7d27221857a39ad25298d Mon Sep 17 00:00:00 2001 From: windowsair Date: Sat, 26 Dec 2020 07:44:27 -0800 Subject: [PATCH 3/4] feat: Add github action (#9) --- .github/workflows/main.yml | 52 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..5bcceab --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,52 @@ +name: build + +on: [push] + +env: + UPLOAD_USER_FIRMWARE: false + +jobs: + build: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + + - name: before_install + run: | + sudo apt update + sudo apt install -y gcc git wget make libncurses-dev flex bison python python-serial ninja-build + wget https://dl.espressif.com/dl/xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz + + - name: install + run: | + tar -xzf ./xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz + wget https://github.com/espressif/ESP8266_RTOS_SDK/releases/download/v3.3-rc1/ESP8266_RTOS_SDK-v3.3-rc1.zip + unzip ESP8266_RTOS_SDK-v3.3-rc1.zip + python -m pip install --user -r ./ESP8266_RTOS_SDK/requirements.txt + + - name: script + id: script + run: | + export IDF_PATH=$PWD/ESP8266_RTOS_SDK + export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" + echo "FIRMWARE=$PWD/build" >> $GITHUB_ENV + python ./idf.py fullclean + python ./idf.py build + echo "::set-output name=status::success" + + - name: Generate release tag + id: tag + if: env.UPLOAD_USER_FIRMWARE == 'true' && steps.script.outputs.status == 'success' && !cancelled() + run: | + echo "::set-output name=release_tag::UserBuild_$(date +"%Y.%m.%d-%H:%M")" + echo "::set-output name=status::success" + + - name: Release user firmware + uses: softprops/action-gh-release@v1 + if: steps.tag.outputs.status == 'success' && !cancelled() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.tag.outputs.release_tag }} + files: ${{ env.FIRMWARE }}/esp8266_dap.bin + From bc63a07a9b3b479d26839b2979a3b5c0161683e0 Mon Sep 17 00:00:00 2001 From: windowsair Date: Sun, 27 Dec 2020 20:02:38 +0800 Subject: [PATCH 4/4] feat: Improve WINUSB transfer speed --- CMakeLists.txt | 2 ++ README.md | 31 ++++++++++++++++++++++-------- components/DAP/config/DAP_config.h | 11 ++--------- components/README.md | 2 -- components/USBIP/USB_handle.c | 1 + components/USBIP/USBd_config.h | 2 +- main/DAP_handle.c | 3 +-- main/dap_configuration.h | 22 +++++++++++++++++++++ main/tcp_server.c | 8 +++++++- sdkconfig | 17 ++++++++-------- 10 files changed, 67 insertions(+), 32 deletions(-) delete mode 100644 components/README.md create mode 100644 main/dap_configuration.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eb1581..7bc2902 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,5 +3,7 @@ cmake_minimum_required(VERSION 3.5) #set(COMPONENT_DIRS "${IDF_PATH}/components ${PROJECT_PATH}/components") +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/main) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp8266_dap) diff --git a/README.md b/README.md index c01e68d..943ef50 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@

Wireless ESP8266 DAP

-[![Build Status](https://travis-ci.com/windowsair/wireless-esp8266-dap.svg?branch=master)](https://travis-ci.com/windowsair/wireless-esp8266-dap) master -[![Build Status](https://travis-ci.com/windowsair/wireless-esp8266-dap.svg?branch=develop)](https://travis-ci.com/windowsair/wireless-esp8266-dap) develop +[![Build Status](https://github.com/windowsair/wireless-esp8266-dap/workflows/build/badge.svg?branch=master)](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Amaster) master +[![Build Status](https://github.com/windowsair/wireless-esp8266-dap/workflows/build/badge.svg?branch=develop)](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Adevelop) develop [![](https://img.shields.io/badge/license-MIT-green.svg?style=flat-square)](https://github.com/windowsair/wireless-esp8266-dap/LICENSE) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-blue.svg?style=flat-square)](https://github.com/windowsair/wireless-esp8266-dap/pulls) [![%e2%9d%a4](https://img.shields.io/badge/made%20with-%e2%9d%a4-ff69b4.svg?style=flat-square)](https://github.com/windowsair/wireless-esp8266-dap) @@ -32,8 +32,9 @@ Realized by USBIP and CMSIS-DAP protocol stack. - [ ] SWO Streaming Trace 4. More.. - - [x] Custom maximum debug clock ~~(more than 10MHz)~~ (experimental) - - [ ] ... + - [x] Custom maximum debug clock (40MHz, SWD only) + - [x] SWD protocol based on SPI acceleration + - [x] ... @@ -82,6 +83,14 @@ You can modify these pin definitions in [DAP_config.h](components/DAP/config/DAP ## Build +You can build locally or use Github Action to build online + +### Build with Github Action Online + +See: [Build with Github Action](https://github.com/windowsair/wireless-esp8266-dap/wiki/Build-with-Github-Action) + +### General build + 1. Get ESP8266 RTOS Software Development Kit For now, use the 3.3-rc1 version of the SDK (this is a known issue) @@ -117,14 +126,14 @@ python ./idf.py -p /dev/ttyS5 flash 3. Connect it with usbip: ```bash -# HID Mode +# HID Mode only # for pre-compiled version on SourceForge # or usbip old version .\usbip.exe -D -a 1-1 # HID Mode Or WinUSB Mode # for usbip-win 0.3.0 kmdf ude -.\usbip.exe attach-ude -r -b 1-1 +.\usbip.exe attach_ude -r -b 1-1 ``` @@ -141,6 +150,8 @@ Then test it under MDK: ## Develop +0. Check other branches to know the latest development progress. + 1. Use WinUSB Mode: change `USE_WINUSB` macor in [USBd_config.h](components/USBIP/USBd_config.h) @@ -153,16 +164,20 @@ Then test it under MDK: > - https://github.com/cezanne/usbip-win for usbip windows -In this repo you can find the complete implementation of the USB protocol stack including USB-HID, WCID, WinUSB. Although WinUSB-based mode currently does not work on USBIP :disappointed_relieved: . They are very easy and can help you quickly build your own DAP on other hardware platforms. +In this repo you can find the complete implementation of the USB protocol stack including USB-HID, WCID, WinUSB. ~~Although WinUSB-based mode currently does not work on USBIP~~ :disappointed_relieved: . They are very easy and can help you quickly build your own DAP on other hardware platforms. -Currently using USB-HID for transmission is still slightly slower, If you have any ideas, welcome: +Currently TCP transmission speed needs to be further improved, If you have any ideas, welcome: - [New issues](https://github.com/windowsair/wireless-esp8266-dap/issues) - [New pull](https://github.com/windowsair/wireless-esp8266-dap/pulls) ### Issue +2020.12.1 + +TCP transmission speed needs to be further improved. + 2020.11.11 Winusb is now available, but it is very slow. diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index f502fb6..fcf2d24 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -37,7 +37,7 @@ #include "esp8266/pin_mux_register.h" #include "spi_switch.h" - +#include "dap_configuration.h" //************************************************************************************************** /** \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information @@ -98,18 +98,11 @@ This information includes: #define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<1MHz -/// Maximum Package Size for Command and Response data. -/// This configuration settings is used to optimize the communication performance with the -/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, -/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. -#define DAP_PACKET_SIZE 255U ///< Specifies Packet Size in bytes. -// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 512 for High-speed USB WinUSB. - /// Maximum Package Buffers for Command and Response data. /// This configuration settings is used to optimize the communication performance with the /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the /// setting can be reduced (valid range is 1 .. 255). -#define DAP_PACKET_COUNT 20 ///< Specifies number of packets buffered. +#define DAP_PACKET_COUNT 255 ///< Specifies number of packets buffered. /// Indicate that UART Serial Wire Output (SWO) trace is available. /// This information is returned by the command \ref DAP_Info as part of Capabilities. diff --git a/components/README.md b/components/README.md deleted file mode 100644 index 3fc0da1..0000000 --- a/components/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# TODO -1. USB \ No newline at end of file diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index 0ea27c5..e806f1e 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -272,6 +272,7 @@ static void handleGetDescriptor(usbip_stage2_header *header) os_printf("low bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8lo); os_printf("high bit : %d\r\n", (int)header->u.cmd_submit.request.wValue.u8hi); os_printf("***Unsupported String descriptor***\r\n"); + send_stage2_submit(header, 0, 0); } break; diff --git a/components/USBIP/USBd_config.h b/components/USBIP/USBd_config.h index dc3a3e2..188b529 100644 --- a/components/USBIP/USBd_config.h +++ b/components/USBIP/USBd_config.h @@ -1,7 +1,7 @@ #ifndef __USBD_CONFIG_H__ #define __USBD_CONFIG_H__ -#define USE_WINUSB 0 +#include "dap_configuration.h" // Vendor ID assigned by USB-IF (idVendor). #define USBD0_DEV_DESC_IDVENDOR 0xC251 diff --git a/main/DAP_handle.c b/main/DAP_handle.c index 3efb856..ff7f2cc 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -16,6 +16,7 @@ #include "DAP.h" #include "esp_libc.h" #include "USBd_config.h" +#include "dap_configuration.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -32,8 +33,6 @@ extern TaskHandle_t kDAPTaskHandle; int kRestartDAPHandle = 0; -////TODO: Merge this -#define DAP_PACKET_SIZE 255 #if (USE_WINUSB == 1) typedef struct diff --git a/main/dap_configuration.h b/main/dap_configuration.h new file mode 100644 index 0000000..07298cf --- /dev/null +++ b/main/dap_configuration.h @@ -0,0 +1,22 @@ +#ifndef __DAP_CONFIGURATION_H__ +#define __DAP_CONFIGURATION_H__ + +/** + * @brief Specify the use of WINUSB + * + */ +#define USE_WINUSB 1 + +/// Maximum Package Size for Command and Response data. +/// This configuration settings is used to optimize the communication performance with the +/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, +/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. + +#if (USE_WINUSB == 1) + #define DAP_PACKET_SIZE 512U // 512 for WinUSB. +#else + #define DAP_PACKET_SIZE 255U // 255 for USB HID +#endif + + +#endif diff --git a/main/tcp_server.c b/main/tcp_server.c index aee67c0..8f85f6f 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -37,11 +37,12 @@ int kSock = -1; void tcp_server_task(void *pvParameters) { - uint8_t tcp_rx_buffer[768]; + uint8_t tcp_rx_buffer[1024]; char addr_str[128]; int addr_family; int ip_protocol; + int on = 1; while (1) { @@ -71,6 +72,9 @@ void tcp_server_task(void *pvParameters) } os_printf("Socket created\r\n"); + setsockopt(listen_sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); + setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)); + int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); if (err != 0) { @@ -101,6 +105,8 @@ void tcp_server_task(void *pvParameters) os_printf("Unable to accept connection: errno %d\r\n", errno); break; } + setsockopt(kSock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on)); + setsockopt(kSock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)); os_printf("Socket accepted\r\n"); while (1) diff --git a/sdkconfig b/sdkconfig index e20f324..c3b4568 100644 --- a/sdkconfig +++ b/sdkconfig @@ -123,8 +123,8 @@ CONFIG_TASK_WDT_PANIC=y CONFIG_TASK_WDT_TIMEOUT_15N=y CONFIG_TASK_WDT_TIMEOUT_S=15 CONFIG_RESET_REASON=y -CONFIG_WIFI_PPT_TASKSTACK_SIZE=2048 -CONFIG_EVENT_LOOP_STACK_SIZE=2048 +CONFIG_WIFI_PPT_TASKSTACK_SIZE=4096 +CONFIG_EVENT_LOOP_STACK_SIZE=4096 # CONFIG_ESP8266_OTA_FROM_OLD is not set # CONFIG_ESP8266_BOOT_COPY_APP is not set CONFIG_ESP_ERR_TO_NAME_LOOKUP=y @@ -135,9 +135,9 @@ CONFIG_WIFI_TX_RATE_SEQUENCE_FROM_HIGH=y # CONFIG_ESP8266_WIFI_QOS_ENABLED is not set # CONFIG_ESP8266_WIFI_AMPDU_RX_ENABLED is not set # CONFIG_ESP8266_WIFI_AMSDU_ENABLED is not set -CONFIG_ESP8266_WIFI_RX_BUFFER_NUM=26 -CONFIG_ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM=4 -CONFIG_ESP8266_WIFI_RX_PKT_NUM=7 +CONFIG_ESP8266_WIFI_RX_BUFFER_NUM=28 +CONFIG_ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM=8 +CONFIG_ESP8266_WIFI_RX_PKT_NUM=16 CONFIG_ESP8266_WIFI_TX_PKT_NUM=6 CONFIG_ESP8266_WIFI_NVS_ENABLED=y CONFIG_ESP8266_WIFI_CONNECT_OPEN_ROUTER_WHEN_PWD_IS_SET=y @@ -183,9 +183,8 @@ CONFIG_TCPIP_RECVMBOX_SIZE=64 CONFIG_LWIP_ARP_TABLE_SIZE=10 CONFIG_LWIP_ARP_MAXAGE=300 # CONFIG_LWIP_ESP_GRATUITOUS_ARP is not set -CONFIG_LWIP_SOCKET_MULTITHREAD=y +# CONFIG_LWIP_SOCKET_MULTITHREAD is not set CONFIG_ENABLE_NONBLOCK_SPEEDUP=y -CONFIG_SET_SOLINGER_DEFAULT=y CONFIG_ESP_UDP_SYNC_SEND=y CONFIG_ESP_UDP_SYNC_RETRY_MAX=5 CONFIG_LWIP_MAX_SOCKETS=10 @@ -214,13 +213,13 @@ CONFIG_ESP_DNS=y CONFIG_DNS_MAX_SERVERS=3 # CONFIG_LWIP_NETIF_LOOPBACK is not set CONFIG_TCP_HIGH_SPEED_RETRANSMISSION=y -CONFIG_LWIP_MAX_ACTIVE_TCP=5 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 CONFIG_LWIP_MAX_LISTENING_TCP=8 CONFIG_TCP_MAXRTX=12 CONFIG_TCP_SYNMAXRTX=6 CONFIG_TCP_MSS=1460 CONFIG_TCP_SND_BUF_DEFAULT=2920 -CONFIG_TCP_WND_DEFAULT=5840 +CONFIG_TCP_WND_DEFAULT=10240 CONFIG_TCP_RECVMBOX_SIZE=16 CONFIG_TCP_QUEUE_OOSEQ=y CONFIG_TCP_OVERSIZE_MSS=y