diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..0445a67 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,52 @@ +name: build + +on: [push] + +env: + UPLOAD_USER_FIRMWARE: false + +jobs: + build: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + + - name: before_install + run: | + sudo apt update + sudo apt install -y gcc git wget make libncurses-dev flex bison python python-serial ninja-build + wget https://dl.espressif.com/dl/xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz + + - name: install + run: | + tar -xzf ./xtensa-lx106-elf-linux64-1.22.0-100-ge567ec7-5.2.0.tar.gz + wget https://github.com/espressif/ESP8266_RTOS_SDK/releases/download/v3.3-rc1/ESP8266_RTOS_SDK-v3.3-rc1.zip + unzip ESP8266_RTOS_SDK-v3.3-rc1.zip + python -m pip install --user -r ./ESP8266_RTOS_SDK/requirements.txt + + - name: script + id: script + run: | + export IDF_PATH=$PWD/ESP8266_RTOS_SDK + export PATH="$PATH:$PWD/xtensa-lx106-elf/bin" + echo "FIRMWARE=$PWD/build" >> $GITHUB_ENV + python ./idf.py fullclean + python ./idf.py build + echo "::set-output name=status::success" + + - name: Generate release tag + id: tag + if: env.UPLOAD_USER_FIRMWARE == 'true' && steps.script.outputs.status == 'success' && !cancelled() + run: | + echo "::set-output name=release_tag::UserBuild_$(date +"%Y.%m.%d_%H-%M")" + echo "::set-output name=status::success" + + - name: Release user firmware + uses: softprops/action-gh-release@v1 + if: steps.tag.outputs.status == 'success' && !cancelled() + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.tag.outputs.release_tag }} + files: ${{ env.FIRMWARE }}/esp8266_dap.bin + diff --git a/.gitignore b/.gitignore index e524d79..33904f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .vscode/ build/ +tmp/ +.history/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8950d78 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ESP8266_RTOS_SDK"] + path = ESP8266_RTOS_SDK + url = https://github.com/espressif/ESP8266_RTOS_SDK diff --git a/.travis.yml b/.travis.yml index 45b689f..af6a8d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eb1581..7bc2902 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,5 +3,7 @@ cmake_minimum_required(VERSION 3.5) #set(COMPONENT_DIRS "${IDF_PATH}/components ${PROJECT_PATH}/components") +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/main) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(esp8266_dap) diff --git a/ESP8266_RTOS_SDK b/ESP8266_RTOS_SDK new file mode 160000 index 0000000..1be2289 --- /dev/null +++ b/ESP8266_RTOS_SDK @@ -0,0 +1 @@ +Subproject commit 1be2289fcd68672f5d6bf6aafa4f4b57b20527a4 diff --git a/README.md b/README.md index b8f4a0d..c88bc8a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -

-

Wireless ESP8266 DAP

+

-[![Build Status](https://travis-ci.com/windowsair/wireless-esp8266-dap.svg?branch=master)](https://travis-ci.com/windowsair/wireless-esp8266-dap) master -[![Build Status](https://travis-ci.com/windowsair/wireless-esp8266-dap.svg?branch=develop)](https://travis-ci.com/windowsair/wireless-esp8266-dap) develop +![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: -

+

## 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 1-1 + +# πŸ‘‰ Recommend +# HID Mode Or WinUSB Mode +# for usbip-win 0.3.0 kmdf ude +.\usbip.exe attach_ude -r -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) \ No newline at end of file diff --git a/components/DAP/CMakeLists.txt b/components/DAP/CMakeLists.txt index 3eec5a2..c18752a 100644 --- a/components/DAP/CMakeLists.txt +++ b/components/DAP/CMakeLists.txt @@ -1,5 +1,6 @@ set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp8266/include/esp8266/ $ENV{IDF_PATH}//components/esp_ringbuf/include/") -set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c ./source/uart_modify.c") +set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c ./source/uart_modify.c ./source/spi_op.c ./source/spi_switch.c ./source/dap_utility.c") + register_component() \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index 7121a2e..44b3012 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -1,764 +1,715 @@ -/* - * 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 Configuration - * Title: DAP_config.h CMSIS-DAP Configuration File (Template) - * - *---------------------------------------------------------------------------*/ - -#ifndef __DAP_CONFIG_H__ -#define __DAP_CONFIG_H__ - -#include -#include -#include "cmsis_compiler.h" -#include "gpio.h" -#include "gpio_struct.h" -#include "timer_struct.h" -#include "esp8266/pin_mux_register.h" - -//************************************************************************************************** -/** -\defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information -\ingroup DAP_ConfigIO_gr -@{ -Provides definitions about the hardware and configuration of the Debug Unit. - -This information includes: - - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. - - Debug Unit Identification strings (Vendor, Product, Serial Number). - - Debug Unit communication packet size. - - Debug Access Port supported modes and settings (JTAG/SWD and SWO). - - Optional information about a connected Target Device (for Evaluation Boards). -*/ - -//#ifdef _RTE_ -//#include "RTE_Components.h" -//#include CMSIS_device_header -//#else -//#include "device.h" // Debug Unit Cortex-M Processor Header File -//#endif - -/// Processor Clock of the Cortex-M MCU used in the Debug Unit. -/// This value is used to calculate the SWD/JTAG clock speed. -#define CPU_CLOCK 160000000 ///< Specifies the CPU Clock in Hz. -// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz - -// This value is used to replace the largest 10MHZ speed clock in Keil -#define MAX_USER_CLOCK 10000000 ///< Specifies the max Debug Clock in Hz. - -/// Number of processor cycles for I/O Port write operations. -/// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O -/// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors -/// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses -/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be -/// required. -#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. - -/// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. -/// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. - -/// Indicate that JTAG communication mode is available at the Debug Port. -/// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. - -/// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. -/// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. -#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. - -/// Default communication mode on the Debug Access Port. -/// Used for the command \ref DAP_Connect when Port Default mode is selected. -#define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. - -/// Default communication speed on the Debug Access Port for SWD and JTAG mode. -/// Used to initialize the default SWD/JTAG clock frequency. -/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. -#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. -// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<1MHz - -/// Maximum Package Size for Command and Response data. -/// This configuration settings is used to optimize the communication performance with the -/// debugger and depends on the USB peripheral. Typical vales are 64 for Full-speed USB HID or WinUSB, -/// 1024 for High-speed USB HID and 512 for High-speed USB WinUSB. -#define DAP_PACKET_SIZE 255U ///< Specifies Packet Size in bytes. -// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 512 for High-speed USB WinUSB. - -/// Maximum Package Buffers for Command and Response data. -/// This configuration settings is used to optimize the communication performance with the -/// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the -/// setting can be reduced (valid range is 1 .. 255). -#define DAP_PACKET_COUNT 20 ///< Specifies number of packets buffered. - -/// Indicate that UART Serial Wire Output (SWO) trace is available. -/// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available. - -/// Maximum SWO UART Baudrate. -#define SWO_UART_MAX_BAUDRATE (115200U * 40U) ///< SWO UART Maximum Baudrate in Hz. -// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz -//// TODO: uncertain value - -/// Indicate that Manchester Serial Wire Output (SWO) trace is available. -/// This information is returned by the command \ref DAP_Info as part of Capabilities. -#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. - -/// SWO Trace Buffer Size. -#define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). - -/// SWO Streaming Trace. -#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. - -/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. -#define TIMESTAMP_CLOCK 5000000U ///< Timestamp clock in Hz (0 = timestamps not supported). -// <<<<<<<<<<<<<<<<<<<<<5MHz - -/// Debug Unit is connected to fixed Target Device. -/// The Debug Unit may be part of an evaluation board and always connected to a fixed -/// known device. In this case a Device Vendor and Device Name string is stored which -/// may be used by the debugger or IDE to configure device parameters. -#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; - -#if TARGET_DEVICE_FIXED -#define TARGET_DEVICE_VENDOR "ARM" ///< String indicating the Silicon Vendor -#define TARGET_DEVICE_NAME "Cortex-M4" ///< String indicating the Target Device -#endif - -/** - * @brief Get Vendor ID string. - * - * @param str Pointer to buffer to store the string. - * @return String length. - */ -__STATIC_INLINE uint8_t DAP_GetVendorString(char *str) -{ - ////TODO: fill this - // In fact, Keil can get the corresponding information through USB - // without filling in this information. - // (void)str; - strcpy(str, "windowsair"); - return (sizeof("windowsair")); -} - -/** - * @brief Get Product ID string. - * - * @param str Pointer to buffer to store the string. - * @return String length. - */ -__STATIC_INLINE uint8_t DAP_GetProductString(char *str) -{ - //(void)str; - strcpy(str, "CMSIS-DAP v2"); - return (sizeof("CMSIS-DAP v2")); -} - -/** - * @brief Get Serial Number string. - * - * @param str Pointer to buffer to store the string. - * @return String length. - */ -__STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) -{ - strcpy(str, "1234"); - return (sizeof("1234")); -} - -///@} - -// Modify your pins here - -// ATTENTION: DO NOT USE RTC GPIO16 -#define PIN_SWDIO 4 -#define PIN_SWCLK 5 -#define PIN_TDO 13 -#define PIN_TDI 12 -#define PIN_nTRST 0 // optional -#define PIN_nRESET 14 -// LED_BUILTIN -#define PIN_LED_CONNECTED 2 -// LED_BUILTIN -#define PIN_LED_RUNNING 15 - -//************************************************************************************************** -/** -\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access -\ingroup DAP_ConfigIO_gr -@{ - -Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode -and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug -interface of a device. The following I/O Pins are provided: - -JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode ----------------------------- | -------------------- | --------------------------------------------- -TCK: Test Clock | SWCLK: Clock | Output Push/Pull -TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) -TDI: Test Data Input | | Output Push/Pull -TDO: Test Data Output | | Input -nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor -nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor - - -DAP Hardware I/O Pin Access Functions -------------------------------------- -The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to -these I/O Pins. - -For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. -This functions are provided to achieve faster I/O that is possible with some advanced GPIO -peripherals that can independently write/read a single I/O pin without affecting any other pins -of the same I/O port. The following SWDIO I/O Pin functions are provided: - - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. - - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. - - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. - - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. -*/ - -/** - * @brief Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. - * Configures the DAP Hardware I/O pins for JTAG mode: - * - TCK, TMS, TDI, nTRST, nRESET to ***output*** mode and set to high level. - * - TDO to ***input*** mode. - * - */ -__STATIC_INLINE void PORT_JTAG_SETUP(void) -{ - gpio_pin_reg_t pin_reg; - - // gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); - // gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); - GPIO.enable_w1ts |= (0x1 << PIN_SWCLK); - GPIO.pin[PIN_SWCLK].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWCLK)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWCLK), pin_reg.val); - GPIO.enable_w1ts |= (0x1 << PIN_SWDIO); - GPIO.pin[PIN_SWDIO].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWDIO)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWDIO), pin_reg.val); - - // gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); - GPIO.enable_w1tc |= (0x1 << PIN_TDO); - GPIO.pin[PIN_TDO].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDO)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDO), pin_reg.val); - // gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); - GPIO.enable_w1ts |= (0x1 << PIN_TDI); - GPIO.pin[PIN_TDI].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDI)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDI), pin_reg.val); - - // gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); - // gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); - GPIO.enable_w1tc |= (0x1 << PIN_nTRST); - GPIO.pin[PIN_nTRST].driver = 1; - GPIO.enable_w1tc |= (0x1 << PIN_nRESET); - GPIO.pin[PIN_nRESET].driver = 1; - - // gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); - // gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nTRST)); - pin_reg.pullup = 1; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_nTRST), pin_reg.val); - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nRESET)); - pin_reg.pullup = 1; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_nRESET), pin_reg.val); -} - -/** - * @brief Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. - * Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: - * - SWCLK, SWDIO, nRESET to output mode and set to default high level. - * - TDI, nTRST to HighZ mode (pins are unused in SWD mode). - * - */ -__STATIC_INLINE void PORT_SWD_SETUP(void) -{ - gpio_pin_reg_t pin_reg; - - // gpio_set_direction(PIN_SWCLK, GPIO_MODE_OUTPUT); - // gpio_set_direction(PIN_SWDIO, GPIO_MODE_OUTPUT); - GPIO.enable_w1ts |= (0x1 << PIN_SWCLK); - GPIO.pin[PIN_SWCLK].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWCLK)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWCLK), pin_reg.val); - GPIO.enable_w1ts |= (0x1 << PIN_SWDIO); - GPIO.pin[PIN_SWDIO].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_SWDIO)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_SWDIO), pin_reg.val); - - // gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); - GPIO.enable_w1tc |= (0x1 << PIN_TDO); - GPIO.pin[PIN_TDO].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDO)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDO), pin_reg.val); - // gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); - GPIO.enable_w1ts |= (0x1 << PIN_TDI); - GPIO.pin[PIN_TDI].driver = 0; - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDI)); - pin_reg.pullup = 0; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDI), pin_reg.val); - - // gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); - // gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); - GPIO.enable_w1tc |= (0x1 << PIN_nTRST); - GPIO.pin[PIN_nTRST].driver = 1; - GPIO.enable_w1tc |= (0x1 << PIN_nRESET); - GPIO.pin[PIN_nRESET].driver = 1; - - // gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); - // gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nTRST)); - pin_reg.pullup = 1; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_nTRST), pin_reg.val); - pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nRESET)); - pin_reg.pullup = 1; - WRITE_PERI_REG(GPIO_PIN_REG(PIN_nRESET), pin_reg.val); -} - -/** - * @brief Disable JTAG/SWD I/O Pins. - * Disables the DAP Hardware I/O pins which configures: - * - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. - * - */ -__STATIC_INLINE void PORT_OFF(void) -{ - // Will be called when the DAP disconnected - // gpio_set_direction(PIN_SWCLK, GPIO_MODE_DEF_DISABLE); - // gpio_set_direction(PIN_SWDIO, GPIO_MODE_DEF_DISABLE); - - // gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_DISABLE); - // gpio_set_direction(PIN_TDI, GPIO_MODE_DEF_DISABLE); - - // gpio_set_direction(PIN_nTRST, GPIO_MODE_DEF_DISABLE); - // gpio_set_direction(PIN_nRESET, GPIO_MODE_DEF_DISABLE); - GPIO.pin[PIN_SWCLK].driver = 0; - GPIO.enable_w1tc |= (0x1 << PIN_SWCLK); - - GPIO.pin[PIN_SWDIO].driver = 0; - GPIO.enable_w1tc |= (0x1 << PIN_SWDIO); - - GPIO.pin[PIN_TDO].driver = 0; - GPIO.enable_w1tc |= (0x1 << PIN_TDO); - - GPIO.pin[PIN_TDI].driver = 0; - GPIO.enable_w1tc |= (0x1 << PIN_TDI); - - GPIO.pin[PIN_nTRST].driver = 0; - GPIO.enable_w1tc |= (0x1 << PIN_nTRST); - - GPIO.pin[PIN_nRESET].driver = 0; - GPIO.enable_w1tc |= (0x1 << PIN_nRESET); -} - -// SWCLK/TCK I/O pin ------------------------------------- - -/** - * @brief SWCLK/TCK I/O pin: Get Input. - * - * @return Current status of the SWCLK/TCK DAP hardware I/O pin. - */ -__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) -{ - ////TODO: can we set to 0? - return 0; -} - -/** - * @brief SWCLK/TCK I/O pin: Set Output to High. - * - * Set the SWCLK/TCK DAP hardware I/O pin to high level. - */ -__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET(void) -{ - GPIO.out_w1ts |= (0x1 << PIN_SWCLK); -} - -/** - * @brief SWCLK/TCK I/O pin: Set Output to Low. - * - * Set the SWCLK/TCK DAP hardware I/O pin to low level. - */ -__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) -{ - GPIO.out_w1tc |= (0x1 << PIN_SWCLK); -} - -// SWDIO/TMS Pin I/O -------------------------------------- - -/** - * @brief SWDIO/TMS I/O pin: Get Input. - * - * @return Current status of the SWDIO/TMS DAP hardware I/O pin. - */ -__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) -{ - return ((GPIO.in >> PIN_SWDIO) & 0x1) ? 1 : 0; -} - -/** - * @brief SWDIO/TMS I/O pin: Set Output to High. - * - * Set the SWDIO/TMS DAP hardware I/O pin to high level. - */ -__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void) -{ - GPIO.out_w1ts |= (0x1 << PIN_SWDIO); -} - -/** - * @brief SWDIO/TMS I/O pin: Set Output to Low. - * - * Set the SWDIO/TMS DAP hardware I/O pin to low level. - */ -__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) -{ - GPIO.out_w1tc |= (0x1 << PIN_SWDIO); -} - -/** - * @brief SWDIO I/O pin: Get Input (used in SWD mode only). - * - * @return Current status of the SWDIO DAP hardware I/O pin. - */ -__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) -{ - return ((GPIO.in >> PIN_SWDIO) & 0x1) ? 1 : 0; -} - -/** - * @brief SWDIO I/O pin: Set Output (used in SWD mode only). - * - * @param bit Output value for the SWDIO DAP hardware I/O pin. - * - */ -__STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) -{ - /** - * Important: Use only one bit (bit0) of param! - * Sometimes the func "SWD_TransferFunction" of SW_DP.c will - * issue "2" as param instead of "0". Zach Lee - */ - if ((bit & 1U) == 1) - { - //set bit - GPIO.out_w1ts |= (0x1 << PIN_SWDIO); - - } - else - { - //reset bit - GPIO.out_w1tc |= (0x1 << PIN_SWDIO); - - } -} - -/** - * @brief SWDIO I/O pin: Switch to Output mode (used in SWD mode only). - * Configure the SWDIO DAP hardware I/O pin to output mode. This function is - * called prior \ref PIN_SWDIO_OUT function calls. - */ -__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) -{ - // Need fast response - - // set \ref gpio_set_direction -> OUTPUT - GPIO.enable_w1ts |= (0x1 << PIN_SWDIO); - GPIO.pin[PIN_SWDIO].driver = 0; -} - -/** - * @brief SWDIO I/O pin: Switch to Input mode (used in SWD mode only). - * Configure the SWDIO DAP hardware I/O pin to input mode. This function is - * called prior \ref PIN_SWDIO_IN function calls. - */ -__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) -{ - // Need fast response - // set \ref gpio_set_dircetion -> INPUT - // esp8266 input is always connected - GPIO.enable_w1tc |= (0x1 << PIN_SWDIO); - GPIO.pin[PIN_SWDIO].driver = 0; -} - -// TDI Pin I/O --------------------------------------------- - -/** - * @brief TDI I/O pin: Get Input. - * - * @return Current status of the TDI DAP hardware I/O pin. - */ -__STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) -{ - return ((GPIO.in >> PIN_TDI) & 0x1) ? 1 : 0; -} - -/** - * @brief TDI I/O pin: Set Output. - * - * @param bit Output value for the TDI DAP hardware I/O pin. - * - */ -__STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) -{ - if ((bit & 1U) == 1) - { - //set bit - GPIO.out_w1ts |= (0x1 << PIN_TDI); - - } - else - { - //reset bit - GPIO.out_w1tc |= (0x1 << PIN_TDI); - - } -} - -// TDO Pin I/O --------------------------------------------- - -/** - * @brief TDO I/O pin: Get Input. - * - * @return Current status of the TDO DAP hardware I/O pin. - */ -__STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) -{ - return ((GPIO.in >> PIN_TDO) & 0x1) ? 1 : 0; -} - -// nTRST Pin I/O ------------------------------------------- - -/** - * @brief nTRST I/O pin: Get Input. - * - * @return Current status of the nTRST DAP hardware I/O pin. - */ -__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) -{ - return 0; // not available -} - -/** - * @brief nTRST I/O pin: Set Output. - * - * @param bit JTAG TRST Test Reset pin status: - * - 0: issue a JTAG TRST Test Reset. - - 1: release JTAG TRST Test Reset. - */ -__STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) -{ - // ////TODO: What does this mean? ? ? - // if ((bit & 1U) == 1) - // { - // //set bit - // GPIO.out_w1ts |= (0x1 << PIN_nTRST); - // } - // else - // { - // //reset bit - // GPIO.out_w1tc |= (0x1 << PIN_nTRST); - // } - ; // not available -} - -// nRESET Pin I/O------------------------------------------ - -/** - * @brief nRESET I/O pin: Get Input. - * - * @return Current status of the nRESET DAP hardware I/O pin. - */ -__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) -{ - return ((GPIO.in >> PIN_nRESET) & 0x1) ? 1 : 0; -} - -/** - * @brief nRESET I/O pin: Set Output. - * - * @param bit target device hardware reset pin status: - * - 0: issue a device hardware reset. - * - 1: release device hardware reset. - */ -__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) -{ - ////TODO: What does this mean? ? ? - if ((bit & 1U) == 1) - { - //set bit - GPIO.out_w1ts |= (0x1 << PIN_nRESET); - } - else - { - //reset bit - GPIO.out_w1tc |= (0x1 << PIN_nRESET); - } -} - -///@} - -//************************************************************************************************** -/** -\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs -\ingroup DAP_ConfigIO_gr -@{ - -CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. - -It is recommended to provide the following LEDs for status indication: - - Connect LED: is active when the DAP hardware is connected to a debugger. - - Running LED: is active when the debugger has put the target device into running state. -*/ - -/** Debug Unit: Set status of Connected LED. -\param bit status of the Connect LED. - - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. - - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. -*/ - -/** - * @brief Debug Unit: Set status of Connected LED. - * - * @param bit status of the Connect LED. - * - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. - * - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. - */ -__STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit) -{ - if (bit) - { - //set bit - GPIO.out_w1ts |= (0x1 << PIN_LED_CONNECTED); - } - else - { - //reset bit - GPIO.out_w1tc |= (0x1 << PIN_LED_CONNECTED); - } -} - -/** - * @brief Debug Unit: Set status Target Running LED. - * - * @param bit status of the Target Running LED. - * - 1: Target Running LED ON: program execution in target started. - * - 0: Target Running LED OFF: program execution in target stopped. - */ -__STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit) -{ - if (bit) - { - //set bit - GPIO.out_w1ts |= (0x1 << PIN_LED_RUNNING); - } - else - { - //reset bit - GPIO.out_w1tc |= (0x1 << PIN_LED_RUNNING); - } -} - -///@} - -//************************************************************************************************** -/** -\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp -\ingroup DAP_ConfigIO_gr -@{ -Access function for Test Domain Timer. - -The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By -default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. - -*/ - -/** - * @brief Get timestamp of Test Domain Timer. - * - * @return Current timestamp value. - */ -__STATIC_INLINE uint32_t TIMESTAMP_GET(void) -{ - // FRC1 is a 23-bit countdown timer - return (0x7FFFFF - (frc1.count.data)); -} - -///@} - -//************************************************************************************************** -/** -\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization -\ingroup DAP_ConfigIO_gr -@{ - -CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. -*/ - -/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). -This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the -Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: - - I/O clock system enabled. - - all I/O pins: input buffer enabled, output pins are set to HighZ mode. - - for nTRST, nRESET a weak pull-up (if available) is enabled. - - LED output pins are enabled and LEDs are turned off. -*/ -__STATIC_INLINE void DAP_SETUP(void) -{ - // This function maybe unnecessary... - gpio_set_direction(PIN_SWCLK, GPIO_MODE_DEF_INPUT); - gpio_set_direction(PIN_SWDIO, GPIO_MODE_DEF_INPUT); // - gpio_set_direction(PIN_nRESET, GPIO_MODE_DEF_INPUT); // - gpio_set_direction(PIN_TDI, GPIO_MODE_DEF_INPUT); - gpio_set_direction(PIN_TDO, GPIO_MODE_DEF_INPUT); - - // Configure: LED as output (turned off) - gpio_set_direction(PIN_LED_CONNECTED, GPIO_MODE_DEF_OUTPUT); - LED_CONNECTED_OUT(0); - gpio_set_direction(PIN_LED_RUNNING, GPIO_MODE_DEF_OUTPUT); - LED_RUNNING_OUT(0); -} - -/** Reset Target Device with custom specific I/O pin or command sequence. -This function allows the optional implementation of a device specific reset sequence. -It is called when the command \ref DAP_ResetTarget and is for example required -when a device needs a time-critical unlock sequence that enables the debug port. -\return 0 = no device specific reset sequence is implemented.\n - 1 = a device specific reset sequence is implemented. -*/ -__STATIC_INLINE uint8_t RESET_TARGET(void) -{ - return (0U); // not available -} - -///@} - -#endif /* __DAP_CONFIG_H__ */ +/* + * 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 Configuration + * Title: DAP_config.h CMSIS-DAP Configuration File (Template) + * + *---------------------------------------------------------------------------*/ + +/** + * @file DAP_config.h + * @author windowsair + * @brief Adaptation of GPIO and SPI pin + * @change: 2021-2-10 Support GPIO and SPI + * 2021-2-18 Try to support SWO + * @version 0.1 + * @date 2021-2-10 + * + * @copyright Copyright (c) 2021 + * + */ + + +#ifndef __DAP_CONFIG_H__ +#define __DAP_CONFIG_H__ + +#include +#include +#include "cmsis_compiler.h" +#include "gpio.h" +#include "gpio_struct.h" +#include "timer.h" +#include "esp8266/pin_mux_register.h" + +#include "gpio_op.h" +#include "spi_switch.h" +#include "dap_configuration.h" +//************************************************************************************************** +/** +\defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information +\ingroup DAP_ConfigIO_gr +@{ +Provides definitions about the hardware and configuration of the Debug Unit. + +This information includes: + - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. + - Debug Unit Identification strings (Vendor, Product, Serial Number). + - Debug Unit communication packet size. + - Debug Access Port supported modes and settings (JTAG/SWD and SWO). + - Optional information about a connected Target Device (for Evaluation Boards). +*/ + +//#ifdef _RTE_ +//#include "RTE_Components.h" +//#include CMSIS_device_header +//#else +//#include "device.h" // Debug Unit Cortex-M Processor Header File +//#endif + +/// Processor Clock of the Cortex-M MCU used in the Debug Unit. +/// This value is used to calculate the SWD/JTAG clock speed. +#define CPU_CLOCK 160000000 ///< Specifies the CPU Clock in Hz. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<160MHz + + +//#define MAX_USER_CLOCK 16000000 ///< Specifies the max Debug Clock in Hz. + +/// Number of processor cycles for I/O Port write operations. +/// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O +/// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors +/// require 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses +/// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be +/// required. +#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0. + +/// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available. + +/// Indicate that JTAG communication mode is available at the Debug Port. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. + +/// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. +/// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. +#define DAP_JTAG_DEV_CNT 8U ///< Maximum number of JTAG devices on scan chain. + +/// Default communication mode on the Debug Access Port. +/// Used for the command \ref DAP_Connect when Port Default mode is selected. +#define DAP_DEFAULT_PORT 1U ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. + +/// Default communication speed on the Debug Access Port for SWD and JTAG mode. +/// Used to initialize the default SWD/JTAG clock frequency. +/// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. +#define DAP_DEFAULT_SWJ_CLOCK 1000000U ///< Default SWD/JTAG clock frequency in Hz. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<1MHz + +/// Maximum Package Buffers for Command and Response data. +/// This configuration settings is used to optimize the communication performance with the +/// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the +/// setting can be reduced (valid range is 1 .. 255). +#define DAP_PACKET_COUNT 255 ///< Specifies number of packets buffered. + +/// Indicates that the SWO function(UART SWO & Streaming Trace) is available +#define SWO_FUNCTION_ENABLE 0 ///< SWO function: 1 = available, 0 = not available. + + +/// Indicate that UART Serial Wire Output (SWO) trace is available. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define SWO_UART SWO_FUNCTION_ENABLE ///< SWO UART: 1 = available, 0 = not available. + +/// Maximum SWO UART Baudrate. +#define SWO_UART_MAX_BAUDRATE (115200U * 40U) ///< SWO UART Maximum Baudrate in Hz. +// <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz +//// TODO: uncertain value + +/// Indicate that Manchester Serial Wire Output (SWO) trace is available. +/// This information is returned by the command \ref DAP_Info as part of Capabilities. +#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. +// (windowsair)Do not modify. Not support. + + +/// SWO Trace Buffer Size. +#define SWO_BUFFER_SIZE 2048U ///< SWO Trace Buffer Size in bytes (must be 2^n). + +/// SWO Streaming Trace. +#define SWO_STREAM SWO_FUNCTION_ENABLE ///< SWO Streaming Trace: 1 = available, 0 = not available. + +/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. +#define TIMESTAMP_CLOCK 5000000U ///< Timestamp clock in Hz (0 = timestamps not supported). +// <<<<<<<<<<<<<<<<<<<<<5MHz + +/// Debug Unit is connected to fixed Target Device. +/// The Debug Unit may be part of an evaluation board and always connected to a fixed +/// known device. In this case a Device Vendor and Device Name string is stored which +/// may be used by the debugger or IDE to configure device parameters. +#define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; + +#if TARGET_DEVICE_FIXED +#define TARGET_DEVICE_VENDOR "ARM" ///< String indicating the Silicon Vendor +#define TARGET_DEVICE_NAME "Cortex-M4" ///< String indicating the Target Device +#endif + +/** + * @brief Get Vendor ID string. + * + * @param str Pointer to buffer to store the string. + * @return String length. + */ +__STATIC_INLINE uint8_t DAP_GetVendorString(char *str) +{ + // In fact, Keil can get the corresponding information through USB + // without filling in this information. + // (void)str; + strcpy(str, "windowsair"); + return (sizeof("windowsair")); +} + +/** + * @brief Get Product ID string. + * + * @param str Pointer to buffer to store the string. + * @return String length. + */ +__STATIC_INLINE uint8_t DAP_GetProductString(char *str) +{ + //(void)str; + strcpy(str, "CMSIS-DAP v2"); + return (sizeof("CMSIS-DAP v2")); +} + +/** + * @brief Get Serial Number string. + * + * @param str Pointer to buffer to store the string. + * @return String length. + */ +__STATIC_INLINE uint8_t DAP_GetSerNumString(char *str) +{ + strcpy(str, "1234"); + return (sizeof("1234")); +} + +///@} + + +// Note: DO NOT modify these pins: PIN_SWDIO PIN_SWDIO_MOSI PIN_SWCLK +// Modify the following pins carefully: PIN_TDO +#define PIN_SWDIO 12 // SPI MISO +#define PIN_SWDIO_MOSI 13 // SPI MOSI +#define PIN_SWCLK 14 +#define PIN_TDO 16 // device TDO -> Host Data Input (use RTC pin 16) +#define PIN_TDI 4 +#define PIN_nTRST 0 // optional +#define PIN_nRESET 5 +// LED_BUILTIN +#define PIN_LED_CONNECTED 2 +// LED_BUILTIN +#define PIN_LED_RUNNING 15 + +//************************************************************************************************** +/** +\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access +\ingroup DAP_ConfigIO_gr +@{ + +Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode +and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug +interface of a device. The following I/O Pins are provided: + +JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode +---------------------------- | -------------------- | --------------------------------------------- +TCK: Test Clock | SWCLK: Clock | Output Push/Pull +TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) +TDI: Test Data Input | | Output Push/Pull +TDO: Test Data Output | | Input +nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor +nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor + + +DAP Hardware I/O Pin Access Functions +------------------------------------- +The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to +these I/O Pins. + +For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. +This functions are provided to achieve faster I/O that is possible with some advanced GPIO +peripherals that can independently write/read a single I/O pin without affecting any other pins +of the same I/O port. The following SWDIO I/O Pin functions are provided: + - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. + - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. + - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. + - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. +*/ + +/** + * @brief Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. + * Configures the DAP Hardware I/O pins for JTAG mode: + * - TCK, TMS, TDI, nTRST, nRESET to ***output*** mode and set to high level. + * - TDO to ***input*** mode. + * + */ +__STATIC_INLINE void PORT_JTAG_SETUP(void) +{ + gpio_pin_reg_t pin_reg; + + + // set TCK, TMS pin + DAP_SPI_Deinit(); + + + // use RTC pin 16 + // output disable + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, ((READ_PERI_REG(PAD_XPD_DCDC_CONF) & (uint32_t)0xffffffbc)) | (uint32_t)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection + CLEAR_PERI_REG_MASK(RTC_GPIO_CONF, 0x1); // mux configuration for out enable + CLEAR_PERI_REG_MASK(RTC_GPIO_ENABLE, 0x1); // out disable + // pulldown disable + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDO)); + pin_reg.rtc_pin.pulldown = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDO), pin_reg.val); + + + + // gpio_set_direction(PIN_TDI, GPIO_MODE_OUTPUT); + GPIO.enable_w1ts |= (0x1 << PIN_TDI); + GPIO.pin[PIN_TDI].driver = 0; + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_TDI)); + pin_reg.pullup = 0; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_TDI), pin_reg.val); + + // gpio_set_direction(PIN_nTRST, GPIO_MODE_OUTPUT_OD); + // gpio_set_direction(PIN_nRESET, GPIO_MODE_OUTPUT_OD); + GPIO.enable_w1tc |= (0x1 << PIN_nTRST); + GPIO.pin[PIN_nTRST].driver = 1; + GPIO.enable_w1tc |= (0x1 << PIN_nRESET); + GPIO.pin[PIN_nRESET].driver = 1; + + // gpio_set_pull_mode(PIN_nTRST, GPIO_PULLUP_ONLY); + // gpio_set_pull_mode(PIN_nRESET, GPIO_PULLUP_ONLY); + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nTRST)); + pin_reg.pullup = 1; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_nTRST), pin_reg.val); + + pin_reg.val = READ_PERI_REG(GPIO_PIN_REG(PIN_nRESET)); + pin_reg.pullup = 1; + WRITE_PERI_REG(GPIO_PIN_REG(PIN_nRESET), pin_reg.val); +} + +/** + * @brief Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. + * Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: + * - SWCLK, SWDIO, nRESET to output mode and set to default high level. + * - TDI, nTRST to HighZ mode (pins are unused in SWD mode). + * + */ +__STATIC_INLINE void PORT_SWD_SETUP(void) +{ + // At this stage we do not consider whether to use SPI or GPIO. + // We will switch to the specific mode when setting the transfer rate. + DAP_SPI_Init(); + DAP_SPI_Disable(); +} + +/** + * @brief Disable JTAG/SWD I/O Pins. + * Disables the DAP Hardware I/O pins which configures: + * - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. + * + */ +__STATIC_INLINE void PORT_OFF(void) +{ + // Will be called when the DAP disconnected + DAP_SPI_Disable(); +} + +// SWCLK/TCK I/O pin ------------------------------------- + +/** + * @brief SWCLK/TCK I/O pin: Get Input. + * + * @return Current status of the SWCLK/TCK DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void) +{ + ////TODO: can we set to 0? + return 0; +} + +/** + * @brief SWCLK/TCK I/O pin: Set Output to High. + * + * Set the SWCLK/TCK DAP hardware I/O pin to high level. + */ +__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET(void) +{ + GPIO.out_w1ts |= (0x1 << PIN_SWCLK); +} + +/** + * @brief SWCLK/TCK I/O pin: Set Output to Low. + * + * Set the SWCLK/TCK DAP hardware I/O pin to low level. + */ +__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void) +{ + GPIO.out_w1tc |= (0x1 << PIN_SWCLK); +} + +// SWDIO/TMS Pin I/O -------------------------------------- + +/** + * @brief SWDIO/TMS I/O pin: Get Input. + * + * @return Current status of the SWDIO/TMS DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void) +{ + // Note that we only use mosi in GPIO mode + return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; +} + +/** + * @brief SWDIO/TMS I/O pin: Set Output to High. + * + * Set the SWDIO/TMS DAP hardware I/O pin to high level. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void) +{ + GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI); +} + +/** + * @brief SWDIO/TMS I/O pin: Set Output to Low. + * + * Set the SWDIO/TMS DAP hardware I/O pin to low level. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void) +{ + GPIO.out_w1tc |= (0x1 << PIN_SWDIO_MOSI); +} + +/** + * @brief SWDIO I/O pin: Get Input (used in SWD mode only). + * + * @return Current status of the SWDIO DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void) +{ + // Note that we only use mosi in GPIO mode + return ((GPIO.in >> PIN_SWDIO_MOSI) & 0x1) ? 1 : 0; +} + +/** + * @brief SWDIO I/O pin: Set Output (used in SWD mode only). + * + * @param bit Output value for the SWDIO DAP hardware I/O pin. + * + */ +__STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit) +{ + /** + * Important: Use only one bit (bit0) of param! + * Sometimes the func "SWD_TransferFunction" of SW_DP.c will + * issue "2" as param instead of "0". Zach Lee + */ + if ((bit & 1U) == 1) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI); + + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_SWDIO_MOSI); + + } +} + +/** + * @brief SWDIO I/O pin: Switch to Output mode (used in SWD mode only). + * Configure the SWDIO DAP hardware I/O pin to output mode. This function is + * called prior \ref PIN_SWDIO_OUT function calls. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void) +{ + // set \ref gpio_set_direction -> OUTPUT + // GPIO.enable_w1ts |= (0x1 << PIN_SWDIO_MOSI); + // GPIO.pin[PIN_SWDIO_MOSI].driver = 0; + do {}while (0); + +} + +/** + * @brief SWDIO I/O pin: Switch to Input mode (used in SWD mode only). + * Configure the SWDIO DAP hardware I/O pin to input mode. This function is + * called prior \ref PIN_SWDIO_IN function calls. + */ +__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void) +{ + // may be unuse. + // set \ref gpio_set_dircetion -> INPUT + // esp8266 input is always connected + // GPIO.enable_w1tc |= (0x1 << PIN_SWDIO_MOSI); + // GPIO.pin[PIN_SWDIO_MOSI].driver = 0; + GPIO.out_w1ts |= (0x1 << PIN_SWDIO_MOSI); +} + +// TDI Pin I/O --------------------------------------------- + +/** + * @brief TDI I/O pin: Get Input. + * + * @return Current status of the TDI DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void) +{ + return ((GPIO.in >> PIN_TDI) & 0x1) ? 1 : 0; +} + +/** + * @brief TDI I/O pin: Set Output. + * + * @param bit Output value for the TDI DAP hardware I/O pin. + * + */ +__STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit) +{ + if ((bit & 1U) == 1) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_TDI); + + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_TDI); + + } +} + +// TDO Pin I/O --------------------------------------------- + +/** + * @brief TDO I/O pin: Get Input. + * + * @return Current status of the TDO DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void) +{ + return READ_PERI_REG(RTC_GPIO_IN_DATA) & 0x1; +} + +// nTRST Pin I/O ------------------------------------------- + +/** + * @brief nTRST I/O pin: Get Input. + * + * @return Current status of the nTRST DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void) +{ + return 0; // not available +} + +/** + * @brief nTRST I/O pin: Set Output. + * + * @param bit JTAG TRST Test Reset pin status: + * - 0: issue a JTAG TRST Test Reset. + - 1: release JTAG TRST Test Reset. + */ +__STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit) +{ + // Vendor reset sequence + ; // not available +} + +// nRESET Pin I/O------------------------------------------ + +/** + * @brief nRESET I/O pin: Get Input. + * + * @return Current status of the nRESET DAP hardware I/O pin. + */ +__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void) +{ + return ((GPIO.in >> PIN_nRESET) & 0x1) ? 1 : 0; +} + +/** + * @brief nRESET I/O pin: Set Output. + * + * @param bit target device hardware reset pin status: + * - 0: issue a device hardware reset. + * - 1: release device hardware reset. + */ +__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit) +{ + // Vendor reset sequence + //// FIXME: unavailable + if ((bit & 1U) == 1) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_nRESET); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_nRESET); + } +} + +///@} + +//************************************************************************************************** +/** +\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs +\ingroup DAP_ConfigIO_gr +@{ + +CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. + +It is recommended to provide the following LEDs for status indication: + - Connect LED: is active when the DAP hardware is connected to a debugger. + - Running LED: is active when the debugger has put the target device into running state. +*/ + +/** Debug Unit: Set status of Connected LED. +\param bit status of the Connect LED. + - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. + - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. +*/ + +/** + * @brief Debug Unit: Set status of Connected LED. + * + * @param bit status of the Connect LED. + * - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. + * - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. + */ +__STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit) +{ + if (bit) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_LED_CONNECTED); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_LED_CONNECTED); + } +} + +/** + * @brief Debug Unit: Set status Target Running LED. + * + * @param bit status of the Target Running LED. + * - 1: Target Running LED ON: program execution in target started. + * - 0: Target Running LED OFF: program execution in target stopped. + */ +__STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit) +{ + if (bit) + { + //set bit + GPIO.out_w1ts |= (0x1 << PIN_LED_RUNNING); + } + else + { + //reset bit + GPIO.out_w1tc |= (0x1 << PIN_LED_RUNNING); + } +} + +///@} + +//************************************************************************************************** +/** +\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp +\ingroup DAP_ConfigIO_gr +@{ +Access function for Test Domain Timer. + +The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By +default, the DWT timer is used. The frequency of this timer is configured with \ref TIMESTAMP_CLOCK. + +*/ + +/** + * @brief Get timestamp of Test Domain Timer. + * + * @return Current timestamp value. + */ +__STATIC_INLINE uint32_t TIMESTAMP_GET(void) +{ + return get_timer_count(); +} + +///@} + +//************************************************************************************************** +/** +\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization +\ingroup DAP_ConfigIO_gr +@{ + +CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. +*/ + +/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). +This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the +Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: + - I/O clock system enabled. + - all I/O pins: input buffer enabled, output pins are set to HighZ mode. + - for nTRST, nRESET a weak pull-up (if available) is enabled. + - LED output pins are enabled and LEDs are turned off. +*/ +__STATIC_INLINE void DAP_SETUP(void) +{ + // Connecting non-SWD pins to GPIO + GPIO_FUNCTION_SET(PIN_TDO); + GPIO_FUNCTION_SET(PIN_TDI); + GPIO_FUNCTION_SET(PIN_nTRST); + GPIO_FUNCTION_SET(PIN_nRESET); + GPIO_FUNCTION_SET(PIN_LED_CONNECTED); + GPIO_FUNCTION_SET(PIN_LED_RUNNING); + + + // Configure: LED as output (turned off) + + GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_CONNECTED); + GPIO_SET_DIRECTION_NORMAL_OUT(PIN_LED_RUNNING); + + LED_CONNECTED_OUT(0); + LED_RUNNING_OUT(0); + + PORT_OFF(); +} + +/** Reset Target Device with custom specific I/O pin or command sequence. +This function allows the optional implementation of a device specific reset sequence. +It is called when the command \ref DAP_ResetTarget and is for example required +when a device needs a time-critical unlock sequence that enables the debug port. +\return 0 = no device specific reset sequence is implemented.\n + 1 = a device specific reset sequence is implemented. +*/ +__STATIC_INLINE uint8_t RESET_TARGET(void) +{ + return (0U); // not available +} + +///@} + +#endif /* __DAP_CONFIG_H__ */ diff --git a/components/DAP/include/DAP.h b/components/DAP/include/DAP.h index 65e0459..a011a92 100644 --- a/components/DAP/include/DAP.h +++ b/components/DAP/include/DAP.h @@ -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); diff --git a/components/DAP/include/cmsis_compiler.h b/components/DAP/include/cmsis_compiler.h index aafbe21..9d032bb 100644 --- a/components/DAP/include/cmsis_compiler.h +++ b/components/DAP/include/cmsis_compiler.h @@ -7,6 +7,9 @@ #ifndef __STATIC_INLINE #define __STATIC_INLINE static inline __attribute__((always_inline)) #endif +#ifndef __FORCEINLINE + #define __FORCEINLINE inline __attribute__((always_inline)) +#endif #ifndef __WEAK #define __WEAK __attribute__((weak)) #endif diff --git a/components/DAP/include/dap_utility.h b/components/DAP/include/dap_utility.h new file mode 100644 index 0000000..ee25c6f --- /dev/null +++ b/components/DAP/include/dap_utility.h @@ -0,0 +1,33 @@ +#ifndef __DAP_UTILITY_H__ +#define __DAP_UTILITY_H__ + +#include + +#ifndef __STATIC_FORCEINLINE + #define __STATIC_FORCEINLINE static inline __attribute__((always_inline)) +#endif +#ifndef __STATIC_INLINE + #define __STATIC_INLINE static inline __attribute__((always_inline)) +#endif +#ifndef __WEAK + #define __WEAK __attribute__((weak)) +#endif + + +extern const uint8_t kParityByteTable[256]; + +__STATIC_FORCEINLINE uint8_t ParityEvenUint32(uint32_t v) +{ + v ^= v >> 16; + v ^= v >> 8; + v ^= v >> 4; + v &= 0xf; + return (0x6996 >> v) & 1; +} + +__STATIC_FORCEINLINE uint8_t ParityEvenUint8(uint8_t v) +{ + return kParityByteTable[v]; +} + +#endif diff --git a/components/DAP/include/gpio_op.h b/components/DAP/include/gpio_op.h new file mode 100644 index 0000000..30b214d --- /dev/null +++ b/components/DAP/include/gpio_op.h @@ -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 \ No newline at end of file diff --git a/components/DAP/include/spi_op.h b/components/DAP/include/spi_op.h new file mode 100644 index 0000000..85ae927 --- /dev/null +++ b/components/DAP/include/spi_op.h @@ -0,0 +1,20 @@ +#ifndef __SPI_OP_H__ +#define __SPI_OP_H__ + +#include + + +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 diff --git a/components/DAP/include/spi_switch.h b/components/DAP/include/spi_switch.h new file mode 100644 index 0000000..3b7eb80 --- /dev/null +++ b/components/DAP/include/spi_switch.h @@ -0,0 +1,10 @@ +#ifndef __SPI_SWITCH_H__ +#define __SPI_SWITCH_H__ + +void DAP_SPI_Init(); +void DAP_SPI_Deinit(); +void DAP_SPI_Enable(); +void DAP_SPI_Disable(); + + +#endif diff --git a/components/DAP/include/swo.h b/components/DAP/include/swo.h new file mode 100644 index 0000000..b7d1ff5 --- /dev/null +++ b/components/DAP/include/swo.h @@ -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 \ No newline at end of file diff --git a/components/DAP/include/uart_modify.h b/components/DAP/include/uart_modify.h index 3d3a277..c6f67f0 100644 --- a/components/DAP/include/uart_modify.h +++ b/components/DAP/include/uart_modify.h @@ -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 diff --git a/components/DAP/source/DAP.c b/components/DAP/source/DAP.c index 03f048c..973f0fb 100644 --- a/components/DAP/source/DAP.c +++ b/components/DAP/source/DAP.c @@ -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); } diff --git a/components/DAP/source/SWO.c b/components/DAP/source/SWO.c index d331a0c..7497ef6 100644 --- a/components/DAP/source/SWO.c +++ b/components/DAP/source/SWO.c @@ -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) */ diff --git a/components/DAP/source/SW_DP.c b/components/DAP/source/SW_DP.c index 803cf42..b65b1d6 100644 --- a/components/DAP/source/SW_DP.c +++ b/components/DAP/source/SW_DP.c @@ -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) */ diff --git a/components/DAP/source/dap_utility.c b/components/DAP/source/dap_utility.c new file mode 100644 index 0000000..94c0381 --- /dev/null +++ b/components/DAP/source/dap_utility.c @@ -0,0 +1,10 @@ +#include "dap_utility.h" + +const uint8_t kParityByteTable[256] = +{ + #define P2(n) n, n^1, n^1, n + #define P4(n) P2(n), P2(n^1), P2(n^1), P2(n) + #define P6(n) P4(n), P4(n^1), P4(n^1), P4(n) + + P6(0), P6(1), P6(1), P6(0) +}; diff --git a/components/DAP/source/spi_op.c b/components/DAP/source/spi_op.c new file mode 100644 index 0000000..3d95880 --- /dev/null +++ b/components/DAP/source/spi_op.c @@ -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 +#include + +#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; +} diff --git a/components/DAP/source/spi_switch.c b/components/DAP/source/spi_switch.c new file mode 100644 index 0000000..418faaf --- /dev/null +++ b/components/DAP/source/spi_switch.c @@ -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 + +#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); +} + diff --git a/components/DAP/source/uart_modify.c b/components/DAP/source/uart_modify.c index e485482..df5ad3a 100644 --- a/components/DAP/source/uart_modify.c +++ b/components/DAP/source/uart_modify.c @@ -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; +} diff --git a/components/README.md b/components/README.md deleted file mode 100644 index 3fc0da1..0000000 --- a/components/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# TODO -1. USB \ No newline at end of file diff --git a/components/USBIP/MSOS20Descriptors.c b/components/USBIP/MSOS20Descriptors.c index 6621557..8e3ba5d 100644 --- a/components/USBIP/MSOS20Descriptors.c +++ b/components/USBIP/MSOS20Descriptors.c @@ -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: diff --git a/components/USBIP/USB_handle.c b/components/USBIP/USB_handle.c index f9fe76a..e806f1e 100644 --- a/components/USBIP/USB_handle.c +++ b/components/USBIP/USB_handle.c @@ -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); diff --git a/components/USBIP/USBd_config.c b/components/USBIP/USBd_config.c index 0061a8b..a15bf51 100644 --- a/components/USBIP/USBd_config.c +++ b/components/USBIP/USBd_config.c @@ -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 diff --git a/components/USBIP/USBd_config.h b/components/USBIP/USBd_config.h index dc3a3e2..188b529 100644 --- a/components/USBIP/USBd_config.h +++ b/components/USBIP/USBd_config.h @@ -1,7 +1,7 @@ #ifndef __USBD_CONFIG_H__ #define __USBD_CONFIG_H__ -#define USE_WINUSB 0 +#include "dap_configuration.h" // Vendor ID assigned by USB-IF (idVendor). #define USBD0_DEV_DESC_IDVENDOR 0xC251 diff --git a/main/DAP_handle.c b/main/DAP_handle.c index a3bff99..1aa3f9d 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -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 -#include -#include "usbip_server.h" -#include "DAP_handle.h" -#include "DAP.h" -#include "esp_libc.h" -#include "USBd_config.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/ringbuf.h" -#include "freertos/semphr.h" - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -extern int kSock; -extern TaskHandle_t kDAPTaskHandle; -////TODO: Merge this -#define DAP_PACKET_SIZE 255 - -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 +#include + +#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 + +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]); + } } \ No newline at end of file diff --git a/main/dap_configuration.h b/main/dap_configuration.h new file mode 100644 index 0000000..4779c4c --- /dev/null +++ b/main/dap_configuration.h @@ -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 diff --git a/main/main.c b/main/main.c index bc92117..de1b1fa 100644 --- a/main/main.c +++ b/main/main.c @@ -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 -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -#include "tcp_server.h" -#include "timer.h" -#include "wifi_configuration.h" - - - -extern void SWO_Thread(void *argument); -extern void usart_monitor_task(void *argument); -extern void DAP_Setup(void); -extern void DAP_Thread(void *argument); - -/* FreeRTOS event group to signal when we are connected & ready to make a request */ -static EventGroupHandle_t wifi_event_group; -TaskHandle_t kDAPTaskHandle = NULL; - -const int IPV4_GOTIP_BIT = BIT0; -#ifdef CONFIG_EXAMPLE_IPV6 -const int IPV6_GOTIP_BIT = BIT1; -#endif - - -static esp_err_t event_handler(void *ctx, system_event_t *event) -{ - /* For accessing reason codes in case of disconnection */ - system_event_info_t *info = &event->event_info; - - switch (event->event_id) - { - case SYSTEM_EVENT_STA_START: - esp_wifi_connect(); - os_printf("SYSTEM_EVENT_STA_START\r\n"); - break; - case SYSTEM_EVENT_STA_CONNECTED: -#ifdef CONFIG_EXAMPLE_IPV6 - /* enable ipv6 */ - tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_STA); -#endif - break; - case SYSTEM_EVENT_STA_GOT_IP: - xEventGroupSetBits(wifi_event_group, IPV4_GOTIP_BIT); - os_printf("SYSTEM_EVENT_STA_GOT_IP\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 +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +#include "tcp_server.h" +#include "timer.h" +#include "wifi_configuration.h" +#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... +} diff --git a/main/monitor.c b/main/monitor.c new file mode 100644 index 0000000..14a52d8 --- /dev/null +++ b/main/monitor.c @@ -0,0 +1,23 @@ +#include +#include +#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); + } +} \ No newline at end of file diff --git a/main/tcp_server.c b/main/tcp_server.c index 99e9fe8..8f85f6f 100644 --- a/main/tcp_server.c +++ b/main/tcp_server.c @@ -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 -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/event_groups.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_event_loop.h" -#include "esp_log.h" -#include "nvs_flash.h" - -#include "lwip/err.h" -#include "lwip/sockets.h" -#include "lwip/sys.h" -#include - -#include "wifi_configuration.h" -#include "usbip_server.h" - -uint8_t kState = ACCEPTING; -int kSock = -1; - -void tcp_server_task(void *pvParameters) -{ - uint8_t tcp_rx_buffer[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 +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "esp_system.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "nvs_flash.h" + +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include + +#include "wifi_configuration.h" +#include "usbip_server.h" + +extern TaskHandle_t kDAPTaskHandle; +extern int kRestartDAPHandle; + +uint8_t kState = ACCEPTING; +int kSock = -1; + +void tcp_server_task(void *pvParameters) +{ + uint8_t tcp_rx_buffer[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); } \ No newline at end of file diff --git a/main/timer.c b/main/timer.c index 6fbe6b7..5682c8f 100644 --- a/main/timer.c +++ b/main/timer.c @@ -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 #include + #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; } \ No newline at end of file diff --git a/main/timer.h b/main/timer.h index bc569a9..1fa4fa0 100644 --- a/main/timer.h +++ b/main/timer.h @@ -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 -#endif \ No newline at end of file + +// 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 \ No newline at end of file diff --git a/main/usbip_server.c b/main/usbip_server.c index 1eb2b75..0e8ab2b 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -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"); diff --git a/main/usbip_server.h b/main/usbip_server.h index 2d0effd..08b6c10 100644 --- a/main/usbip_server.h +++ b/main/usbip_server.h @@ -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 \ No newline at end of file diff --git a/main/wifi_configuration.h b/main/wifi_configuration.h index 5f84b6d..6c40f2c 100644 --- a/main/wifi_configuration.h +++ b/main/wifi_configuration.h @@ -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 \ No newline at end of file +#endif \ No newline at end of file diff --git a/sdkconfig b/sdkconfig index e20f324..538549f 100644 --- a/sdkconfig +++ b/sdkconfig @@ -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