From 2863553018f6277740c3cf8b75a204bb4b845cf2 Mon Sep 17 00:00:00 2001 From: windowsair Date: Thu, 25 Feb 2021 11:54:50 +0800 Subject: [PATCH] feat: Try to support SWO (Still Unavailable) --- .gitignore | 3 +- components/DAP/config/DAP_config.h | 19 +- components/DAP/include/DAP.h | 4 +- components/DAP/include/swo.h | 17 + components/DAP/include/uart_modify.h | 35 +- components/DAP/source/SWO.c | 499 ++++++++++++--------------- components/DAP/source/SW_DP.c | 2 +- components/DAP/source/spi_op.c | 22 +- components/DAP/source/uart_modify.c | 118 ++++++- main/DAP_handle.c | 57 ++- main/main.c | 37 +- main/timer.c | 47 ++- main/timer.h | 69 +++- sdkconfig | 8 +- 14 files changed, 564 insertions(+), 373 deletions(-) create mode 100644 components/DAP/include/swo.h diff --git a/.gitignore b/.gitignore index 9a47b5a..33904f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vscode/ build/ -tmp/ \ No newline at end of file +tmp/ +.history/ \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index c3b724d..11bf230 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -30,6 +30,7 @@ * @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 * @@ -46,7 +47,7 @@ #include "cmsis_compiler.h" #include "gpio.h" #include "gpio_struct.h" -#include "timer_struct.h" +#include "timer.h" #include "esp8266/pin_mux_register.h" #include "gpio_op.h" @@ -118,9 +119,13 @@ This information includes: /// 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 1 ///< 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 0 ///< SWO UART: 1 = available, 0 = not available. +#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. @@ -130,12 +135,14 @@ This information includes: /// 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 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n). +#define SWO_BUFFER_SIZE 2048U ///< 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. +#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). @@ -160,7 +167,6 @@ This information includes: */ __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; @@ -648,8 +654,7 @@ default, the DWT timer is used. The frequency of this timer is configured with */ __STATIC_INLINE uint32_t TIMESTAMP_GET(void) { - // FRC1 is a 23-bit countdown timer - return (0x7FFFFF - (frc1.count.data)); + return get_timer_count(); } ///@} diff --git a/components/DAP/include/DAP.h b/components/DAP/include/DAP.h index e7260d3..a011a92 100644 --- a/components/DAP/include/DAP.h +++ b/components/DAP/include/DAP.h @@ -273,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/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/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 9a2088f..b65b1d6 100644 --- a/components/DAP/source/SW_DP.c +++ b/components/DAP/source/SW_DP.c @@ -218,6 +218,7 @@ void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { // 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; @@ -355,7 +356,6 @@ static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) { } else { - //// FIXME: bug /* Protocol error */ DAP_SPI_Disable(); PIN_SWDIO_TMS_SET(); diff --git a/components/DAP/source/spi_op.c b/components/DAP/source/spi_op.c index 728c837..f5dba3d 100644 --- a/components/DAP/source/spi_op.c +++ b/components/DAP/source/spi_op.c @@ -83,7 +83,7 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf) // Start transmission DAP_SPI.cmd.usr = 1; // Wait for sending to complete - while (DAP_SPI.cmd.usr); + while (DAP_SPI.cmd.usr) continue; } @@ -108,7 +108,7 @@ void DAP_SPI_ReadBits(const uint8_t count, uint8_t *buf) { // Start transmission DAP_SPI.cmd.usr = 1; // Wait for reading to complete - while (DAP_SPI.cmd.usr); + while (DAP_SPI.cmd.usr) continue; data_buf[0] = DAP_SPI.data_buf[0]; data_buf[1] = DAP_SPI.data_buf[1]; @@ -148,7 +148,7 @@ __FORCEINLINE void DAP_SPI_Send_Header(const uint8_t packetHeaderData, uint8_t * // Start transmission DAP_SPI.cmd.usr = 1; // Wait for sending to complete - while (DAP_SPI.cmd.usr); + while (DAP_SPI.cmd.usr) continue; dataBuf = DAP_SPI.data_buf[0]; *ack = (dataBuf >> 1) & 0b111; @@ -175,7 +175,7 @@ __FORCEINLINE void DAP_SPI_Read_Data(uint32_t *resData, uint8_t *resParity) // Start transmission DAP_SPI.cmd.usr = 1; // Wait for sending to complete - while (DAP_SPI.cmd.usr); + while (DAP_SPI.cmd.usr) continue; pU32Data[0] = DAP_SPI.data_buf[0]; pU32Data[1] = DAP_SPI.data_buf[1]; @@ -204,7 +204,7 @@ __FORCEINLINE void DAP_SPI_Write_Data(uint32_t data, uint8_t parity) // Start transmission DAP_SPI.cmd.usr = 1; // Wait for sending to complete - while (DAP_SPI.cmd.usr); + while (DAP_SPI.cmd.usr) continue; } /** @@ -221,8 +221,10 @@ __FORCEINLINE void DAP_SPI_Generate_Cycle(uint8_t num) DAP_SPI.data_buf[0] = 0x00000000U; + // Start transmission DAP_SPI.cmd.usr = 1; - while (DAP_SPI.cmd.usr); + // Wait for sending to complete + while (DAP_SPI.cmd.usr) continue; } @@ -239,8 +241,10 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Read() DAP_SPI.data_buf[0] = 0xFFFFFFFFU; DAP_SPI.data_buf[1] = 0xFFFFFFFFU; + // Start transmission DAP_SPI.cmd.usr = 1; - while (DAP_SPI.cmd.usr); + // Wait for sending to complete + while (DAP_SPI.cmd.usr) continue; } @@ -257,6 +261,8 @@ __FORCEINLINE void DAP_SPI_Protocol_Error_Write() DAP_SPI.data_buf[0] = 0xFFFFFFFFU; DAP_SPI.data_buf[1] = 0xFFFFFFFFU; + // Start transmission DAP_SPI.cmd.usr = 1; - while (DAP_SPI.cmd.usr); + // Wait for sending to complete + while (DAP_SPI.cmd.usr) continue; } 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/main/DAP_handle.c b/main/DAP_handle.c index ff7f2cc..042b464 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -1,21 +1,24 @@ /** * @file DAP_handle.c * @brief Handle DAP packets and transaction push - * @version 0.3 - * @date 2020-02-04 first version - * 2020-11-11 support WinUSB mode - * - * @copyright Copyright (c) 2020 - * + * @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" @@ -55,10 +58,12 @@ 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 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; @@ -76,7 +81,7 @@ void handle_dap_data_request(usbip_stage2_header *header, uint32_t length) // 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); + xRingbufferSend(dap_dataIN_handle, data_in - sizeof(uint32_t), DAP_HANDLE_SIZE, portMAX_DELAY); xTaskNotifyGive(kDAPTaskHandle); #else @@ -110,17 +115,17 @@ void handle_dap_data_response(usbip_stage2_header *header) void handle_swo_trace_response(usbip_stage2_header *header) { - // TODO: - send_stage2_submit(header, 0, 0); - return; - if (swo_trace_respond) + if (kSwoTransferBusy) { - swo_trace_respond = 0; - //send_stage2_submit_data(header, 0, (void *)DAPDataProcessed.buf, DAP_PACKET_SIZE); + // 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); } } @@ -131,15 +136,7 @@ void handle_swo_trace_response(usbip_stage2_header *header) 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 ... + swo_data_num = num; } void DAP_Thread(void *argument) @@ -181,7 +178,7 @@ void DAP_Thread(void *argument) ulTaskNotifyTake(pdFALSE, portMAX_DELAY); packetSize = 0; item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize, - (1 / portTICK_RATE_MS), DAP_HANDLE_SIZE); + pdMS_TO_TICKS(1), DAP_HANDLE_SIZE); if (packetSize == 0) { break; @@ -200,7 +197,7 @@ void DAP_Thread(void *argument) 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 = 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. @@ -229,7 +226,7 @@ int fast_reply(uint8_t *buf, uint32_t length) DAPPacetDataType *item; size_t packetSize = 0; item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataOUT_handle, &packetSize, - (10 / portTICK_RATE_MS), DAP_HANDLE_SIZE); + pdMS_TO_TICKS(10), DAP_HANDLE_SIZE); if (packetSize == DAP_HANDLE_SIZE) { unpack((uint32_t *)buf, sizeof(usbip_stage2_header)); @@ -240,7 +237,7 @@ int fast_reply(uint8_t *buf, uint32_t length) #else send_stage2_submit_data((usbip_stage2_header *)buf, 0, item->buf, DAP_HANDLE_SIZE); #endif - + if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) { @@ -259,7 +256,7 @@ int fast_reply(uint8_t *buf, uint32_t length) } else { - //// TODO: ep0 dir 0 ? + //// TODO: ep0 dir 0 ? buf[0x3] = 0x3; // command buf[0xF] = 0; // direction buf[0x16] = 0; diff --git a/main/main.c b/main/main.c index a8c3e85..4e2dad5 100644 --- a/main/main.c +++ b/main/main.c @@ -26,16 +26,19 @@ #include "tcp_server.h" #include "timer.h" #include "wifi_configuration.h" +#include "DAP_config.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); +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; -TaskHandle_t kDAPTaskHandle = NULL; const int IPV4_GOTIP_BIT = BIT0; #ifdef CONFIG_EXAMPLE_IPV6 @@ -128,15 +131,35 @@ static void wait_for_ip() 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(); // DAP Setup + DAP_Setup(); + timer_init(); + - xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 14, NULL); xTaskCreate(DAP_Thread, "DAP_Task", 2048, NULL, 10, &kDAPTaskHandle); // SWO Trace Task - //xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); - //xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); + #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/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/sdkconfig b/sdkconfig index c3b4568..afbd3ae 100644 --- a/sdkconfig +++ b/sdkconfig @@ -104,10 +104,12 @@ CONFIG_USING_NEW_ETS_VPRINTF=y # CONFIG_LINK_ETS_PRINTF_TO_IRAM is not set 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_DEFAULT is not set +CONFIG_CONSOLE_UART_CUSTOM=y # CONFIG_CONSOLE_UART_NONE is not set -CONFIG_CONSOLE_UART_NUM=0 +# 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_DISABLE_ROM_UART_PRINT is not set