0
0
Fork 0

Merge branch 'feature/spi' into develop

This commit is contained in:
windowsair 2020-12-27 20:34:05 +08:00
commit 810c11c95f
21 changed files with 1337 additions and 793 deletions

1
.gitignore vendored
View File

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

View File

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

View File

@ -1,8 +1,8 @@
<p align="center"><img src="https://user-images.githubusercontent.com/17078589/73821108-300bda00-482e-11ea-89f6-011a50037a12.png"/></p>
<h1 align="center">Wireless ESP8266 DAP</h1>
[![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 <your-esp8266-ip-address> 1-1
# HID Mode Or WinUSB Mode
# for usbip-win 0.3.0 kmdf ude
.\usbip.exe attach-ude -r <your-esp8266-ip-address> -b 1-1
.\usbip.exe attach_ude -r <your-esp8266-ip-address> -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.

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"
#include "dap_configuration.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
@ -96,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 <b>Capabilities</b>.
@ -189,12 +184,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 +296,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 +363,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 +441,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 +451,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 +480,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 +499,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 +517,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 +589,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 +614,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 +737,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 +753,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,176 @@ 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);
return DAP_TRANSFER_ERROR;
}

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

@ -1,2 +0,0 @@
# TODO
1. USB

View File

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

View File

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

View File

@ -1,268 +1,286 @@
/**
* @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 <stdint.h>
#include <string.h>
#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 <lwip/netdb.h>
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 <stdint.h>
#include <string.h>
#include "usbip_server.h"
#include "DAP_handle.h"
#include "DAP.h"
#include "esp_libc.h"
#include "USBd_config.h"
#include "dap_configuration.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 <lwip/netdb.h>
extern int kSock;
extern TaskHandle_t kDAPTaskHandle;
int kRestartDAPHandle = 0;
#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]);
}
}

22
main/dap_configuration.h Normal file
View File

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

View File

@ -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 <string.h>
#include <stdint.h>
#include <sys/param.h>
#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 <lwip/netdb.h>
#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 <string.h>
#include <stdint.h>
#include <sys/param.h>
#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 <lwip/netdb.h>
#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);
}

View File

@ -1,168 +1,181 @@
/**
* @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 <string.h>
#include <stdint.h>
#include <sys/param.h>
#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 <lwip/netdb.h>
#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 <string.h>
#include <stdint.h>
#include <sys/param.h>
#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 <lwip/netdb.h>
#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[1024];
char addr_str[128];
int addr_family;
int ip_protocol;
int on = 1;
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");
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)
{
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;
}
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)
{
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);
}

View File

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