Merge branch 'feature/spi' into develop
This commit is contained in:
commit
810c11c95f
|
@ -1,2 +1,3 @@
|
|||
.vscode/
|
||||
build/
|
||||
tmp/
|
|
@ -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)
|
||||
|
|
31
README.md
31
README.md
|
@ -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>
|
||||
|
||||
[](https://travis-ci.com/windowsair/wireless-esp8266-dap) master
|
||||
[](https://travis-ci.com/windowsair/wireless-esp8266-dap) develop
|
||||
[](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Amaster) master
|
||||
[](https://github.com/windowsair/wireless-esp8266-dap/actions?query=branch%3Adevelop) develop
|
||||
|
||||
[](https://github.com/windowsair/wireless-esp8266-dap/LICENSE) [](https://github.com/windowsair/wireless-esp8266-dap/pulls) [](https://github.com/windowsair/wireless-esp8266-dap)
|
||||
|
||||
|
@ -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.
|
||||
|
|
|
@ -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()
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
# TODO
|
||||
1. USB
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
|
@ -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
|
284
main/main.c
284
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 <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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
17
sdkconfig
17
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
|
||||
|
|
Loading…
Reference in New Issue