0
0
Fork 0

Merge pull request #1 from windowsair/develop

Develop
This commit is contained in:
windowsair 2021-04-06 20:01:31 +08:00 committed by GitHub
commit 2a805100db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 3560 additions and 2088 deletions

52
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: build
on: [push]
env:
UPLOAD_USER_FIRMWARE: false
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: before_install
run: |
sudo apt update
sudo apt install -y gcc git wget make libncurses-dev flex bison python python-serial ninja-build
wget https://dl.espressif.com/dl/xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz
- name: install
run: |
tar -xzf ./xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz
wget https://github.com/espressif/ESP8266_RTOS_SDK/releases/download/v3.3-rc1/ESP8266_RTOS_SDK-v3.3-rc1.zip
unzip ESP8266_RTOS_SDK-v3.3-rc1.zip
python -m pip install --user -r ./ESP8266_RTOS_SDK/requirements.txt
- name: script
id: script
run: |
export IDF_PATH=$PWD/ESP8266_RTOS_SDK
export PATH="$PATH:$PWD/xtensa-lx106-elf/bin"
echo "FIRMWARE=$PWD/build" >> $GITHUB_ENV
python ./idf.py fullclean
python ./idf.py build
echo "::set-output name=status::success"
- name: Generate release tag
id: tag
if: env.UPLOAD_USER_FIRMWARE == 'true' && steps.script.outputs.status == 'success' && !cancelled()
run: |
echo "::set-output name=release_tag::UserBuild_$(date +"%Y.%m.%d_%H-%M")"
echo "::set-output name=status::success"
- name: Release user firmware
uses: softprops/action-gh-release@v1
if: steps.tag.outputs.status == 'success' && !cancelled()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.tag.outputs.release_tag }}
files: ${{ env.FIRMWARE }}/esp8266_dap.bin

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
.vscode/
build/
tmp/
.history/

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "ESP8266_RTOS_SDK"]
path = ESP8266_RTOS_SDK
url = https://github.com/espressif/ESP8266_RTOS_SDK

View File

@ -1,12 +1,14 @@
language: c
sudo: required
before_install:
- sudo apt install -y gcc git wget make libncurses-dev flex bison python python-serial
- sudo apt update
- sudo apt install -y gcc git wget make libncurses-dev flex bison python python-serial ninja-build
- wget https://dl.espressif.com/dl/xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz
install:
- tar -xzf ./xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz
- git clone --recursive https://github.com/espressif/ESP8266_RTOS_SDK.git
- wget https://github.com/espressif/ESP8266_RTOS_SDK/releases/download/v3.3-rc1/ESP8266_RTOS_SDK-v3.3-rc1.zip
- unzip ESP8266_RTOS_SDK-v3.3-rc1.zip
- python -m pip install --user -r ./ESP8266_RTOS_SDK/requirements.txt
before_script:

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)

1
ESP8266_RTOS_SDK Submodule

@ -0,0 +1 @@
Subproject commit 1be2289fcd68672f5d6bf6aafa4f4b57b20527a4

166
README.md
View File

@ -1,10 +1,12 @@
<p align="center"><img src="https://user-images.githubusercontent.com/17078589/73821108-300bda00-482e-11ea-89f6-011a50037a12.png"/></p>
<h1 align="center">Wireless ESP8266 DAP</h1>
<p align="center"><img src="https://user-images.githubusercontent.com/17078589/107881245-7d7d5580-6f1e-11eb-9f66-6ac589e5f95c.png"/></p>
[![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
![image](https://user-images.githubusercontent.com/17078589/107857220-05ecef00-6e68-11eb-9fa0-506b32052dba.png)
[![](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)
[![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)
## Introduce
@ -13,80 +15,110 @@ Wireless debugging with ***only one ESP8266*** !
Realized by USBIP and CMSIS-DAP protocol stack.
> 👉 5m distance, 100kb size firmware flash test:
> 👉 5m distance, 100kb size firmware(Hex) flash test:
<p align="center"><img src="https://user-images.githubusercontent.com/17078589/73829782-808b3380-483e-11ea-8389-1570bc4200af.gif"/></p>
<p align="center"><img src="https://user-images.githubusercontent.com/17078589/107896674-e5a95700-6f71-11eb-90f7-bf7362045537.gif"/></p>
## Feature
1. Debug Communication Mode
- [x] SWJ
- [x] JTAG
1. Debug Communication Mode & Debug Port
- [x] SWD(SW-DP)
- [x] JTAG(JTAG-DP)
- [x] SWJ-DP
2. USB Communication Mode
- [x] USB-HID
- [ ] WCID & WinUSB
- [x] WCID & WinUSB (Default)
3. Debug Trace
- [ ] UART Serial Wire Output(SWO)
- [ ] SWO Streaming Trace
4. More..
- [x] Custom maximum debug clock(more than 10MHz)
- [ ] ...
- [x] Custom maximum debug clock (40MHz, SWD only)
- [x] SWD protocol based on SPI acceleration
- [x] ...
## Link your board
1. WIFI
### WIFI
The default connected WIFI SSID is `DAP` , password `12345678`
You can change `WIFI_SSID` and ` WIFI_PASS` in [wifi_configuration.h](main/wifi_configuration.h)
2. Debugger
You can also specify your IP in the above file (We recommend using the static address binding feature of the router).
### Debugger
- SWD
| SWD | |
|----------------|--------|
| SWCLK | GPIO5 |
| SWDIO | GPIO4 |
| SWCLK | GPIO14 |
| SWDIO | GPIO12 |
| SWDIO_MOSI | GPIO13 |
| LED\_CONNECTED | GPIO2 |
| LED\_RUNNING | GPIO15 |
| TVCC | 3V3 |
| GND | GND |
- JTAG
--------------
| JTAG | |
|--------------------|---------|
| TCK | GPIO5 |
| TMS | GPIO4 |
| TDI | GPIO13 |
| TDO | GPIO12 |
| TCK | GPIO14 |
| TMS | GPIO13 |
| TDI | GPIO4 |
| TDO | GPIO16 |
| nTRST \(optional\) | GPIO0\* |
| nRESET | GPIO14 |
| nRESET | GPIO5 |
| LED\_CONNECTED | GPIO2 |
| LED\_RUNNING | GPIO15 |
| TVCC | 3V3 |
| GND | GND |
You can modify these pin definitions in [DAP_config.h](components/DAP/config/DAP_config.h)
> Tips: Try to avoid using `GPIO0`(working mode switch) and `GPIO16`(RTC)
In order to use SPI acceleration, you need to physically connect `SWDIO(GPIO12)` to `SWDIO_MOSI(GPIO13)`.
## Build
Here, we give a simple example for reference:
![sch](https://user-images.githubusercontent.com/17078589/107851862-f9589e80-6e47-11eb-9eca-e80760822a6a.png)
Alternatively, you can connect directly with wires as we gave at the beginning, without additional circuits.
> If you need to modify the LED or JTAG pins, please refer to the instructions in [DAP_config.h](components/DAP/config/DAP_config.h) to modify them carefully.
------
## Build And Flash
You can build locally or use Github Action to build online and then download firmware to flash.
### Build with Github Action Online
See: [Build with Github Action](https://github.com/windowsair/wireless-esp8266-dap/wiki/Build-with-Github-Action)
### General build and Flash
1. Get ESP8266 RTOS Software Development Kit
See: [ESP8266_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK "ESP8266_RTOS_SDK")
For now, use the 3.3-rc1 version of the SDK (this is a known issue)
See: [ESP8266_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK/releases/tag/v3.3-rc1 "ESP8266_RTOS_SDK")
2. Build & Flash
Build with ESP-IDF build system.
More information can be found at the following link: [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html "Build System")
Build with ESP-IDF build system.
More information can be found at the following link: [Build System](https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html "Build System")
The following example shows a possible way to build on Windows:
@ -104,48 +136,86 @@ python ./idf.py -p /dev/ttyS5 flash
1. Get USBIP project
- Windows: [usbip-windows](https://github.com/george-hopkins/usbip-windows "usbip-windows") . Or you can find it already built here: https://github.com/barbalion/usbip-win-client
- Linux: Distributed as part of the kernel
- Windows: [usbip-win](https://github.com/cezanne/usbip-win) .
- Linux: Distributed as part of the Linux kernel, but we have not yet tested on Linux platform, and the following instructions are all under Windows platform.
2. Start esp8266 and connect it to the device to be debugged
3. Connect it with usbip:
```bash
# HID Mode only
# for pre-compiled version on SourceForge
# or usbip old version
.\usbip.exe -D -a <your-esp8266-ip-address> 1-1
# 👉 Recommend
# HID Mode Or WinUSB Mode
# for usbip-win 0.3.0 kmdf ude
.\usbip.exe attach_ude -r <your-esp8266-ip-address> -b 1-1
```
If all goes well, you should see your device connected.
![image](https://user-images.githubusercontent.com/17078589/73833411-eb3f6d80-4844-11ea-8501-02a008f6119d.png)
![image](https://user-images.githubusercontent.com/17078589/107849548-f903d780-6e36-11eb-846f-3eaf0c0dc089.png)
Here, we use MDK for testing:
![target](https://user-images.githubusercontent.com/17078589/73830040-eb3c6f00-483e-11ea-85ee-c40b68a836b2.png)
------
## Speed Strategy
The maximum rate of esp8266 pure IO is about 2MHz.
When you select max clock, we will take the following actions:
- `clock < 2Mhz` : Similar to the clock speed you choose.
- `2MHz <= clock < 10MHz` : Use the fastest pure IO speed.
- `clock >= 10MHz` : SPI acceleration using 40MHz clock.
> Note that the most significant speed constraint of this project is still the TCP connection speed.
## Develop
> Credits to:
> - https://github.com/thevoidnn/esp8266-wifi-cmsis-dap for adapter firmware based on CMSIS-DAP v1.0
> - https://github.com/ARM-software/CMSIS_5 for CMSIS
0. Check other branches to know the latest development progress.
1. Use WinUSB Mode(enabled by default):
change `USE_WINUSB` macor in [dap_configuration.h](main/dap_configuration.h)
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
2-4
2020.12.1
TCP transmission speed needs to be further improved.
2020.11.11
Winusb is now available, but it is very slow.
2020.2.4
Due to the limitation of USB-HID (I'm not sure if this is a problem with USBIP or Windows), now each URB packet can only reach 255 bytes (About 1MBps bandwidth), which has not reached the upper limit of ESP8266 transmission bandwidth.
I now have an idea to construct a Man-in-the-middle between the two to forward traffic, thereby increasing the bandwidth of each transmission.
1-31
2020.1.31
At present, the adaptation to WCID, WinUSB, etc. has all been completed. However, when transmitting data on the endpoint, we received an error message from USBIP. This is most likely a problem with the USBIP project itself.
@ -154,6 +224,22 @@ Due to the completeness of the USBIP protocol document, we have not yet understo
We will continue to try to make it work on USB HID. Once the USBIP problem is solved, we will immediately transfer it to work on WinUSB
------
# Credit
Credits to the following project, people and organizations:
> - https://github.com/thevoidnn/esp8266-wifi-cmsis-dap for adapter firmware based on CMSIS-DAP v1.0
> - https://github.com/ARM-software/CMSIS_5 for CMSIS
> - https://github.com/cezanne/usbip-win for usbip windows
- [@HeavenSpree](https://www.github.com/HeavenSpree)
- [@Zy19930907](https://www.github.com/Zy19930907)
- [@caiguang1997](https://www.github.com/caiguang1997)
## License
[MIT LICENSE](LICENSE)

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

File diff suppressed because it is too large Load Diff

View File

@ -233,6 +233,14 @@ extern DAP_Data_t DAP_Data; // DAP Data
extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag
enum transfer_type {
kTransfer_GPIO_normal,
kTransfer_GPIO_fast,
kTransfer_SPI
};
extern uint8_t SWD_TransferSpeed;
#ifdef __cplusplus
extern "C"
{
@ -265,8 +273,8 @@ extern void SWO_TransferComplete (void);
extern uint32_t UART_SWO_Mode (uint32_t enable);
extern uint32_t UART_SWO_Baudrate (uint32_t baudrate);
extern uint32_t UART_SWO_Control (uint32_t active);
extern void UART_SWO_Capture (uint8_t *buf, uint32_t num);
extern uint32_t UART_SWO_GetCount (void);
// extern void UART_SWO_Capture (uint8_t *buf, uint32_t num);
// extern uint32_t UART_SWO_GetCount (void);
extern uint32_t Manchester_SWO_Mode (uint32_t enable);
extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate);

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,46 @@
#ifndef __GPIO_OP_H__
#define __GPIO_OP_H__
#include "cmsis_compiler.h"
#include "gpio.h"
#include "gpio_struct.h"
#include "timer_struct.h"
#include "esp8266/pin_mux_register.h"
__STATIC_INLINE void GPIO_FUNCTION_SET(int io_num)
{
gpio_pin_reg_t pin_reg;
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(io_num));
// It should be noted that GPIO0, 2, 4, and 5 need to set the func register to 0,
// and the other GPIO needs to be set to 3 so that IO can be GPIO function.
if ((0x1 << io_num) & (GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5)) {
pin_reg.rtc_pin.func_low_bit = 0;
pin_reg.rtc_pin.func_high_bit = 0;
} else {
pin_reg.func_low_bit = 3;
pin_reg.func_high_bit = 0;
}
WRITE_PERI_REG(GPIO_PIN_REG(io_num), pin_reg.val);
}
static void GPIO_SET_DIRECTION_NORMAL_OUT(int io_num)
{
GPIO.enable_w1ts |= (0x1 << io_num);
// PP out
GPIO.pin[io_num].driver = 0;
}
// static void GPIO_SET_DIRECTION_NORMAL_IN(int io_num)
// {
// GPIO.enable_w1tc |= (0x1 << io_num);
// }
#endif

View File

@ -0,0 +1,20 @@
#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_ReadBits(const uint8_t count, uint8_t *buf);
void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t *ack, uint8_t TrnAfterACK);
void DAP_SPI_Read_Data(uint32_t* resData, uint8_t* resParity);
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

@ -0,0 +1,17 @@
#ifndef __SWO_H__
#define __SWO_H__
typedef void * EventGroupHandle_t;
// event group bits
#define SWO_GOT_DATA 0x00000001
#define UART_GOT_DATA 0x00000002
#define SWO_ERROR_TIME_OUT 0x00000004
extern EventGroupHandle_t kSwoThreadEventGroup;
extern volatile uint8_t kSwoTransferBusy;
void SetTraceError(uint8_t flag); // Use in the uart handler
#endif

View File

@ -1,6 +1,6 @@
/**
* @brief Made some simple modifications to the official UART
*
*
*/
// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
@ -28,6 +28,13 @@ extern "C" {
#include "esp_err.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
// SWO modify
extern volatile uint32_t kSWO_read_index;
extern volatile uint32_t kSWO_read_num;
extern volatile uint8_t kSWO_uart_notify_enable;
extern SemaphoreHandle_t kSWO_read_mux;
#define UART_FIFO_LEN (128) /*!< Length of the hardware FIFO buffers */
#define UART_INTR_MASK 0x1ff /*!< Mask of all UART interrupts */
@ -428,7 +435,7 @@ esp_err_t my_uart_intr_config(uart_port_t uart_num, uart_intr_config_t *uart_int
* @param uart_queue UART event queue handle (out param). On success, a new queue handle is written here to provide
* access to UART events. If set to NULL, driver will not use an event queue.
* @param no_use Invalid parameters, just to fit some modules.
*
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
@ -558,6 +565,30 @@ esp_err_t my_uart_get_buffered_data_len(uart_port_t uart_num, size_t *size);
*/
esp_err_t my_uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh);
/**
* @brief Asynchronously read bytes to swo buffer
* @note This function only serves as a notification,
* and will initiate a callback when the buffer reaches the length since we modify the uart
* @param index buffer index to read
* @param length data length
* @return esp_err_t
* - ESP_OK Success
* - ESP_FAIL There are still unfinished requests
*/
esp_err_t my_uart_read_bytes_async_swo(uint32_t index, uint32_t length);
/**
* @brief UART get RX ring buffer cached data length
* @note This function is basically equivalent to \ref my_uart_get_buffered_data_len
* @param uart_num UART port number.
*
* @return data length
*/
int my_uart_get_rx_buffered_data_len(uart_port_t uart_num);
#ifdef __cplusplus
}
#endif

View File

@ -29,6 +29,8 @@
#include "DAP_config.h"
#include "DAP.h"
#include "spi_switch.h"
#if (DAP_PACKET_SIZE < 64U)
#error "Minimum Packet Size is 64!"
@ -109,7 +111,7 @@ static uint8_t DAP_Info(uint8_t id, uint8_t *info) {
length = 1U;
break;
case DAP_ID_TIMESTAMP_CLOCK:
#if (TIMESTAMP_CLOCK != 0U)
#if (TIMESTAMP_CLOCK != 0U)
info[0] = (uint8_t)(TIMESTAMP_CLOCK >> 0);
info[1] = (uint8_t)(TIMESTAMP_CLOCK >> 8);
info[2] = (uint8_t)(TIMESTAMP_CLOCK >> 16);
@ -207,7 +209,7 @@ static uint32_t DAP_Connect(const uint8_t *request, uint8_t *response) {
} else {
port = *request;
}
switch (port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
@ -266,9 +268,9 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) {
uint32_t select;
uint32_t wait;
uint32_t timestamp;
value = (uint32_t) *(request+0);
select = (uint32_t) *(request+1);
select = (uint32_t) *(request+1);
wait = (uint32_t)(*(request+2) << 0) |
(uint32_t)(*(request+3) << 8) |
(uint32_t)(*(request+4) << 16) |
@ -300,7 +302,7 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) {
if (wait != 0U) {
#if (TIMESTAMP_CLOCK != 0U)
if (wait > 3000000U) {
if (wait > 3000000U) {
wait = 3000000U;
}
#if (TIMESTAMP_CLOCK >= 1000000U)
@ -357,6 +359,7 @@ static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) {
return ((6U << 16) | 1U);
}
extern uint8_t SWD_TransferSpeed;
// Process SWJ Clock command and prepare response
// request: pointer to request data
@ -377,18 +380,30 @@ static uint32_t DAP_SWJ_Clock(const uint8_t *request, uint8_t *response) {
*response = DAP_ERROR;
return ((4U << 16) | 1U);
}
if(clock == 10000000){
clock = MAX_USER_CLOCK;
}
if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) {
// Note that the maximum IO frequency of esp8266 is less than 2MHz
// clock >= 10MHz -> use 40MHz SPI
if (clock >= 10000000) {
DAP_SPI_Init();
DAP_Data.fast_clock = 1U;
DAP_Data.clock_delay = 1U;
SWD_TransferSpeed = kTransfer_SPI;
} else if (clock >= 2000000) {
// clock >= 2MHz -> Use GPIO with no program delay
DAP_SPI_Deinit();
DAP_Data.fast_clock = 1U;
DAP_Data.clock_delay = 1U;
SWD_TransferSpeed = kTransfer_GPIO_fast;
} else {
// clock < 2MHz -> Use GPIO with delay
DAP_SPI_Deinit();
DAP_Data.fast_clock = 0U;
SWD_TransferSpeed = kTransfer_GPIO_normal;
delay = ((CPU_CLOCK/2U) + (clock - 1U)) / clock;
#define CPU_CLOCK_FIXED 80000000
delay = ((CPU_CLOCK_FIXED/2U) + (clock - 1U)) / clock;
if (delay > IO_PORT_WRITE_CYCLES) {
delay -= IO_PORT_WRITE_CYCLES;
delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES;
@ -417,7 +432,7 @@ static uint32_t DAP_SWJ_Sequence(const uint8_t *request, uint8_t *response) {
uint32_t count;
count = *request++;
if (count == 0U) {
if (count == 0U) {
count = 256U;
}
@ -446,7 +461,7 @@ static uint32_t DAP_SWD_Configure(const uint8_t *request, uint8_t *response) {
value = *request;
DAP_Data.swd_conf.turnaround = (value & 0x03U) + 1U;
DAP_Data.swd_conf.data_phase = (value & 0x04U) ? 1U : 0U;
*response = DAP_OK;
#else
*response = DAP_ERROR;
@ -480,7 +495,7 @@ static uint32_t DAP_SWD_Sequence(const uint8_t *request, uint8_t *response) {
while (sequence_count--) {
sequence_info = *request++;
count = sequence_info & SWD_SEQUENCE_CLK;
if (count == 0U) {
if (count == 0U) {
count = 64U;
}
count = (count + 7U) / 8U;
@ -630,7 +645,7 @@ static uint32_t DAP_JTAG_IDCode(const uint8_t *request, uint8_t *response) {
id_error:
#endif
*response = DAP_ERROR;
return ((1U << 16) | 1U);
return ((1U << 16) | 1U);
}
@ -644,11 +659,11 @@ static uint32_t DAP_TransferConfigure(const uint8_t *request, uint8_t *response)
DAP_Data.transfer.idle_cycles = *(request+0);
DAP_Data.transfer.retry_count = (uint16_t) *(request+1) |
(uint16_t)(*(request+2) << 8);
DAP_Data.transfer.match_retry = (uint16_t) *(request+3) |
DAP_Data.transfer.match_retry = (uint16_t) *(request+3) |
(uint16_t)(*(request+4) << 8);
*response = DAP_OK;
return ((5U << 16) | 1U);
return ((5U << 16) | 1U);
}
@ -711,7 +726,7 @@ static uint32_t DAP_SWD_Transfer(const uint8_t *request, uint8_t *response) {
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
post_read = 0U;
}
if (response_value != DAP_TRANSFER_OK) {
if (response_value != DAP_TRANSFER_OK) {
break;
}
// Store previous AP data
@ -1386,14 +1401,14 @@ static uint32_t DAP_JTAG_TransferBlock(const uint8_t *request, uint8_t *response
// Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request++;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
goto end;
}
request_count = (uint32_t)(*(request+0) << 0) |
request_count = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8);
request += 2;
if (request_count == 0U) {
if (request_count == 0U) {
goto end;
}
@ -1549,7 +1564,7 @@ static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) {
DAP_Data.jtag_dev.index = *request;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
*response = DAP_ERROR;
return (1U);
return (1U);
}
// Select JTAG chain
@ -1565,7 +1580,7 @@ static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) {
JTAG_WriteAbort(data);
*response = DAP_OK;
return (1U);
return (1U);
}
#endif
@ -1741,7 +1756,7 @@ uint32_t DAP_ExecuteCommand(const uint8_t *request, uint8_t *response) {
n = DAP_ProcessCommand(request, response);
num += n;
request += (uint16_t)(n >> 16);
response += (uint16_t) n;
response += (uint16_t) n;
}
return (num);
}

View File

@ -1,6 +1,14 @@
/**
* @brief Modify this file to fit esp8266 Uart
*
* @file SWO.c
* @author windowsair
* @brief SWO support
* @change: 2021-02-17: Add basic functions
* @version 0.2
*
* @date 2021-02-17
*
* @copyright Copyright (c) 2021
*
*/
/*
@ -37,15 +45,11 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "uart_modify.h"
#include "swo.h"
EventGroupHandle_t kSWO_Thread_event_group;
EventGroupHandle_t kUART_Monitoe_event_group;
#define SWO_GOT_DATA BIT0
#define SWO_ERROR_TIME_OUT BIT1
#define UART_GOT_DATA BIT0
EventGroupHandle_t kSwoThreadEventGroup;
#if (SWO_STREAM != 0)
@ -61,14 +65,14 @@ EventGroupHandle_t kUART_Monitoe_event_group;
#endif
// use in baudrate setting
static uint8_t USART_Ready = 0U;
#endif /* (SWO_UART != 0) */
#if ((SWO_UART != 0) || (SWO_MANCHESTER != 0))
#define SWO_STREAM_TIMEOUT (50 / portTICK_RATE_MS) /* Stream timeout in ms */
#define SWO_STREAM_TIMEOUT pdMS_TO_TICKS(50) /* Stream timeout in ms */
#define USB_BLOCK_SIZE 512U /* USB Block Size */
#define TRACE_BLOCK_SIZE 64U /* Trace Block Size (2^n: 32...512) */
@ -81,7 +85,7 @@ static uint8_t TraceError[2] = {0U, 0U}; /* Trace Error flags (banked) */
static uint8_t TraceError_n = 0U; /* Active Trace Error bank */
// Trace Buffer
static uint8_t TraceBuf[SWO_BUFFER_SIZE]; /* Trace Buffer (must be 2^n) */
static uint8_t kSwoTraceBuf[SWO_BUFFER_SIZE]; /* Trace Buffer (must be 2^n) */
static volatile uint32_t TraceIndexI = 0U; /* Incoming Trace Index */
static volatile uint32_t TraceIndexO = 0U; /* Outgoing Trace Index */
static volatile uint8_t TraceUpdate; /* Trace Update Flag */
@ -101,105 +105,35 @@ static void ClearTrace(void);
static void ResumeTrace(void);
static uint32_t GetTraceCount(void);
static uint8_t GetTraceStatus(void);
void SetTraceError(uint8_t flag);
#if (SWO_STREAM != 0)
static volatile uint8_t TransferBusy = 0U; /* Transfer Busy Flag */
static uint32_t TransferSize; /* Current Transfer Size */
volatile uint8_t kSwoTransferBusy = 0U; /* Transfer Busy Flag */
static uint32_t TransferSize; /* Current Transfer Size */
#endif
#if (SWO_UART != 0)
void usart_monitor_task(void *argument)
{
uint32_t index_i;
uint32_t index_o;
uint32_t count;
uint32_t num;
uint32_t flags;
kUART_Monitoe_event_group = xEventGroupCreate();
for (;;)
{
flags = xEventGroupWaitBits(kUART_Monitoe_event_group, UART_GOT_DATA,
pdTRUE, pdFALSE, portMAX_DELAY);
if (flags & UART_GOT_DATA)
{
#if (TIMESTAMP_CLOCK != 0U)
TraceTimestamp.tick = TIMESTAMP_GET();
#endif
index_o = TraceIndexO;
index_i = TraceIndexI;
index_i += TraceBlockSize;
TraceIndexI = index_i;
#if (TIMESTAMP_CLOCK != 0U)
TraceTimestamp.index = index_i;
#endif
num = TRACE_BLOCK_SIZE - (index_i & (TRACE_BLOCK_SIZE - 1U));
// num is the number of bytes we need to read
// (to achieve the size of TRACE_BLOCK_SIZE)
count = index_i - index_o;
// Amount of data that has not been processed yet
// (SWO_BUFFER_SIZE-num): the remaining usable length of the buffer after reading this data
if (count <= (SWO_BUFFER_SIZE - num))
{
index_i &= SWO_BUFFER_SIZE - 1U;
TraceBlockSize = num;
my_uart_read_bytes(USART_PORT, &TraceBuf[index_i], num, 20 / portTICK_RATE_MS);
//pUSART->Receive(&TraceBuf[index_i], num);
}
else
{
// Not enough buffers
TraceStatus = DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED;
}
TraceUpdate = 1U;
#if (SWO_STREAM != 0)
if (TraceTransport == 2U)
{
if (count >= (USB_BLOCK_SIZE - (index_o & (USB_BLOCK_SIZE - 1U))))
{
xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA);
}
}
#endif
}
}
// if (event & ARM_USART_EVENT_RX_OVERFLOW)
// {
// SetTraceError(DAP_SWO_BUFFER_OVERRUN);
// }
// if (event & (ARM_USART_EVENT_RX_BREAK |
// ARM_USART_EVENT_RX_FRAMING_ERROR |
// ARM_USART_EVENT_RX_PARITY_ERROR))
// {
// SetTraceError(DAP_SWO_STREAM_ERROR);
// }
}
// Enable or disable UART SWO Mode
// enable: enable flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t UART_SWO_Mode(uint32_t enable)
uint32_t UART_SWO_Mode(uint32_t enable)
{
int32_t status;
USART_Ready = 0U;
uart_config_t uart_config = {
.baud_rate = 115200,
.baud_rate = 74880,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE};
my_uart_param_config(USART_PORT, &uart_config);
my_uart_param_config(USART_PORT, &uart_config); // register setting
#define BUF_SIZE (1024)
my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0);
//// TODO: remove this
if (enable != 0U)
{
@ -207,6 +141,7 @@ __WEAK uint32_t UART_SWO_Mode(uint32_t enable)
status = my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0);
if (status != ESP_OK)
{
my_uart_driver_delete(USART_PORT);
return (0U);
}
}
@ -214,6 +149,7 @@ __WEAK uint32_t UART_SWO_Mode(uint32_t enable)
{
my_uart_driver_delete(USART_PORT);
}
return (1U);
@ -222,11 +158,12 @@ __WEAK uint32_t UART_SWO_Mode(uint32_t enable)
// Configure UART SWO Baudrate
// baudrate: requested baudrate
// return: actual baudrate or 0 when not configured
__WEAK uint32_t UART_SWO_Baudrate(uint32_t baudrate)
uint32_t UART_SWO_Baudrate(uint32_t baudrate)
{
int32_t status;
//// TODO: There may be bugs.
//int32_t status;
uint32_t index;
uint32_t num;
uint32_t remain_trace_block_size;
if (baudrate > SWO_UART_MAX_BAUDRATE)
{
@ -235,10 +172,8 @@ __WEAK uint32_t UART_SWO_Baudrate(uint32_t baudrate)
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)
{
size_t len = 0;
my_uart_get_buffered_data_len(USART_PORT, &len);
TraceIndexI += my_uart_get_rx_buffered_data_len(USART_PORT);
my_uart_flush(USART_PORT);
TraceIndexI += len;
// pUSART->Control(ARM_USART_CONTROL_RX, 0U);
// if (pUSART->GetStatus().rx_busy)
// {
@ -248,29 +183,21 @@ __WEAK uint32_t UART_SWO_Baudrate(uint32_t baudrate)
}
/////////////
status = my_uart_set_baudrate(USART_PORT, baudrate);
my_uart_set_baudrate(USART_PORT, baudrate);
USART_Ready = 1U;
if (status == ESP_OK)
{
USART_Ready = 1U;
}
else
{
USART_Ready = 0U;
return (0U);
}
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)
{
if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 0U)
{
index = TraceIndexI & (SWO_BUFFER_SIZE - 1U);
num = TRACE_BLOCK_SIZE - (index & (TRACE_BLOCK_SIZE - 1U));
TraceBlockSize = num;
//pUSART->Receive(&TraceBuf[index], num);
my_uart_read_bytes(USART_PORT, &TraceBuf[index], num, 20 / portTICK_RATE_MS);
index = TraceIndexI & (SWO_BUFFER_SIZE - 1U); // TraceIndexI % SWO_BUFFER_SIZE
remain_trace_block_size = TRACE_BLOCK_SIZE - (index & (TRACE_BLOCK_SIZE - 1U)); // index % TRACE_BLOCK_SIZE
TraceBlockSize = remain_trace_block_size;
//pUSART->Receive(&kSwoTraceBuf[index], num);
my_uart_read_bytes_async_swo(index, remain_trace_block_size);
}
//pUSART->Control(ARM_USART_CONTROL_RX, 1U); ////TODO:
//pUSART->Control(ARM_USART_CONTROL_RX, 1U);
}
return (baudrate);
@ -279,7 +206,7 @@ __WEAK uint32_t UART_SWO_Baudrate(uint32_t baudrate)
// Control UART SWO Capture
// active: active flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t UART_SWO_Control(uint32_t active)
uint32_t UART_SWO_Control(uint32_t active)
{
int32_t status;
@ -290,7 +217,8 @@ __WEAK uint32_t UART_SWO_Control(uint32_t active)
return (0U);
}
TraceBlockSize = 1U;
status = my_uart_read_bytes(USART_PORT, &TraceBuf[0], 1U, 20 / portTICK_RATE_MS);
status = my_uart_read_bytes_async_swo(0, 1U);
if (status == ESP_FAIL)
{
return (0U);
@ -299,14 +227,13 @@ __WEAK uint32_t UART_SWO_Control(uint32_t active)
// if (status != ARM_DRIVER_OK)
// {
// return (0U);
// } ////TODO:
// }
}
else
{
size_t len = 0;
my_uart_get_buffered_data_len(USART_PORT, &len);
// no active
TraceIndexI += my_uart_get_rx_buffered_data_len(USART_PORT);
my_uart_flush(USART_PORT);
TraceIndexI += len;
// pUSART->Control(ARM_USART_CONTROL_RX, 0U);
// if (pUSART->GetStatus().rx_busy)
// {
@ -318,20 +245,19 @@ __WEAK uint32_t UART_SWO_Control(uint32_t active)
}
// Start UART SWO Capture
// buf: pointer to buffer for capturing
// index: trace buffer index to read
// num: number of bytes to capture
__WEAK void UART_SWO_Capture(uint8_t *buf, uint32_t num)
static void UART_SWO_Capture(uint32_t index, uint32_t num)
{
TraceBlockSize = num;
my_uart_read_bytes(USART_PORT, buf, num, 20 / portTICK_RATE_MS);
my_uart_read_bytes_async_swo(index, num);
}
// Get UART SWO Pending Trace Count
// return: number of pending trace data bytes
__WEAK uint32_t UART_SWO_GetCount(void)
static uint32_t UART_SWO_GetCount(void)
{
uint32_t count;
//// TODO: There may be bugs.
// if (pUSART->GetStatus().rx_busy)
// {
// count = pUSART->GetRxCount();
@ -340,65 +266,31 @@ __WEAK uint32_t UART_SWO_GetCount(void)
// {
// count = 0U;
// }
my_uart_get_buffered_data_len(USART_PORT, &count);
return (count);
return my_uart_get_rx_buffered_data_len(USART_PORT);
}
#endif /* (SWO_UART != 0) */
#if (SWO_MANCHESTER != 0)
// Enable or disable Manchester SWO Mode
// enable: enable flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t Manchester_SWO_Mode(uint32_t enable)
{
return (0U);
}
// Configure Manchester SWO Baudrate
// baudrate: requested baudrate
// return: actual baudrate or 0 when not configured
__WEAK uint32_t Manchester_SWO_Baudrate(uint32_t baudrate)
{
return (0U);
}
//
// Trace status helper functions
//
// Control Manchester SWO Capture
// active: active flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t Manchester_SWO_Control(uint32_t active)
{
return (0U);
}
// Start Manchester SWO Capture
// buf: pointer to buffer for capturing
// num: number of bytes to capture
__WEAK void Manchester_SWO_Capture(uint8_t *buf, uint32_t num)
{
}
// Get Manchester SWO Pending Trace Count
// return: number of pending trace data bytes
__WEAK uint32_t Manchester_SWO_GetCount(void)
{
return (0U);
}
#endif /* (SWO_MANCHESTER != 0) */
// Clear Trace Errors and Data
static void ClearTrace(void)
{
#if (SWO_STREAM != 0)
if (TraceTransport == 2U)
if (TraceTransport == 2U) // Indicates that we use WinUSB for transfer.
{
if (TransferBusy != 0U)
if (kSwoTransferBusy != 0U)
{
SWO_AbortTransfer();
TransferBusy = 0U;
// Unfortunately, we cannot abort the transmission
// SWO_AbortTransfer();
kSwoTransferBusy = 0U;
}
}
#endif
@ -430,18 +322,10 @@ static void ResumeTrace(void)
index_i &= SWO_BUFFER_SIZE - 1U;
switch (TraceMode)
{
#if (SWO_UART != 0)
case DAP_SWO_UART:
TraceStatus = DAP_SWO_CAPTURE_ACTIVE;
UART_SWO_Capture(&TraceBuf[index_i], 1U);
UART_SWO_Capture(index_i, 1U);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
TraceStatus = DAP_SWO_CAPTURE_ACTIVE;
Manchester_SWO_Capture(&TraceBuf[index_i], 1U);
break;
#endif
default:
break;
}
@ -463,20 +347,15 @@ static uint32_t GetTraceCount(void)
count = TraceIndexI - TraceIndexO;
switch (TraceMode)
{
#if (SWO_UART != 0)
case DAP_SWO_UART:
count += UART_SWO_GetCount();
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
count += Manchester_SWO_GetCount();
break;
#endif
default:
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
} while (TraceUpdate != 0U);
// Synchronously wait for the data to complete
}
else
{
@ -541,14 +420,7 @@ uint32_t SWO_Transport(const uint8_t *request, uint8_t *response)
result = 0U;
}
if (result != 0U)
{
*response = DAP_OK;
}
else
{
*response = DAP_ERROR;
}
*response = result ? DAP_OK : DAP_ERROR;
return ((1U << 16) | 1U);
}
@ -565,6 +437,7 @@ uint32_t SWO_Mode(const uint8_t *request, uint8_t *response)
mode = *request;
// disable swo mode
switch (TraceMode)
{
#if (SWO_UART != 0)
@ -572,11 +445,7 @@ uint32_t SWO_Mode(const uint8_t *request, uint8_t *response)
UART_SWO_Mode(0U);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
Manchester_SWO_Mode(0U);
break;
#endif
default:
break;
}
@ -591,34 +460,18 @@ uint32_t SWO_Mode(const uint8_t *request, uint8_t *response)
result = UART_SWO_Mode(1U);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
result = Manchester_SWO_Mode(1U);
break;
#endif
default:
result = 0U;
break;
}
if (result != 0U)
{
TraceMode = mode;
}
else
{
TraceMode = DAP_SWO_OFF;
}
// DAP_SWO_OFF -> has error
TraceMode = result ? mode : DAP_SWO_OFF;
TraceStatus = 0U;
if (result != 0U)
{
*response = DAP_OK;
}
else
{
*response = DAP_ERROR;
}
*response = result ? DAP_OK : DAP_ERROR;
return ((1U << 16) | 1U);
}
@ -644,11 +497,7 @@ uint32_t SWO_Baudrate(const uint8_t *request, uint8_t *response)
baudrate = UART_SWO_Baudrate(baudrate);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
baudrate = Manchester_SWO_Baudrate(baudrate);
break;
#endif
default:
baudrate = 0U;
break;
@ -681,7 +530,9 @@ uint32_t SWO_Control(const uint8_t *request, uint8_t *response)
if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE))
{
if (active)
// active status: request != now status
if (active) // request: active
{
ClearTrace();
}
@ -692,39 +543,32 @@ uint32_t SWO_Control(const uint8_t *request, uint8_t *response)
result = UART_SWO_Control(active);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
result = Manchester_SWO_Control(active);
break;
#endif
default:
result = 0U;
break;
}
if (result != 0U)
{
// success done
TraceStatus = active;
#if (SWO_STREAM != 0)
if (TraceTransport == 2U)
if (TraceTransport == 2U) // Indicates that we use WinUSB for transfer.
{
xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA);
xEventGroupSetBits(kSwoThreadEventGroup, SWO_GOT_DATA);
}
#endif
}
}
else
{
// request: active but already actived
result = 1U;
}
if (result != 0U)
{
*response = DAP_OK;
}
else
{
*response = DAP_ERROR;
}
*response = result ? DAP_OK : DAP_ERROR;
return ((1U << 16) | 1U);
}
@ -793,6 +637,7 @@ uint32_t SWO_ExtendedStatus(const uint8_t *request, uint8_t *response)
TraceUpdate = 0U;
index = TraceTimestamp.index;
tick = TraceTimestamp.tick;
vTaskDelay(pdMS_TO_TICKS(10));
} while (TraceUpdate != 0U);
*response++ = (uint8_t)(index >> 0);
*response++ = (uint8_t)(index >> 8);
@ -824,6 +669,8 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
status = GetTraceStatus();
count = GetTraceCount();
// transport 1: use DAP SWO command
// transport 2: WinUSB
if (TraceTransport == 1U)
{
n = (uint32_t)(*(request + 0) << 0) |
@ -839,6 +686,7 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
}
else
{
// if use winusb, then nothing to do.
count = 0U;
}
@ -852,7 +700,7 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
for (i = index, n = count; n; n--)
{
i &= SWO_BUFFER_SIZE - 1U;
*response++ = TraceBuf[i++];
*response++ = kSwoTraceBuf[i++];
}
TraceIndexO = index + count;
ResumeTrace();
@ -867,78 +715,171 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
void SWO_TransferComplete(void)
{
TraceIndexO += TransferSize;
TransferBusy = 0U;
kSwoTransferBusy = 0U;
ResumeTrace();
xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA);
xEventGroupSetBits(kSwoThreadEventGroup, SWO_GOT_DATA);
}
// SWO Thread
void SWO_Thread(void *argument)
void SWO_Thread()
{
uint32_t timeout;
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;
(void)argument;
timeout = portMAX_DELAY;
kSWO_Thread_event_group = xEventGroupCreate();
uint32_t index_i;
uint32_t index_o;
uint32_t remain_trace_block_size;
TickType_t timeout = portMAX_DELAY;
kSwoThreadEventGroup = xEventGroupCreate();
for (;;)
{
flags = xEventGroupWaitBits(kSWO_Thread_event_group, SWO_GOT_DATA | SWO_ERROR_TIME_OUT,
/*
Here, our event group handles two main types of events:
1. `SWO_GOT_DATA` : The SWO package may be ready to send.
2. `UART_GOT_DATA` : The uart transfer event is complete and we can start reading.
Note that the `SWO_ERROR_TIME_OUT` flag is only used for internal processing, only when the status is
inactive can it be set.
We deal with uart events first.
Currently, SWO events are always handled.
*/
flags = xEventGroupWaitBits(kSwoThreadEventGroup, SWO_GOT_DATA | UART_GOT_DATA | SWO_ERROR_TIME_OUT,
pdTRUE, pdFALSE, timeout);
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)
if (!(flags & UART_GOT_DATA) && !(flags & SWO_GOT_DATA))
{
timeout = SWO_STREAM_TIMEOUT;
if (TraceMode != DAP_SWO_OFF && my_uart_get_rx_buffered_data_len(USART_PORT) >= kSWO_read_num)
{
flags = UART_GOT_DATA;
}
}
if (flags & UART_GOT_DATA)
{
// The data is still in the uart buffer,
// and the data in the uart needs to be read into the SWO buffer
my_uart_read_bytes(USART_PORT, &kSwoTraceBuf[kSWO_read_index], kSWO_read_num, pdMS_TO_TICKS(20));
index_o = TraceIndexO;
TraceIndexI += TraceBlockSize;
index_i = TraceIndexI;
#if (TIMESTAMP_CLOCK != 0U)
TraceTimestamp.tick = TIMESTAMP_GET();
TraceTimestamp.index = index_i;
#endif
remain_trace_block_size = TRACE_BLOCK_SIZE - (index_i & (TRACE_BLOCK_SIZE - 1U));
// remain_trace_block_size is the number of bytes we need to read
// (to achieve the size of TRACE_BLOCK_SIZE)
count = index_i - index_o;
// Amount of data that has not been processed yet
// (SWO_BUFFER_SIZE-num): the remaining usable length of the buffer after reading this data
if (count <= (SWO_BUFFER_SIZE - remain_trace_block_size))
{
// index_i % 4096
index_i &= SWO_BUFFER_SIZE - 1U;
TraceBlockSize = remain_trace_block_size;
my_uart_read_bytes_async_swo(index_i, remain_trace_block_size);
//pUSART->Receive(&kSwoTraceBuf[index_i], num);
}
else
{
// Not enough buffers
TraceStatus = DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED;
}
TraceUpdate = 1U;
#if (SWO_STREAM != 0)
if (TraceTransport == 2U) // Indicates that we use WinUSB for transfer.
{
// unsent length >= remaining length of the USB block
//// TODO: may be we can remove this
if (count >= (USB_BLOCK_SIZE - (index_o & (USB_BLOCK_SIZE - 1U))))
{
flags = SWO_GOT_DATA;
}
}
#endif
}
// xEventGroupClearBits
/*
`SWO_GOT_DATA` may be set in the following situations:
- The SWO status requested by `SWD_contorl` is different from the current SWO status.
- When `SWO_TransferComplete` is called, and there may be potentially unsent data in the buffer.
- monitor task believes we need to send data that is already long enough.
Note: The processing of the following code segment will always be executed,
and should be ensured to be stable enough.
TODO: The time interval for executing the code is not guaranteed.
*/
if (!(TraceStatus & DAP_SWO_CAPTURE_ACTIVE))
{
flags = SWO_ERROR_TIME_OUT;
timeout = portMAX_DELAY;
}
else
{
timeout = portMAX_DELAY;
flags = SWO_ERROR_TIME_OUT;
timeout = pdMS_TO_TICKS(150);
}
if (TransferBusy == 0U)
if (kSwoTransferBusy)
{
count = GetTraceCount();
if (count != 0U)
continue;
}
count = GetTraceCount();
if (count != 0U)
{
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n)
{
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n)
count = n;
}
if ((flags & SWO_ERROR_TIME_OUT) == 0)
{
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U)
{
count = n;
count &= ~(USB_BLOCK_SIZE - 1U); // Take down to the nearest number that is a multiple of USB_BLOCK_SIZE
}
if ((flags & SWO_ERROR_TIME_OUT) == 0)
else
{
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U)
n = USB_BLOCK_SIZE - i;
if (count >= n)
{
count &= ~(USB_BLOCK_SIZE - 1U);
// Take down to the nearest number that is a multiple of USB_BLOCK_SIZE
count = n; // The number of bytes to be sent exceeds the remain USB block size.
}
else
{
n = USB_BLOCK_SIZE - i;
if (count >= n)
{
count = n;
}
else
{
count = 0U;
}
count = 0U; // Haven't received a full USB block yet.
}
}
if (count != 0U)
{
TransferSize = count;
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count); //through USB
}
}
// Notify that there is data available for transmission
if (count != 0U)
{
TransferSize = count;
kSwoTransferBusy = 1U;
SWO_QueueTransfer(&kSwoTraceBuf[index], count); // through USB
}
}
}
// For all exceptions, we have handled them directly in the interrupt handlers.
}
#endif /* (SWO_STREAM != 0) */

View File

@ -1,286 +1,528 @@
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 1. December 2017
* $Revision: V2.0.0
*
* Project: CMSIS-DAP Source
* Title: SW_DP.c CMSIS-DAP SW DP I/O
*
*---------------------------------------------------------------------------*/
#include "DAP_config.h"
#include "DAP.h"
// SW Macros
#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR
#define SW_CLOCK_CYCLE() \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
PIN_SWCLK_SET(); \
PIN_DELAY()
#define SW_WRITE_BIT(bit) \
PIN_SWDIO_OUT(bit); \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
PIN_SWCLK_SET(); \
PIN_DELAY()
#define SW_READ_BIT(bit) \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
bit = PIN_SWDIO_IN(); \
PIN_SWCLK_SET(); \
PIN_DELAY()
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
// Generate SWJ Sequence
// count: sequence bit count
// data: pointer to sequence bit data
// return: none
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
void SWJ_Sequence (uint32_t count, const uint8_t *data) {
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--;
}
}
#endif
// Generate SWD Sequence
// info: sequence information
// swdo: pointer to SWDIO generated data
// swdi: pointer to SWDIO captured data
// return: none
#if (DAP_SWD != 0)
void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
uint32_t val;
uint32_t bit;
uint32_t n, k;
n = info & SWD_SEQUENCE_CLK;
if (n == 0U) {
n = 64U;
}
if (info & SWD_SEQUENCE_DIN) {
while (n) {
val = 0U;
for (k = 8U; k && n; k--, n--) {
SW_READ_BIT(bit);
val >>= 1;
val |= bit << 7;
}
val >>= k;
*swdi++ = (uint8_t)val;
}
} else {
while (n) {
val = *swdo++;
for (k = 8U; k && n; k--, n--) {
SW_WRITE_BIT(val);
val >>= 1;
}
}
}
}
#endif
#if (DAP_SWD != 0)
// SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
#define SWD_TransferFunction(speed) /**/ \
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); \
}
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_FAST()
SWD_TransferFunction(Fast)
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
SWD_TransferFunction(Slow)
// SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
uint8_t SWD_Transfer(uint32_t request, uint32_t *data) {
if (DAP_Data.fast_clock) {
return SWD_TransferFast(request, data);
} else {
return SWD_TransferSlow(request, data);
}
}
#endif /* (DAP_SWD != 0) */
/*
* Copyright (c) 2013-2017 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ----------------------------------------------------------------------
*
* $Date: 1. December 2017
* $Revision: V2.0.0
*
* Project: CMSIS-DAP Source
* Title: SW_DP.c CMSIS-DAP SW DP I/O
*
*---------------------------------------------------------------------------*/
/**
* @file SW_DP.c
* @author windowsair
* @brief Adaptation of GPIO and SPI
* @change:
* 2021-2-10 Support GPIO and SPI for SWD sequence / SWJ sequence / SWD transfer
* Note: SWD sequence not yet tested
* @version 0.1
* @date 2021-2-10
*
* @copyright Copyright (c) 2021
*
*/
#include "DAP_config.h"
#include "DAP.h"
#include "spi_op.h"
#include "spi_switch.h"
#include "dap_utility.h"
// Debug
#define PRINT_SWD_PROTOCOL 0
// SW Macros
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR
// Space for time in the original version,
// and time for space in our implementation
#define SW_CLOCK_CYCLE() \
PIN_SWCLK_CLR(); \
if (need_delay) { PIN_DELAY(); } \
PIN_SWCLK_SET(); \
if (need_delay) { PIN_DELAY(); }
#define SW_WRITE_BIT(bit) \
PIN_SWDIO_OUT(bit); \
PIN_SWCLK_CLR(); \
if (need_delay) { PIN_DELAY(); } \
PIN_SWCLK_SET(); \
if (need_delay) { PIN_DELAY(); }
#define SW_READ_BIT(bit) \
PIN_SWCLK_CLR(); \
if (need_delay) { PIN_DELAY(); } \
bit = PIN_SWDIO_IN(); \
PIN_SWCLK_SET(); \
if (need_delay) { PIN_DELAY(); }
uint8_t SWD_TransferSpeed = kTransfer_GPIO_normal;
void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay);
void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data);
void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi);
void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi);
// Generate SWJ Sequence
// count: sequence bit count
// data: pointer to sequence bit data
// return: none
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
void SWJ_Sequence (uint32_t count, const uint8_t *data) {
// if (count != 8 && count != 16 && count!= 51)
// {
// printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count);
// return;
// }
if(SWD_TransferSpeed == kTransfer_SPI) {
SWJ_Sequence_SPI(count, data);
} else {
SWJ_Sequence_GPIO(count, data, 1);
}
}
void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay) {
uint32_t val;
uint32_t n;
val = 0U;
n = 0U;
while (count--) {
if (n == 0U) {
val = *data++;
n = 8U;
}
if (val & 1U) {
PIN_SWDIO_TMS_SET();
} else {
PIN_SWDIO_TMS_CLR();
}
SW_CLOCK_CYCLE();
val >>= 1;
n--;
}
}
void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data) {
DAP_SPI_Enable();
DAP_SPI_WriteBits(count, data);
}
#endif
// Generate SWD Sequence
// info: sequence information
// swdo: pointer to SWDIO generated data
// swdi: pointer to SWDIO captured data
// return: none
#if (DAP_SWD != 0)
void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
if (SWD_TransferSpeed == kTransfer_SPI) {
SWD_Sequence_SPI(info, swdo, swdi);
} else {
SWD_Sequence_GPIO(info, swdo, swdi);
}
}
void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
const uint8_t need_delay = 1;
uint32_t val;
uint32_t bit;
uint32_t n, k;
n = info & SWD_SEQUENCE_CLK;
if (n == 0U) {
n = 64U;
}
// n = 1 ~ 64
// LSB
if (info & SWD_SEQUENCE_DIN) {
while (n) {
val = 0U;
for (k = 8U; k && n; k--, n--) {
SW_READ_BIT(bit);
val >>= 1;
val |= bit << 7;
}
val >>= k;
*swdi++ = (uint8_t)val;
}
} else {
while (n) {
val = *swdo++;
for (k = 8U; k && n; k--, n--) {
SW_WRITE_BIT(val);
val >>= 1;
}
}
}
}
void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
uint32_t n;
n = info & SWD_SEQUENCE_CLK;
if (n == 0U) {
n = 64U;
}
// n = 1 ~ 64
if (info & SWD_SEQUENCE_DIN) {
DAP_SPI_ReadBits(n, swdi);
} else {
DAP_SPI_WriteBits(n, swdo);
}
}
#endif
#if (DAP_SWD != 0)
// SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) {
//// FIXME: overrun detection
// SPI transfer mode does not require operations such as PIN_DELAY
uint8_t ack;
// uint32_t bit;
uint32_t val;
uint8_t parity;
uint8_t computedParity;
uint32_t n;
const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */
uint8_t requestByte; /* LSB */
DAP_SPI_Enable();
requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U);
/* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */
#if (PRINT_SWD_PROTOCOL == 1)
switch (requestByte)
{
case 0xA5U:
printf("IDCODE\r\n");
break;
case 0xA9U:
printf("W CTRL/STAT\r\n");
break;
case 0xBDU:
printf("RDBUFF\r\n");
break;
case 0x8DU:
printf("R CTRL/STAT\r\n");
break;
case 0x81U:
printf("W ABORT\r\n");
break;
case 0xB1U:
printf("W SELECT\r\n");
break;
case 0xBBU:
printf("W APc\r\n");
break;
case 0x9FU:
printf("R APc\r\n");
break;
case 0x8BU:
printf("W AP4\r\n");
break;
case 0xA3U:
printf("W AP0\r\n");
break;
case 0X87U:
printf("R AP0\r\n");
break;
case 0xB7U:
printf("R AP8\r\n");
break;
default:
//W AP8
printf("Unknown:%08x\r\n", requestByte);
break;
}
#endif
if (request & DAP_TRANSFER_RnW) {
/* Read data */
DAP_SPI_Send_Header(requestByte, &ack, 0); // 0 Trn After ACK
if (ack == DAP_TRANSFER_OK) {
DAP_SPI_Read_Data(&val, &parity);
computedParity = ParityEvenUint32(val);
if ((computedParity ^ parity) & 1U) {
ack = DAP_TRANSFER_ERROR;
}
if (data) { *data = val; }
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
DAP_Data.timestamp = TIMESTAMP_GET();
}
}
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
DAP_SPI_Generate_Cycle(1);
#if (PRINT_SWD_PROTOCOL == 1)
printf("WAIT\r\n");
#endif
// return DAP_TRANSFER_WAIT;
}
else {
/* Protocol error */
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
DAP_SPI_Enable();
DAP_SPI_Protocol_Error_Read();
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
#if (PRINT_SWD_PROTOCOL == 1)
printf("Protocol Error: Read\r\n");
#endif
}
return ((uint8_t)ack);
}
else {
/* Write data */
parity = ParityEvenUint32(*data);
DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK
if (ack == DAP_TRANSFER_OK) {
DAP_SPI_Write_Data(*data, parity);
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
DAP_Data.timestamp = TIMESTAMP_GET();
}
/* Idle cycles */
n = DAP_Data.transfer.idle_cycles;
if (n) { DAP_SPI_Generate_Cycle(n); }
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
return ((uint8_t)ack);
}
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
/* already turnaround. */
/* TODO: overrun transfer -> for read */
#if (PRINT_SWD_PROTOCOL == 1)
printf("WAIT\r\n");
#endif
}
else {
/* Protocol error */
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
DAP_SPI_Enable();
DAP_SPI_Protocol_Error_Write();
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
#if (PRINT_SWD_PROTOCOL == 1)
printf("Protocol Error: Write\r\n");
#endif
}
return ((uint8_t)ack);
}
return DAP_TRANSFER_ERROR;
}
static uint8_t SWD_Transfer_GPIO (uint32_t request, uint32_t *data, uint8_t need_delay) {
uint32_t ack;
uint32_t bit;
uint32_t val;
uint32_t parity;
uint32_t n;
/* Packet Request */
parity = 0U;
SW_WRITE_BIT(1U); /* Start Bit */
bit = request >> 0;
SW_WRITE_BIT(bit); /* APnDP Bit */
parity += bit;
bit = request >> 1;
SW_WRITE_BIT(bit); /* RnW Bit */
parity += bit;
bit = request >> 2;
SW_WRITE_BIT(bit); /* A2 Bit */
parity += bit;
bit = request >> 3;
SW_WRITE_BIT(bit); /* A3 Bit */
parity += bit;
SW_WRITE_BIT(parity); /* Parity Bit */
SW_WRITE_BIT(0U); /* Stop Bit */
SW_WRITE_BIT(1U); /* Park Bit */
/* Turnaround */
PIN_SWDIO_OUT_DISABLE();
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
SW_CLOCK_CYCLE();
}
/* Acknowledge response */
SW_READ_BIT(bit);
ack = bit << 0;
SW_READ_BIT(bit);
ack |= bit << 1;
SW_READ_BIT(bit);
ack |= bit << 2;
if (ack == DAP_TRANSFER_OK) { /* OK response */
/* Data transfer */
if (request & DAP_TRANSFER_RnW) {
/* Read data */
val = 0U;
parity = 0U;
for (n = 32U; n; n--) {
SW_READ_BIT(bit); /* Read RDATA[0:31] */
parity += bit;
val >>= 1;
val |= bit << 31;
}
SW_READ_BIT(bit); /* Read Parity */
if ((parity ^ bit) & 1U) {
ack = DAP_TRANSFER_ERROR;
}
if (data) { *data = val; }
/* Turnaround */
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
SW_CLOCK_CYCLE();
}
PIN_SWDIO_OUT_ENABLE();
} else {
/* Turnaround */
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
SW_CLOCK_CYCLE();
}
PIN_SWDIO_OUT_ENABLE();
/* Write data */
val = *data;
parity = 0U;
for (n = 32U; n; n--) {
SW_WRITE_BIT(val); /* Write WDATA[0:31] */
parity += val;
val >>= 1;
}
SW_WRITE_BIT(parity); /* Write Parity Bit */
}
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
DAP_Data.timestamp = TIMESTAMP_GET();
}
/* Idle cycles */
n = DAP_Data.transfer.idle_cycles;
if (n) {
PIN_SWDIO_OUT(0U);
for (; n; n--) {
SW_CLOCK_CYCLE();
}
}
PIN_SWDIO_OUT(1U);
return ((uint8_t)ack);
}
if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
/* WAIT or FAULT response */
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) {
for (n = 32U+1U; n; n--) {
SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */
}
}
/* Turnaround */
for (n = DAP_Data.swd_conf.turnaround; n; n--) {
SW_CLOCK_CYCLE();
}
PIN_SWDIO_OUT_ENABLE();
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) {
PIN_SWDIO_OUT(0U);
for (n = 32U+1U; n; n--) {
SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */
}
}
PIN_SWDIO_OUT(1U);
return ((uint8_t)ack);
}
/* Protocol error */
for (n = DAP_Data.swd_conf.turnaround + 32U + 1U; n; n--) {
SW_CLOCK_CYCLE(); /* Back off data phase */
}
PIN_SWDIO_OUT_ENABLE();
PIN_SWDIO_OUT(1U);
return ((uint8_t)ack);
}
// SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
uint8_t SWD_Transfer(uint32_t request, uint32_t *data) {
switch (SWD_TransferSpeed) {
case kTransfer_SPI:
return SWD_Transfer_SPI(request, data);
case kTransfer_GPIO_fast:
return SWD_Transfer_GPIO(request, data, 0);
case kTransfer_GPIO_normal:
return SWD_Transfer_GPIO(request, data, 1);
default:
return SWD_Transfer_GPIO(request, data, 1);
}
}
#endif /* (DAP_SWD != 0) */

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,295 @@
/**
* @file spi_op.c
* @author windowsair
* @brief Using SPI for common transfer operations
* @change: 2020-11-25 first version
* 2021-2-11 Support SWD sequence
* 2021-3-10 Support 3-wire SPI
* @version 0.3
* @date 2021-3-10
*
* @copyright Copyright (c) 2021
*
*/
#include <stdio.h>
#include <stdbool.h>
#include "esp8266/spi_struct.h"
#include "cmsis_compiler.h"
#include "spi_op.h"
#include "dap_configuration.h"
#define DAP_SPI SPI1
/**
* @brief Calculate integer division and round up
*
* @param A
* @param B
* @return result
*/
__STATIC_FORCEINLINE int div_round_up(int A, int B)
{
return (A + B - 1) / B;
}
/**
* @brief Write bits. LSB & little-endian
* Note: No check. The pointer must be valid.
* @param count Number of bits to be written (<= 64 bits, no length check)
* @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:
{
uint32_t data_buf[2];
uint8_t *pData = (uint8_t *)data_buf;
int i;
for (i = 0; i < div_round_up(count, 8); i++)
{
pData[i] = buf[i];
}
// last byte use mask:
pData[i-1] = pData[i-1] & ((2U >> (count % 8)) - 1U);
DAP_SPI.data_buf[0] = data_buf[0];
DAP_SPI.data_buf[1] = data_buf[1];
}
}
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr) continue;
}
/**
* @brief Read bits. LSB & little-endian
* Note: No check. The pointer must be valid.
* @param count Number of bits to be read (<= 64 bits, no length check)
* @param buf Data Buf
*/
void DAP_SPI_ReadBits(const uint8_t count, uint8_t *buf) {
int i;
uint32_t data_buf[2];
uint8_t * pData = (uint8_t *)data_buf;
DAP_SPI.user.usr_mosi = 0;
DAP_SPI.user.usr_miso = 1;
#if (USE_SPI_SIO == 1)
DAP_SPI.user.sio = true;
#endif
DAP_SPI.user1.usr_miso_bitlen = count - 1U;
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for reading to complete
while (DAP_SPI.cmd.usr) continue;
#if (USE_SPI_SIO == 1)
DAP_SPI.user.sio = false;
#endif
data_buf[0] = DAP_SPI.data_buf[0];
data_buf[1] = DAP_SPI.data_buf[1];
for (i = 0; i < div_round_up(count, 8); i++)
{
buf[i] = pData[i];
}
// last byte use mask:
buf[i-1] = buf[i-1] & ((2 >> (count % 8)) - 1);
}
/**
* @brief Step1: Packet Request
*
* @param packetHeaderData data from host
* @param ack ack from target
* @param TrnAfterACK num of trn after ack
*/
__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;
#if (USE_SPI_SIO == 1)
DAP_SPI.user.sio = true;
#endif
// 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) continue;
#if (USE_SPI_SIO == 1)
DAP_SPI.user.sio = false;
#endif
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;
#if (USE_SPI_SIO == 1)
DAP_SPI.user.sio = true;
#endif
// 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) continue;
#if (USE_SPI_SIO == 1)
DAP_SPI.user.sio = false;
#endif
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) continue;
}
/**
* @brief Generate Clock Cycle
*
* @param num Cycle Num
*/
__FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num)
{
//// TODO: It may take long time to generate just one clock
DAP_SPI.user.usr_mosi = 1;
DAP_SPI.user.usr_miso = 0;
DAP_SPI.user1.usr_mosi_bitlen = num - 1U;
DAP_SPI.data_buf[0] = 0x00000000U;
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr) continue;
}
/**
* @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;
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr) continue;
}
/**
* @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;
// Start transmission
DAP_SPI.cmd.usr = 1;
// Wait for sending to complete
while (DAP_SPI.cmd.usr) continue;
}

View File

@ -0,0 +1,185 @@
/**
* @file spi_switch.c
* @author windowsair
* @brief Switching between SPI mode and IO mode
* @change: 2020-11-25 first version
* 2021-2-11 Transmission mode switching test passed
* @version 0.2
* @date 2021-2-11
*
* @copyright Copyright (c) 2021
*
*/
#include <stdbool.h>
#include "esp8266/spi_struct.h"
#include "esp8266/pin_mux_register.h"
#include "esp8266/gpio_struct.h"
#include "cmsis_compiler.h"
#include "spi_switch.h"
#include "dap_configuration.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);
#if (USE_SPI_SIO != 1)
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);
#endif // (USE_SPI_SIO != 1)
// 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 Switch to GPIO
* Note: You may be able to pull the pin high in SPI mode, though you cannot set it to LOW
*/
__FORCEINLINE void DAP_SPI_Deinit()
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); // MOSI
#if (USE_SPI_SIO != 1)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12); // MISO
// disable MISO output connect
GPIO.enable_w1tc |= (0x1 << 12);
#endif // (USE_SPI_SIO != 1)
gpio_pin_reg_t pin_reg;
GPIO.enable_w1ts |= (0x1 << 13);
GPIO.pin[13].driver = 1; // OD output
pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(13));
pin_reg.pullup = 0;
WRITE_PERI_REG(GPIO_PIN_REG(13), pin_reg.val);
}
/**
* @brief Use SPI acclerate
*
*/
void DAP_SPI_Enable()
{
// may be unuse
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); // GPIO13 is SPI MOSI pin (Master Data Out)
}
/**
* @brief Disable SPI
* Drive capability not yet known
*/
__FORCEINLINE void DAP_SPI_Disable()
{
;
//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,6 +1,6 @@
/**
* @brief Made some simple modifications to the official UART
*
*
*/
// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
@ -41,6 +41,7 @@
#include "rom/ets_sys.h"
#include "uart_modify.h"
#include "swo.h"
#include "driver/uart_select.h"
#define portYIELD_FROM_ISR() taskYIELD()
@ -70,6 +71,11 @@ typedef struct
} tx_data;
} uart_tx_data_t;
// read:
// hardware FIFO -> `rx_data_buf` -> `rx_ring_buf` -> user buf
typedef struct
{
uart_port_t uart_num; /*!< UART port number*/
@ -118,18 +124,21 @@ typedef struct
static uart_isr_func_t uart_isr_func[UART_NUM_MAX];
// SWO modify
extern EventGroupHandle_t kUART_Monitoe_event_group;
#define UART_GOT_DATA BIT0
extern void SetTraceError(uint8_t flag);
#define DAP_SWO_CAPTURE_ACTIVE (1U << 0)
#define DAP_SWO_CAPTURE_PAUSED (1U << 1)
#define DAP_SWO_STREAM_ERROR (1U << 6)
#define DAP_SWO_BUFFER_OVERRUN (1U << 7)
//
// non thread safe
volatile uint32_t kSWO_read_index = 0;
volatile uint32_t kSWO_read_num = 0;
volatile uint8_t kSWO_uart_notify_enable = 1;
SemaphoreHandle_t kSWO_read_mux = NULL;
esp_err_t my_uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((data_bit < UART_DATA_BITS_MAX), "data bit error", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL();
@ -140,7 +149,6 @@ esp_err_t my_uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_
esp_err_t my_uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data_bit)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((data_bit), "empty pointer", ESP_FAIL);
*(data_bit) = UART[uart_num]->conf0.bit_num;
@ -149,7 +157,6 @@ esp_err_t my_uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data
esp_err_t my_uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL();
@ -160,7 +167,6 @@ esp_err_t my_uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit)
esp_err_t my_uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bit)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((stop_bit), "empty pointer", ESP_FAIL);
(*stop_bit) = UART[uart_num]->conf0.stop_bit_num;
@ -169,7 +175,6 @@ esp_err_t my_uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bit
esp_err_t my_uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK(((parity_mode == UART_PARITY_DISABLE) || (parity_mode == UART_PARITY_EVEN) || (parity_mode == UART_PARITY_ODD)),
"parity_mode error", ESP_ERR_INVALID_ARG);
@ -182,7 +187,6 @@ esp_err_t my_uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode)
esp_err_t my_uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((parity_mode), "empty pointer", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL();
@ -209,8 +213,6 @@ esp_err_t my_uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode)
esp_err_t my_uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL();
UART[uart_num]->clk_div.val = (uint32_t)(UART_CLK_FREQ / baud_rate) & 0xFFFFF;
UART_EXIT_CRITICAL();
@ -219,7 +221,6 @@ esp_err_t my_uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate)
esp_err_t my_uart_get_baudrate(uart_port_t uart_num, uint32_t *baudrate)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((baudrate), "empty pointer", ESP_ERR_INVALID_ARG);
(*baudrate) = (UART_CLK_FREQ / (UART[uart_num]->clk_div.val & 0xFFFFF));
@ -228,7 +229,6 @@ esp_err_t my_uart_get_baudrate(uart_port_t uart_num, uint32_t *baudrate)
esp_err_t my_uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((((inverse_mask & ~UART_LINE_INV_MASK) == 0) || (inverse_mask == 0)), "inverse_mask error", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL();
@ -377,6 +377,7 @@ static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num)
return ESP_OK;
}
// Clear uart interrupts status.
esp_err_t my_uart_clear_intr_status(uart_port_t uart_num, uint32_t mask)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
@ -387,6 +388,7 @@ esp_err_t my_uart_clear_intr_status(uart_port_t uart_num, uint32_t mask)
return ESP_OK;
}
// Set UART interrupt enable
esp_err_t my_uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
@ -407,6 +409,9 @@ esp_err_t my_uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask)
return ESP_OK;
}
// helper function
esp_err_t my_uart_enable_rx_intr(uart_port_t uart_num)
{
return my_uart_enable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
@ -435,6 +440,9 @@ esp_err_t my_uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh)
return ESP_OK;
}
static void uart_intr_service(void *arg)
{
// UART intr process
@ -460,6 +468,7 @@ static void uart_intr_service(void *arg)
} while (++uart_num < UART_NUM_MAX);
}
// setting isr function
esp_err_t my_uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
@ -552,7 +561,7 @@ static void uart_rx_intr_handler_default(void *param)
uart_obj_t *p_uart = (uart_obj_t *)param;
uint8_t uart_num = p_uart->uart_num;
uart_dev_t *uart_reg = UART[uart_num];
int rx_fifo_len = uart_reg->status.rxfifo_cnt;
int rx_fifo_len = uart_reg->status.rxfifo_cnt;
uint8_t buf_idx = 0;
uint32_t uart_intr_status = UART[uart_num]->int_st.val;
uart_event_t uart_event;
@ -718,7 +727,17 @@ static void uart_rx_intr_handler_default(void *param)
else
{
p_uart->rx_buffered_len += p_uart->rx_stash_len;
xEventGroupSetBitsFromISR(kUART_Monitoe_event_group, UART_GOT_DATA, pdFALSE);
// SWO modify
if (kSWO_read_num && p_uart->rx_buffered_len >= kSWO_read_num)
{
if (kSWO_uart_notify_enable)
{
kSWO_uart_notify_enable = 0;
xEventGroupSetBitsFromISR(kSwoThreadEventGroup, UART_GOT_DATA, pdFALSE);
}
}
}
notify = UART_SELECT_READ_NOTIF;
@ -744,7 +763,7 @@ static void uart_rx_intr_handler_default(void *param)
// SWO modify
// Unfortunately, Overflow occurs usually there is no flow control.
// Although the overflow situation often occurs,
// the buffer stability of the serial port is better,
// the buffer stability of the serial port is better,
// and there is basically no data loss.
////TODO: Can we get rid of this code?
SetTraceError(DAP_SWO_BUFFER_OVERRUN);
@ -804,6 +823,7 @@ static void uart_rx_intr_handler_default(void *param)
}
}
// Fill UART tx_fifo and return a number,
// This function by itself is not thread-safe, always call from within a muxed section.
static int uart_fill_fifo(uart_port_t uart_num, const char *buffer, uint32_t len)
@ -904,6 +924,8 @@ int my_uart_write_bytes(uart_port_t uart_num, const char *src, size_t size)
return uart_tx_all(uart_num, src, size);
}
// return min(length, data length in ring buffer)
int my_uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, TickType_t ticks_to_wait)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1));
@ -934,6 +956,7 @@ int my_uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, Tick
}
else
{
// nothing receive
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
return copy_len;
}
@ -974,6 +997,15 @@ int my_uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, Tick
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
UART_EXIT_CRITICAL();
my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
// SWO modify
if (uart_num == 0 && kSWO_read_num && p_uart_obj[0]->rx_buffered_len >= kSWO_read_num)
{
if (kSWO_uart_notify_enable)
{
kSWO_uart_notify_enable = 0;
xEventGroupSetBitsFromISR(kSwoThreadEventGroup, UART_GOT_DATA, pdFALSE);
}
}
}
}
}
@ -994,6 +1026,7 @@ esp_err_t my_uart_get_buffered_data_len(uart_port_t uart_num, size_t *size)
esp_err_t my_uart_flush(uart_port_t uart_num) __attribute__((alias("my_uart_flush_input")));
// flush RX buffer
esp_err_t my_uart_flush_input(uart_port_t uart_num)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
@ -1051,6 +1084,15 @@ esp_err_t my_uart_flush_input(uart_port_t uart_num)
p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
p_uart_obj[uart_num]->rx_buffer_full_flg = false;
UART_EXIT_CRITICAL();
// SWO modify
if (uart_num == 0 && kSWO_read_num && p_uart_obj[0]->rx_buffered_len >= kSWO_read_num)
{
if (kSWO_uart_notify_enable)
{
kSWO_uart_notify_enable = 0;
xEventGroupSetBitsFromISR(kSwoThreadEventGroup, UART_GOT_DATA, pdFALSE);
}
}
}
}
}
@ -1058,7 +1100,7 @@ esp_err_t my_uart_flush_input(uart_port_t uart_num)
p_uart->rx_ptr = NULL;
p_uart->rx_cur_remain = 0;
p_uart->rx_head_ptr = NULL;
uart_reset_rx_fifo(uart_num);
uart_reset_rx_fifo(uart_num); // reset hardware FIFO
my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
xSemaphoreGive(p_uart->rx_mux);
return ESP_OK;
@ -1096,6 +1138,14 @@ esp_err_t my_uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int t
p_uart_obj[uart_num]->rx_buffered_len = 0;
p_uart_obj[uart_num]->wait_tx_done_flg = false;
// SWO modify
if (uart_num == 0)
{
kSWO_read_index = 0;
kSWO_read_num = 0;
kSWO_read_mux = xSemaphoreCreateMutex();
}
if (uart_queue)
{
p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t));
@ -1176,6 +1226,12 @@ esp_err_t my_uart_driver_delete(uart_port_t uart_num)
my_uart_disable_tx_intr(uart_num);
_xt_isr_mask(0x1 << ETS_UART_INUM);
// SWO modify
if (uart_num == 0 && kSWO_read_mux)
{
vSemaphoreDelete(kSWO_read_mux);
}
if (p_uart_obj[uart_num]->tx_fifo_sem)
{
vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem);
@ -1254,3 +1310,27 @@ esp_err_t my_uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh
UART_EXIT_CRITICAL();
return ESP_OK;
}
// SWO modify
esp_err_t my_uart_read_bytes_async_swo(uint32_t index, uint32_t length)
{
if (kSWO_read_num > 0) {
return ESP_FAIL;
}
xSemaphoreTake(kSWO_read_mux, (portTickType)portMAX_DELAY);
kSWO_read_num = length;
kSWO_read_index = index;
kSWO_uart_notify_enable = 1;
xSemaphoreGive(kSWO_read_mux);
return ESP_OK;
}
int my_uart_get_rx_buffered_data_len(uart_port_t uart_num)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_ARG);
return p_uart_obj[uart_num]->rx_buffered_len;
}

View File

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

View File

@ -61,7 +61,7 @@ const uint8_t bosDescriptor[kLengthOfBos] =
0x05, // bLength of this descriptor
USB_DESCRIPTOR_TYPE_BOS, // BOS Descriptor type(Constant)
USBShort(kLengthOfBos), // wLength
0x01, // bNumDeviceCaps
0x01, // bNumDeviceCaps -> only 0x01 for OS2.0 descriptor
// Microsoft OS 2.0 platform capability descriptor header (Table 4)
// See also:

View File

@ -19,15 +19,9 @@
#include "usb_defs.h"
#include "MSOS20Descriptors.h"
// const char *strings_list[] = {
// 0, // reserved: available languages
// "windowsair",
// "CMSIS-DAP v2",
// "1234",
// };
const char *strings_list[] = {
0, // reserved: available languages
0, // reserved: available languages -> iInterface
"windowsair",
"esp8266 CMSIS-DAP",
"1234",
@ -241,8 +235,7 @@ static void handleGetDescriptor(usbip_stage2_header *header)
else
{
os_printf("Sending ALL CONFIG\r\n");
send_stage2_submit(header, 0, header->u.cmd_submit.data_length);
send_stage2_submit(header, 0, sizeof(kUSBd0ConfigDescriptor) + sizeof(kUSBd0InterfaceDescriptor));
send(kSock, kUSBd0ConfigDescriptor, sizeof(kUSBd0ConfigDescriptor), 0);
send(kSock, kUSBd0InterfaceDescriptor, sizeof(kUSBd0InterfaceDescriptor), 0);
}
@ -279,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;
@ -315,16 +309,19 @@ static void handleGetDescriptor(usbip_stage2_header *header)
////TODO:UNIMPLEMENTED
send_stage2_submit(header, 0, 0);
break;
#if (USE_WINUSB == 1)
case USB_DT_BOS:
os_printf("* GET 0x0F BOS DESCRIPTOR\r\n");
send_stage2_submit_data(header, 0, bosDescriptor, sizeof(bosDescriptor));
break;
#else
case USB_DT_HID_REPORT:
os_printf("* GET 0x22 HID REPORT DESCRIPTOR\r\n");
send_stage2_submit_data(header, 0, (void *)kHidReportDescriptor, sizeof(kHidReportDescriptor));
break;
#endif
default:
//// TODO: ms os 1.0 descriptor
os_printf("USB unknown Get Descriptor requested:%d\r\n", header->u.cmd_submit.request.wValue.u8lo);
os_printf("low bit :%d\r\n",header->u.cmd_submit.request.wValue.u8lo);
os_printf("high bit :%d\r\n",header->u.cmd_submit.request.wValue.u8hi);

View File

@ -26,7 +26,12 @@ const uint8_t kUSBd0DeviceDescriptor[0x12] =
{
0x12, // bLength
USB_DT_DEVICE, // bDescriptorType
#if (USE_WINUSB == 1)
USBShort(0x0210), // bcdUSB
#else
USBShort(0x0200), // bcdUSB
#endif
////TODO: Is it also available elsewhere?
// We need to use a device other than the USB-IF standard, set to 0x00

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,215 +1,286 @@
/**
* @file DAP_handle.c
* @brief Handle DAP packets and transaction push
* @version 0.2
* @date 2020-02-04
*
* @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
static uint8_t data_out[DAP_PACKET_SIZE];
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)
dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out);
//handle_dap_data_response(header);
send_stage2_submit(header, 0, 0);
#else
xRingbufferSend(dap_dataIN_handle, data_in, length - sizeof(usbip_stage2_header), portMAX_DELAY);
//os_printf("LENGTH: %d\r\n", length - sizeof(usbip_stage2_header));
xTaskNotifyGive(kDAPTaskHandle);
send_stage2_submit(header, 0, 0);
#endif
}
void handle_dap_data_response(usbip_stage2_header *header)
{
if (dap_respond)
{
send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE);
dap_respond = 0;
}
else
{
send_stage2_submit(header, 0, 0);
}
}
void handle_swo_trace_response(usbip_stage2_header *header)
{
if (swo_trace_respond)
{
swo_trace_respond = 0;
send_stage2_submit_data(header, 0, data_out, 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_PACKET_SIZE * 20, RINGBUF_TYPE_BYTEBUF);
dap_dataOUT_handle = xRingbufferCreate(DAP_PACKET_SIZE * 10, RINGBUF_TYPE_BYTEBUF);
data_response_mux = xSemaphoreCreateMutex();
size_t packetSize;
uint8_t *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 = (uint8_t *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize,
(1 / portTICK_RATE_MS), DAP_PACKET_SIZE);
if (packetSize == 0)
{
break;
}
else if (packetSize < DAP_PACKET_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[0] == ID_DAP_QueueCommands)
item[0] = ID_DAP_ExecuteCommands;
DAP_ProcessCommand(item, data_out);
vRingbufferReturnItem(dap_dataIN_handle, (void *)item);
xRingbufferSend(dap_dataOUT_handle, data_out, DAP_PACKET_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)
{
uint8_t *item;
size_t packetSize = 0;
item = (uint8_t *)xRingbufferReceiveUpTo(dap_dataOUT_handle, &packetSize,
(10 / portTICK_RATE_MS), DAP_PACKET_SIZE);
if (packetSize == DAP_PACKET_SIZE)
{
unpack((uint32_t *)buf, sizeof(usbip_stage2_header));
send_stage2_submit_data((usbip_stage2_header *)buf, 0, item, DAP_PACKET_SIZE);
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
{
buf[3] = 0x3; // command
buf[15] = 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.4
* @change: 2020.02.04 first version
* 2020.11.11 support WinUSB mode
* 2021.02.17 support SWO
*
* @copyright Copyright (c) 2021
*
*/
#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 "swo.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 uint8_t *swo_data_to_send = NULL;
static uint32_t swo_data_num;
// DAP handle
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)
{
#if (SWO_FUNCTION_ENABLE == 1)
if (kSwoTransferBusy)
{
// busy indicates that there is data to be send
printf("swo use data\r\n");
send_stage2_submit_data(header, 0, (void *)swo_data_to_send, swo_data_num);
SWO_TransferComplete();
}
else
{
// nothing to send.
send_stage2_submit(header, 0, 0);
}
#else
send_stage2_submit(header, 0, 0);
#endif
}
// 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;
swo_data_num = num;
}
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,
pdMS_TO_TICKS(1), 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,
pdMS_TO_TICKS(10), 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_fast((usbip_stage2_header *)buf, 0, item->buf, resLength);
#else
send_stage2_submit_data_fast((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]);
}
}

28
main/dap_configuration.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef __DAP_CONFIGURATION_H__
#define __DAP_CONFIGURATION_H__
/**
* @brief Specify the use of WINUSB
*
*/
#define USE_WINUSB 1
/**
* @brief Enable this option, no need to physically connect MOSI and MISO
*
*/
#define USE_SPI_SIO 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,148 +1,181 @@
/* 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\r\n");
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_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_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"
#include "DAP_config.h"
extern void DAP_Setup(void);
extern void DAP_Thread(void *argument);
extern void SWO_Thread();
TaskHandle_t kDAPTaskHandle = NULL;
/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group;
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();
#if (USE_STATIC_IP == 1)
tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_STA);
tcpip_adapter_ip_info_t ip_info;
#define MY_IP4_ADDR(...) IP4_ADDR(__VA_ARGS__)
MY_IP4_ADDR(&ip_info.ip, DAP_IP_ADDRESS);
MY_IP4_ADDR(&ip_info.gw, DAP_IP_GATEWAY);
MY_IP4_ADDR(&ip_info.netmask, DAP_IP_NETMASK);
#undef MY_IP4_ADDR
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info);
#endif // (USE_STATIC_IP == 1)
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()
{
// struct rst_info *rtc_info = system_get_rst_info();
// os_printf("reset reason: %x\n", rtc_info->reason);
// if (rtc_info->reason == REASON_WDT_RST ||
// rtc_info->reason == REASON_EXCEPTION_RST ||
// rtc_info->reason == REASON_SOFT_WDT_RST)
// {
// if (rtc_info->reason == REASON_EXCEPTION_RST)
// {
// os_printf("Fatal exception (%d):\n", rtc_info->exccause);
// }
// os_printf("epc1=0x%08x, epc2=0x%08x, epc3=0x%08x,excvaddr=0x%08x, depc=0x%08x\n",
// rtc_info->epc1, rtc_info->epc2, rtc_info->epc3,
// rtc_info->excvaddr, rtc_info->depc);
// }
ESP_ERROR_CHECK(nvs_flash_init());
initialise_wifi();
wait_for_ip();
DAP_Setup();
timer_init();
xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 14, NULL);
xTaskCreate(DAP_Thread, "DAP_Task", 2048, NULL, 10, &kDAPTaskHandle);
// SWO Trace Task
#if (SWO_FUNCTION_ENABLE == 1)
xTaskCreate(SWO_Thread, "SWO_Task", 512, NULL, 10, NULL);
#endif
// It seems that the task is overly stressful...
}

23
main/monitor.c Normal file
View File

@ -0,0 +1,23 @@
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
void esp_print_tasks(void)
{
char *pbuffer = (char *)calloc(1, 2048);
printf("--------------- heap:%u ---------------------\r\n", esp_get_free_heap_size());
vTaskGetRunTimeStats(pbuffer);
printf("%s", pbuffer);
printf("----------------------------------------------\r\n");
free(pbuffer);
}
void monitor_task()
{
while(1) {
esp_print_tasks();
vTaskDelay(3000 / portTICK_RATE_MS);
}
}

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[305];
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

@ -1,29 +1,52 @@
/**
* @file timer.c
* @brief Hardware timer for DAP timestamp
* @version 0.1
* @change: 2021-02-18 Using the FRC2 timer
*
* @version 0.2
* @date 2020-01-22
*
* @copyright Copyright (c) 2020
*
*
* @copyright Copyright (c) 2021
*
*/
#include <stdint.h>
#include <stdbool.h>
#include "timer.h"
#include "hw_timer.h"
#include "timer_struct.h"
#include "cmsis_compiler.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
void timer_create_task()
/*
Note:
System bus frequency is 80MHz, will not be affected by CPU frequency. The
frequency of UART, SPI, or other peripheral devices, are divided from system
bus frequency, so they will not be affected by CPU frequency either.
*/
#define TIMER_BASE 0x60000600
volatile frc2_struct_t * frc2 = (frc2_struct_t *)(TIMER_BASE + (1) * 0x20);
void timer_init()
{
// FRC1 frequency 80MHz
vPortEnterCritical();
frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz
frc1.ctrl.intr_type = TIMER_EDGE_INT;
frc1.ctrl.reload = 0x01;
frc1.load.data = 0x7FFFFF; // 23bit??
frc1.ctrl.en = 0x01;
frc2->ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz
frc2->ctrl.intr_type = TIMER_EDGE_INT;
frc2->ctrl.reload = 0x01; // enable auto reload
frc2->load.val = 0x7FFFFFFF; // 31bit max
frc2->ctrl.en = 0x01;
vPortExitCritical();
vTaskDelete(NULL);
}
// Timing up to 2147483647(0x7FFFFFFF) / 5000000(5MHz) = 429s
// 0.2 micro-second resolution
uint32_t get_timer_count()
{
return (uint32_t)frc2->count.data;
}

View File

@ -1,6 +1,71 @@
/**
* @file timer.h
* @author windowsair
* @brief esp8266 hardware timer
* @change: 2021-02-18 Add frc2 timer
* @note
* FRC2 is not officially documented. There is no guarantee of its behavior.
* FRC2 may be used for RTC functions. May be reserved for other functions in the future.
*
*
* @version 0.1
* @date 2021-02-18
*
* @copyright Copyright (c) 2021
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef __TIMER_H__
#define __TIMER_H__
void timer_create_task();
#include <stdint.h>
#endif
// FRC2 is a 32-bit countup timer
typedef struct {
union {
struct {
uint32_t data: 32;
};
uint32_t val;
} load;
union {
struct {
uint32_t data: 31;
uint32_t reserved23: 1;
};
uint32_t val;
} count;
union {
struct {
uint32_t div: 6;
uint32_t reload: 1;
uint32_t en: 1;
uint32_t intr_type: 1;
uint32_t reserved24: 23;
};
uint32_t val;
} ctrl;
union {
struct {
uint32_t clr: 1;
uint32_t reserved1: 31;
};
uint32_t val;
} intr;
} frc2_struct_t;
extern volatile frc2_struct_t* frc2;
extern void timer_init();
extern uint32_t get_timer_count();
#endif

View File

@ -181,17 +181,16 @@ static void send_interface_info()
int emulate(uint8_t *buffer, uint32_t length)
{
// usbip_stage2_header header;
#if (USE_WINUSB == 0)
if(fast_reply(buffer, length))
{
return 0;
}
#endif
int command = read_stage2_command((usbip_stage2_header *)buffer, length);
if (command < 0)
{
return -1;
return -1;
}
switch (command)
@ -230,7 +229,7 @@ static int read_stage2_command(usbip_stage2_header *header, uint32_t length)
* - ret_submit
* - cmd_unlink
* - ret_unlink
*
*
* @param data Point to packets header
* @param size Packets header size
*/
@ -254,7 +253,7 @@ static void pack(void *data, int size)
* - ret_submit
* - cmd_unlink
* - ret_unlink
*
*
* @param data Point to packets header
* @param size packets header size
*/
@ -281,6 +280,7 @@ static int handle_submit(usbip_stage2_header *header, uint32_t length)
{
// control endpoint(endpoint 0)
case 0x00:
//// TODO: judge usb setup 8 byte?
handleUSBControlRequest(header);
break;
@ -355,6 +355,26 @@ void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, co
}
}
void send_stage2_submit_data_fast(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length)
{
uint8_t * send_buf = (uint8_t *)req_header;
req_header->base.command = USBIP_STAGE2_RSP_SUBMIT;
req_header->base.direction = !(req_header->base.direction);
memset(&(req_header->u.ret_submit), 0, sizeof(usbip_stage2_header_ret_submit));
req_header->u.ret_submit.status = status;
req_header->u.ret_submit.data_length = data_length;
pack(req_header, sizeof(usbip_stage2_header));
// payload
memcpy(&send_buf[sizeof(usbip_stage2_header)], data, data_length);
send(kSock, send_buf, sizeof(usbip_stage2_header) + data_length, 0);
}
static void handle_unlink(usbip_stage2_header *header)
{
os_printf("s2 handling cmd unlink...\r\n");

View File

@ -15,5 +15,7 @@ int attach(uint8_t *buffer, uint32_t length);
int emulate(uint8_t *buffer, uint32_t length);
void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void * const data, int32_t data_length);
void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t data_length);
void send_stage2_submit_data_fast(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length);
#endif

View File

@ -3,9 +3,9 @@
* @brief Fill in your wifi configuration information here.
* @version 0.1
* @date 2020-01-22
*
*
* @copyright Copyright (c) 2020
*
*
*/
#ifndef __WIFI_CONFIGURATION__
#define __WIFI_CONFIGURATION__
@ -13,8 +13,15 @@
#define WIFI_SSID "DAP"
#define WIFI_PASS "12345678"
#define PORT 3240
#define USE_STATIC_IP 1
// If you don't want to specify the ip configuration, then ignore the following items.
#define DAP_IP_ADDRESS 192, 168, 137, 123
#define DAP_IP_GATEWAY 192, 168, 137, 1
#define DAP_IP_NETMASK 255, 255, 255, 0
// DO NOT CHANGE
#define PORT 3240
#define CONFIG_EXAMPLE_IPV4 1
#endif
#endif

355
sdkconfig
View File

@ -10,6 +10,8 @@ CONFIG_IDF_TARGET="esp8266"
#
CONFIG_SDK_TOOLPREFIX="xtensa-lx106-elf-"
CONFIG_BOOTLOADER_INIT_SPI_FLASH=y
# CONFIG_BOOTLOADER_DISABLE_JTAG_IO is not set
# CONFIG_BOOTLOADER_FAST_BOOT is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
@ -18,6 +20,7 @@ CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
CONFIG_LOG_BOOTLOADER_LEVEL=3
# CONFIG_BOOTLOADER_APP_TEST is not set
CONFIG_BOOTLOADER_STORE_OFFSET=0x0
CONFIG_ESPTOOLPY_PORT="/dev/ttyS5"
# CONFIG_ESPTOOLPY_BAUD_115200B is not set
# CONFIG_ESPTOOLPY_BAUD_230400B is not set
@ -83,14 +86,18 @@ CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set
CONFIG_APP_UPDATE_CHECK_APP_SUM=y
CONFIG_APP_UPDATE_CHECK_APP_HASH=y
# CONFIG_AWS_IOT_SDK is not set
# CONFIG_USING_ESP_CONSOLE is not set
CONFIG_APP_COMPILE_TIME_DATE=y
# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set
# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set
# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set
# CONFIG_ENABLE_COAP is not set
CONFIG_ESP_TLS_USING_MBEDTLS=y
# CONFIG_ESP_TLS_USING_WOLFSSL is not set
# CONFIG_ESP_TLS_SERVER is not set
# CONFIG_ESP_TLS_PSK_VERIFICATION is not set
# CONFIG_ESP_WOLFSSL_INTERNAL is not set
# CONFIG_WOLFSSL_DEBUG is not set
# CONFIG_ESP8266_NMI_WDT is not set
# CONFIG_ESP8266_DEFAULT_CPU_FREQ_80 is not set
CONFIG_ESP8266_DEFAULT_CPU_FREQ_160=y
CONFIG_ESP8266_DEFAULT_CPU_FREQ_MHZ=160
@ -102,60 +109,120 @@ CONFIG_ESP_FILENAME_MACRO_NO_PATH=y
# CONFIG_ESP_FILENAME_MACRO_NULL is not set
CONFIG_USING_NEW_ETS_VPRINTF=y
# CONFIG_LINK_ETS_PRINTF_TO_IRAM is not set
CONFIG_ETS_PRINTF_EXIT_WHEN_FLASH_RW=y
CONFIG_SOC_FULL_ICACHE=y
CONFIG_SOC_IRAM_SIZE=0x8000
CONFIG_CONSOLE_UART_DEFAULT=y
# CONFIG_CONSOLE_UART_CUSTOM is not set
# CONFIG_CONSOLE_UART_NONE is not set
CONFIG_CONSOLE_UART_NUM=0
CONFIG_CONSOLE_UART_BAUDRATE=74880
# CONFIG_UART0_SWAP_IO is not set
# CONFIG_DISABLE_ROM_UART_PRINT is not set
# CONFIG_PANIC_FULL_STACK is not set
# CONFIG_ESP_PANIC_PRINT_HALT is not set
CONFIG_ESP_PANIC_PRINT_REBOOT=y
# CONFIG_ESP_PANIC_SILENT_REBOOT is not set
CONFIG_MAIN_TASK_STACK_SIZE=3584
CONFIG_TASK_WDT=y
CONFIG_TASK_WDT_PANIC=y
# CONFIG_TASK_WDT_TIMEOUT_13N is not set
# CONFIG_TASK_WDT_TIMEOUT_14N is not set
CONFIG_TASK_WDT_TIMEOUT_15N=y
CONFIG_TASK_WDT_TIMEOUT_S=15
# CONFIG_ESP_PANIC_GDBSTUB is not set
CONFIG_RESET_REASON=y
CONFIG_WIFI_PPT_TASKSTACK_SIZE=2048
CONFIG_EVENT_LOOP_STACK_SIZE=2048
CONFIG_WIFI_PPT_TASKSTACK_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
CONFIG_ESP8266_TIME_SYSCALL_USE_FRC1=y
# CONFIG_ESP8266_TIME_SYSCALL_USE_NONE is not set
# CONFIG_PM_ENABLE is not set
CONFIG_SCAN_AP_MAX=99
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_AMPDU_RX_ENABLED=y
CONFIG_ESP8266_WIFI_RX_BA_WIN_SIZE=6
# 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
CONFIG_ESP8266_WIFI_ENABLE_WPA3_SAE=y
# CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE is not set
CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y
# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set
CONFIG_ESP_PHY_INIT_DATA_VDD33_CONST=33
CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER=21
CONFIG_ESP8266_HSPI_HIGH_THROUGHPUT=y
# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584
CONFIG_ESP_TIMER_TASK_STACK_SIZE=2048
# CONFIG_ESP_CONSOLE_UART_DEFAULT is not set
CONFIG_ESP_CONSOLE_UART_CUSTOM=y
# CONFIG_ESP_CONSOLE_UART_NONE is not set
# CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0 is not set
CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_1=y
CONFIG_ESP_CONSOLE_UART_NUM=1
CONFIG_ESP_CONSOLE_UART_BAUDRATE=74880
# CONFIG_ESP_UART0_SWAP_IO is not set
# CONFIG_ESP_TASK_WDT is not set
# CONFIG_ESP_TASK_WDT_TIMEOUT_13N is not set
# CONFIG_ESP_TASK_WDT_TIMEOUT_14N is not set
CONFIG_ESP_TASK_WDT_TIMEOUT_15N=y
CONFIG_ESP_TASK_WDT_TIMEOUT_S=15
# CONFIG_ESP_EVENT_LOOP_PROFILING is not set
CONFIG_ESP_EVENT_POST_FROM_ISR=y
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set
CONFIG_HTTP_BUF_SIZE=512
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
CONFIG_HTTPD_MAX_URI_LEN=512
CONFIG_OTA_BUF_SIZE=256
# CONFIG_OTA_ALLOW_HTTP is not set
# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set
CONFIG_FATFS_CODEPAGE_437=y
# CONFIG_FATFS_CODEPAGE_720 is not set
# CONFIG_FATFS_CODEPAGE_737 is not set
# CONFIG_FATFS_CODEPAGE_771 is not set
# CONFIG_FATFS_CODEPAGE_775 is not set
# CONFIG_FATFS_CODEPAGE_850 is not set
# CONFIG_FATFS_CODEPAGE_852 is not set
# CONFIG_FATFS_CODEPAGE_855 is not set
# CONFIG_FATFS_CODEPAGE_857 is not set
# CONFIG_FATFS_CODEPAGE_860 is not set
# CONFIG_FATFS_CODEPAGE_861 is not set
# CONFIG_FATFS_CODEPAGE_862 is not set
# CONFIG_FATFS_CODEPAGE_863 is not set
# CONFIG_FATFS_CODEPAGE_864 is not set
# CONFIG_FATFS_CODEPAGE_865 is not set
# CONFIG_FATFS_CODEPAGE_866 is not set
# CONFIG_FATFS_CODEPAGE_869 is not set
# CONFIG_FATFS_CODEPAGE_932 is not set
# CONFIG_FATFS_CODEPAGE_936 is not set
# CONFIG_FATFS_CODEPAGE_949 is not set
# CONFIG_FATFS_CODEPAGE_950 is not set
CONFIG_FATFS_CODEPAGE=437
CONFIG_FATFS_LFN_NONE=y
# CONFIG_FATFS_LFN_HEAP is not set
# CONFIG_FATFS_LFN_STACK is not set
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=y
CONFIG_FMB_COMM_MODE_TCP_EN=y
CONFIG_FMB_TCP_PORT_DEFAULT=502
CONFIG_FMB_TCP_PORT_MAX_CONN=5
CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
CONFIG_FMB_QUEUE_LENGTH=20
CONFIG_FMB_PORT_TASK_STACK_SIZE=4096
CONFIG_FMB_SERIAL_BUF_SIZE=256
CONFIG_FMB_PORT_TASK_PRIO=10
CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y
CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233
CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20
CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
CONFIG_FMB_CONTROLLER_STACK_SIZE=4096
CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20
CONFIG_FMB_TIMER_GROUP=0
CONFIG_FMB_TIMER_INDEX=0
# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set
# CONFIG_DISABLE_FREERTOS is not set
CONFIG_FREERTOS_UNICORE=y
# CONFIG_FREERTOS_ENABLE_REENT is not set
CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_MAX_HOOK=2
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024
CONFIG_FREERTOS_ISR_STACKSIZE=512
@ -167,7 +234,10 @@ CONFIG_TASK_SWITCH_FASTER=y
# CONFIG_ENABLE_FREERTOS_SLEEP is not set
# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set
# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
CONFIG_HEAP_DISABLE_IRAM=y
# CONFIG_HEAP_TRACING is not set
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
@ -177,74 +247,84 @@ CONFIG_LOG_DEFAULT_LEVEL_ERROR=y
CONFIG_LOG_DEFAULT_LEVEL=1
CONFIG_LOG_COLORS=y
# CONFIG_LOG_SET_LEVEL is not set
CONFIG_LWIP_USE_IRAM=y
CONFIG_LWIP_HIGH_THROUGHPUT=y
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_ENABLE_NONBLOCK_SPEEDUP=y
CONFIG_SET_SOLINGER_DEFAULT=y
CONFIG_ESP_UDP_SYNC_SEND=y
CONFIG_ESP_UDP_SYNC_RETRY_MAX=5
CONFIG_LWIP_LOCAL_HOSTNAME="espressif"
CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
# CONFIG_LWIP_L2_TO_L3_COPY is not set
CONFIG_LWIP_IRAM_OPTIMIZATION=y
CONFIG_LWIP_TIMERS_ONDEMAND=y
CONFIG_LWIP_MAX_SOCKETS=10
# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set
# CONFIG_LWIP_SO_LINGER is not set
CONFIG_LWIP_SO_REUSE=y
CONFIG_LWIP_SO_REUSE_RXTOALL=y
# CONFIG_LWIP_SO_RCVBUF is not set
CONFIG_LWIP_RECV_BUFSIZE_DEFAULT=11680
CONFIG_LWIP_TCP_CLOSE_TIMEOUT_MS_DEFAULT=10000
CONFIG_LWIP_IP_FRAG=y
CONFIG_LWIP_IP_REASSEMBLY=y
CONFIG_LWIP_IP_REASS_MAX_PBUFS=10
# CONFIG_LWIP_IP_SOF_BROADCAST is not set
# CONFIG_LWIP_IP_SOF_BROADCAST_RECV is not set
CONFIG_LWIP_ICMP=y
# CONFIG_LWIP_MULTICAST_PING is not set
# CONFIG_LWIP_BROADCAST_PING is not set
# CONFIG_LWIP_RAW is not set
# CONFIG_LWIP_NETBUF_RECVINFO is not set
CONFIG_LWIP_IP4_FRAG=y
# CONFIG_LWIP_IP6_FRAG is not set
# CONFIG_LWIP_IP4_REASSEMBLY is not set
# CONFIG_LWIP_IP6_REASSEMBLY is not set
# CONFIG_LWIP_IP_FORWARD is not set
# CONFIG_LWIP_STATS is not set
# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set
# CONFIG_LWIP_ESP_GRATUITOUS_ARP is not set
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y
CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set
CONFIG_LWIP_DHCPS_LEASE_UNIT=60
CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8
CONFIG_LWIP_DHCP_DISCOVER_RETRANSMISSION_INTERVAL=250
# CONFIG_LWIP_AUTOIP is not set
CONFIG_LWIP_IGMP=y
CONFIG_ESP_DNS=y
CONFIG_DNS_MAX_SERVERS=3
# CONFIG_LWIP_IPV6_AUTOCONFIG is not set
# 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_RECVMBOX_SIZE=16
CONFIG_TCP_QUEUE_OOSEQ=y
CONFIG_TCP_OVERSIZE_MSS=y
# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_TCP_OVERSIZE_DISABLE is not set
# CONFIG_LWIP_TCP_TIMESTAMPS is not set
CONFIG_LWIP_TCP_MAXRTX=12
CONFIG_LWIP_TCP_SYNMAXRTX=6
CONFIG_LWIP_TCP_MSS=1460
CONFIG_LWIP_TCP_TMR_INTERVAL=250
CONFIG_LWIP_TCP_MSL=60000
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=11680
CONFIG_LWIP_TCP_WND_DEFAULT=10240
CONFIG_LWIP_TCP_RECVMBOX_SIZE=16
CONFIG_LWIP_TCP_QUEUE_OOSEQ=y
# CONFIG_LWIP_TCP_SACK_OUT is not set
# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
CONFIG_LWIP_TCP_OVERSIZE_MSS=y
# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set
CONFIG_LWIP_TCP_RTO_TIME=3000
CONFIG_LWIP_MAX_UDP_PCBS=4
CONFIG_UDP_RECVMBOX_SIZE=6
CONFIG_TCPIP_TASK_STACK_SIZE=4096
CONFIG_LWIP_UDP_RECVMBOX_SIZE=6
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096
CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set
CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF
# CONFIG_LWIP_PPP_SUPPORT is not set
CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3
CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5
# CONFIG_LWIP_MULTICAST_PING is not set
# CONFIG_LWIP_BROADCAST_PING is not set
CONFIG_LWIP_MAX_RAW_PCBS=4
# CONFIG_LWIP_IPV6 is not set
# CONFIG_LWIP_STATS is not set
# CONFIG_ESP_LWIP_MEM_DBG is not set
# CONFIG_LWIP_DEBUG is not set
CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
CONFIG_LWIP_ESP_LWIP_ASSERT=y
# CONFIG_LWIP_NETIF_DEBUG is not set
# CONFIG_LWIP_PBUF_DEBUG is not set
# CONFIG_LWIP_ETHARP_DEBUG is not set
# CONFIG_LWIP_API_LIB_DEBUG is not set
# CONFIG_LWIP_SOCKETS_DEBUG is not set
# CONFIG_LWIP_IP_DEBUG is not set
# CONFIG_LWIP_ICMP_DEBUG is not set
# CONFIG_LWIP_IP6_DEBUG is not set
# CONFIG_LWIP_ICMP6_DEBUG is not set
CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set
# CONFIG_MBEDTLS_DEBUG is not set
CONFIG_MBEDTLS_HARDWARE_AES=y
# CONFIG_MBEDTLS_HARDWARE_MPI is not set
CONFIG_MBEDTLS_HARDWARE_SHA=y
CONFIG_MBEDTLS_HAVE_TIME=y
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
@ -302,29 +382,19 @@ CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y
CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
# CONFIG_util_assert is not set
CONFIG_ESP_SHA=y
CONFIG_ESP_AES=y
CONFIG_ESP_MD5=y
CONFIG_ESP_ARC4=y
# CONFIG_ENABLE_MDNS is not set
# CONFIG_MQTT_USING_ESP is not set
CONFIG_MQTT_USING_IBM=y
CONFIG_V3_1=y
# CONFIG_V3_1_1 is not set
CONFIG_DEFAULT_MQTT_VERSION=3
CONFIG_MQTT_CLIENT_ID="espressif_sample"
CONFIG_MQTT_KEEP_ALIVE=30
CONFIG_MQTT_USERNAME="espressif"
CONFIG_MQTT_PASSWORD="admin"
CONFIG_CLEAN_SESSION=y
# CONFIG_KEEP_SESSION is not set
CONFIG_DEFAULT_MQTT_SESSION=1
CONFIG_NO_TLS=y
# CONFIG_TLS_VERIFY_NONE is not set
# CONFIG_TLS_VERIFY_PEER is not set
# CONFIG_TLS_VERIFY_CLIENT is not set
CONFIG_DEFAULT_MQTT_SECURITY=0
CONFIG_MQTT_SEND_BUFFER=2048
CONFIG_MQTT_RECV_BUFFER=2048
CONFIG_MQTT_SEND_CYCLE=30000
CONFIG_MQTT_RECV_CYCLE=0
CONFIG_MQTT_PING_TIMEOUT=3000
CONFIG_MQTT_PROTOCOL_311=y
CONFIG_MQTT_TRANSPORT_SSL=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y
# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set
# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set
# CONFIG_MQTT_CUSTOM_OUTBOX is not set
# CONFIG_NEWLIB_LIBRARY_LEVEL_NORMAL is not set
# CONFIG_NEWLIB_LIBRARY_LEVEL_NANO is not set
CONFIG_NEWLIB_LIBRARY_LEVEL_FLOAT_NANO=y
@ -332,17 +402,45 @@ CONFIG_NEWLIB_LIBRARY_LEVEL_FLOAT_NANO=y
# CONFIG_OPENSSL_DEBUG is not set
CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
# CONFIG_OPENSSL_ASSERT_EXIT is not set
# CONFIG_ENABLE_PTHREAD is not set
# CONFIG_USING_SPIFFS is not set
CONFIG_ENABLE_PTHREAD=y
CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_PTHREAD_STACK_MIN=768
CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SPIFFS_MAX_PARTITIONS=3
CONFIG_SPIFFS_CACHE=y
CONFIG_SPIFFS_CACHE_WR=y
# CONFIG_SPIFFS_CACHE_STATS is not set
CONFIG_SPIFFS_PAGE_CHECK=y
CONFIG_SPIFFS_GC_MAX_RUNS=10
# CONFIG_SPIFFS_GC_STATS is not set
CONFIG_SPIFFS_PAGE_SIZE=256
CONFIG_SPIFFS_OBJ_NAME_LEN=32
CONFIG_SPIFFS_USE_MAGIC=y
CONFIG_SPIFFS_USE_MAGIC_LENGTH=y
CONFIG_SPIFFS_META_LENGTH=4
CONFIG_SPIFFS_USE_MTIME=y
# CONFIG_SPIFFS_DBG is not set
# CONFIG_SPIFFS_API_DBG is not set
# CONFIG_SPIFFS_GC_DBG is not set
# CONFIG_SPIFFS_CACHE_DBG is not set
# CONFIG_SPIFFS_CHECK_DBG is not set
# CONFIG_SPIFFS_TEST_VISUALISATION is not set
CONFIG_IP_LOST_TIMER_INTERVAL=120
# CONFIG_util_assert is not set
CONFIG_ESP_SHA=y
CONFIG_ESP_AES=y
CONFIG_ESP_MD5=y
CONFIG_ESP_ARC4=y
# CONFIG_USING_ESP_VFS is not set
CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y
CONFIG_VFS_SUPPORT_TERMIOS=y
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
# CONFIG_WL_SECTOR_SIZE_512 is not set
CONFIG_WL_SECTOR_SIZE_4096=y
CONFIG_WL_SECTOR_SIZE=4096
# CONFIG_ENABLE_UNIFIED_PROVISIONING is not set
CONFIG_LTM_FAST=y
CONFIG_WPA_MBEDTLS_CRYPTO=y
# CONFIG_WPA_DEBUG_PRINT is not set
# CONFIG_WPA_TESTING_OPTIONS is not set
# CONFIG_WPA_WPS_WARS is not set
# CONFIG_WPA_11KV_SUPPORT is not set
# Deprecated options for backward compatibility
CONFIG_TARGET_PLATFORM="esp8266"
@ -373,4 +471,57 @@ CONFIG_STACK_CHECK_NONE=y
# CONFIG_STACK_CHECK_ALL is not set
# CONFIG_STACK_CHECK is not set
# CONFIG_WARN_WRITE_STRINGS is not set
CONFIG_MAIN_TASK_STACK_SIZE=3584
# CONFIG_CONSOLE_UART_DEFAULT is not set
CONFIG_CONSOLE_UART_CUSTOM=y
# CONFIG_CONSOLE_UART_NONE is not set
# CONFIG_CONSOLE_UART_CUSTOM_NUM_0 is not set
CONFIG_CONSOLE_UART_CUSTOM_NUM_1=y
CONFIG_CONSOLE_UART_NUM=1
CONFIG_CONSOLE_UART_BAUDRATE=74880
# CONFIG_UART0_SWAP_IO is not set
# CONFIG_TASK_WDT is not set
CONFIG_TASK_WDT_TIMEOUT_S=15
CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150
CONFIG_MB_MASTER_DELAY_MS_CONVERT=200
CONFIG_MB_QUEUE_LENGTH=20
CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096
CONFIG_MB_SERIAL_BUF_SIZE=256
CONFIG_MB_SERIAL_TASK_PRIO=10
CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y
CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233
CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20
CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
CONFIG_MB_CONTROLLER_STACK_SIZE=4096
CONFIG_MB_EVENT_QUEUE_TIMEOUT=20
CONFIG_MB_TIMER_GROUP=0
CONFIG_MB_TIMER_INDEX=0
# CONFIG_L2_TO_L3_COPY is not set
# CONFIG_USE_ONLY_LWIP_SELECT is not set
# CONFIG_ESP_GRATUITOUS_ARP is not set
CONFIG_TCPIP_RECVMBOX_SIZE=64
CONFIG_TCP_MAXRTX=12
CONFIG_TCP_SYNMAXRTX=6
CONFIG_TCP_MSS=1460
CONFIG_TCP_MSL=60000
CONFIG_TCP_SND_BUF_DEFAULT=11680
CONFIG_TCP_WND_DEFAULT=10240
CONFIG_TCP_RECVMBOX_SIZE=16
CONFIG_TCP_QUEUE_OOSEQ=y
# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
CONFIG_TCP_OVERSIZE_MSS=y
# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set
# CONFIG_TCP_OVERSIZE_DISABLE is not set
CONFIG_UDP_RECVMBOX_SIZE=6
CONFIG_TCPIP_TASK_STACK_SIZE=4096
CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set
CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
# CONFIG_PPP_SUPPORT is not set
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
CONFIG_ESP32_PTHREAD_STACK_MIN=768
CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y
CONFIG_SUPPORT_TERMIOS=y
# End of deprecated options