0
0
Fork 0

feat: Try to support SWO (Still Unavailable)

This commit is contained in:
windowsair 2021-02-25 11:54:50 +08:00
parent dc0ab3b547
commit 2863553018
14 changed files with 564 additions and 373 deletions

3
.gitignore vendored
View File

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

View File

@ -30,6 +30,7 @@
* @author windowsair * @author windowsair
* @brief Adaptation of GPIO and SPI pin * @brief Adaptation of GPIO and SPI pin
* @change: 2021-2-10 Support GPIO and SPI * @change: 2021-2-10 Support GPIO and SPI
* 2021-2-18 Try to support SWO
* @version 0.1 * @version 0.1
* @date 2021-2-10 * @date 2021-2-10
* *
@ -46,7 +47,7 @@
#include "cmsis_compiler.h" #include "cmsis_compiler.h"
#include "gpio.h" #include "gpio.h"
#include "gpio_struct.h" #include "gpio_struct.h"
#include "timer_struct.h" #include "timer.h"
#include "esp8266/pin_mux_register.h" #include "esp8266/pin_mux_register.h"
#include "gpio_op.h" #include "gpio_op.h"
@ -118,9 +119,13 @@ This information includes:
/// setting can be reduced (valid range is 1 .. 255). /// setting can be reduced (valid range is 1 .. 255).
#define DAP_PACKET_COUNT 255 ///< Specifies number of packets buffered. #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. /// Indicate that UART Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>. /// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#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. /// Maximum SWO UART Baudrate.
#define SWO_UART_MAX_BAUDRATE (115200U * 40U) ///< SWO UART Maximum Baudrate in Hz. #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. /// Indicate that Manchester Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>. /// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available. #define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available.
// (windowsair)Do not modify. Not support.
/// SWO Trace Buffer Size. /// 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. /// 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. /// 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). #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) __STATIC_INLINE uint8_t DAP_GetVendorString(char *str)
{ {
////TODO: fill this
// In fact, Keil can get the corresponding information through USB // In fact, Keil can get the corresponding information through USB
// without filling in this information. // without filling in this information.
// (void)str; // (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) __STATIC_INLINE uint32_t TIMESTAMP_GET(void)
{ {
// FRC1 is a 23-bit countdown timer return get_timer_count();
return (0x7FFFFF - (frc1.count.data));
} }
///@} ///@}

View File

@ -273,8 +273,8 @@ extern void SWO_TransferComplete (void);
extern uint32_t UART_SWO_Mode (uint32_t enable); extern uint32_t UART_SWO_Mode (uint32_t enable);
extern uint32_t UART_SWO_Baudrate (uint32_t baudrate); extern uint32_t UART_SWO_Baudrate (uint32_t baudrate);
extern uint32_t UART_SWO_Control (uint32_t active); extern uint32_t UART_SWO_Control (uint32_t active);
extern void UART_SWO_Capture (uint8_t *buf, uint32_t num); // extern void UART_SWO_Capture (uint8_t *buf, uint32_t num);
extern uint32_t UART_SWO_GetCount (void); // extern uint32_t UART_SWO_GetCount (void);
extern uint32_t Manchester_SWO_Mode (uint32_t enable); extern uint32_t Manchester_SWO_Mode (uint32_t enable);
extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate); extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate);

View File

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

View File

@ -1,6 +1,6 @@
/** /**
* @brief Made some simple modifications to the official UART * @brief Made some simple modifications to the official UART
* *
*/ */
// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD // Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
@ -28,6 +28,13 @@ extern "C" {
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "freertos/queue.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_FIFO_LEN (128) /*!< Length of the hardware FIFO buffers */
#define UART_INTR_MASK 0x1ff /*!< Mask of all UART interrupts */ #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 * @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. * 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. * @param no_use Invalid parameters, just to fit some modules.
* *
* @return * @return
* - ESP_OK Success * - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error * - 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); 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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,6 +1,14 @@
/** /**
* @brief Modify this file to fit esp8266 Uart * @file SWO.c
* * @author windowsair
* @brief SWO support
* @change: 2021-02-17: Add basic functions
* @version 0.2
*
* @date 2021-02-17
*
* @copyright Copyright (c) 2021
*
*/ */
/* /*
@ -37,15 +45,11 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/event_groups.h" #include "freertos/event_groups.h"
#include "uart_modify.h" #include "uart_modify.h"
#include "swo.h"
EventGroupHandle_t kSwoThreadEventGroup;
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
#if (SWO_STREAM != 0) #if (SWO_STREAM != 0)
@ -61,14 +65,14 @@ EventGroupHandle_t kUART_Monitoe_event_group;
#endif #endif
// use in baudrate setting
static uint8_t USART_Ready = 0U; static uint8_t USART_Ready = 0U;
#endif /* (SWO_UART != 0) */ #endif /* (SWO_UART != 0) */
#if ((SWO_UART != 0) || (SWO_MANCHESTER != 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 USB_BLOCK_SIZE 512U /* USB Block Size */
#define TRACE_BLOCK_SIZE 64U /* Trace Block Size (2^n: 32...512) */ #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 */ static uint8_t TraceError_n = 0U; /* Active Trace Error bank */
// Trace Buffer // 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 TraceIndexI = 0U; /* Incoming Trace Index */
static volatile uint32_t TraceIndexO = 0U; /* Outgoing Trace Index */ static volatile uint32_t TraceIndexO = 0U; /* Outgoing Trace Index */
static volatile uint8_t TraceUpdate; /* Trace Update Flag */ static volatile uint8_t TraceUpdate; /* Trace Update Flag */
@ -101,105 +105,35 @@ static void ClearTrace(void);
static void ResumeTrace(void); static void ResumeTrace(void);
static uint32_t GetTraceCount(void); static uint32_t GetTraceCount(void);
static uint8_t GetTraceStatus(void); static uint8_t GetTraceStatus(void);
void SetTraceError(uint8_t flag);
#if (SWO_STREAM != 0) #if (SWO_STREAM != 0)
static volatile uint8_t TransferBusy = 0U; /* Transfer Busy Flag */ volatile uint8_t kSwoTransferBusy = 0U; /* Transfer Busy Flag */
static uint32_t TransferSize; /* Current Transfer Size */ static uint32_t TransferSize; /* Current Transfer Size */
#endif #endif
#if (SWO_UART != 0) #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 or disable UART SWO Mode
// enable: enable flag // enable: enable flag
// return: 1 - Success, 0 - Error // 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; int32_t status;
USART_Ready = 0U; USART_Ready = 0U;
uart_config_t uart_config = { uart_config_t uart_config = {
.baud_rate = 115200, .baud_rate = 74880,
.data_bits = UART_DATA_8_BITS, .data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE, .parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1, .stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE}; .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) #define BUF_SIZE (1024)
my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0); //// TODO: remove this
if (enable != 0U) 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); status = my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0);
if (status != ESP_OK) if (status != ESP_OK)
{ {
my_uart_driver_delete(USART_PORT);
return (0U); return (0U);
} }
} }
@ -214,6 +149,7 @@ __WEAK uint32_t UART_SWO_Mode(uint32_t enable)
{ {
my_uart_driver_delete(USART_PORT); my_uart_driver_delete(USART_PORT);
} }
return (1U); return (1U);
@ -222,11 +158,12 @@ __WEAK uint32_t UART_SWO_Mode(uint32_t enable)
// Configure UART SWO Baudrate // Configure UART SWO Baudrate
// baudrate: requested baudrate // baudrate: requested baudrate
// return: actual baudrate or 0 when not configured // 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 index;
uint32_t num; uint32_t remain_trace_block_size;
if (baudrate > SWO_UART_MAX_BAUDRATE) 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) if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)
{ {
size_t len = 0; TraceIndexI += my_uart_get_rx_buffered_data_len(USART_PORT);
my_uart_get_buffered_data_len(USART_PORT, &len);
my_uart_flush(USART_PORT); my_uart_flush(USART_PORT);
TraceIndexI += len;
// pUSART->Control(ARM_USART_CONTROL_RX, 0U); // pUSART->Control(ARM_USART_CONTROL_RX, 0U);
// if (pUSART->GetStatus().rx_busy) // 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_ACTIVE)
{ {
if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 0U) if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 0U)
{ {
index = TraceIndexI & (SWO_BUFFER_SIZE - 1U); index = TraceIndexI & (SWO_BUFFER_SIZE - 1U); // TraceIndexI % SWO_BUFFER_SIZE
num = TRACE_BLOCK_SIZE - (index & (TRACE_BLOCK_SIZE - 1U)); remain_trace_block_size = TRACE_BLOCK_SIZE - (index & (TRACE_BLOCK_SIZE - 1U)); // index % TRACE_BLOCK_SIZE
TraceBlockSize = num; TraceBlockSize = remain_trace_block_size;
//pUSART->Receive(&TraceBuf[index], num); //pUSART->Receive(&kSwoTraceBuf[index], num);
my_uart_read_bytes(USART_PORT, &TraceBuf[index], num, 20 / portTICK_RATE_MS); 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); return (baudrate);
@ -279,7 +206,7 @@ __WEAK uint32_t UART_SWO_Baudrate(uint32_t baudrate)
// Control UART SWO Capture // Control UART SWO Capture
// active: active flag // active: active flag
// return: 1 - Success, 0 - Error // 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; int32_t status;
@ -290,7 +217,8 @@ __WEAK uint32_t UART_SWO_Control(uint32_t active)
return (0U); return (0U);
} }
TraceBlockSize = 1U; 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) if (status == ESP_FAIL)
{ {
return (0U); return (0U);
@ -299,14 +227,13 @@ __WEAK uint32_t UART_SWO_Control(uint32_t active)
// if (status != ARM_DRIVER_OK) // if (status != ARM_DRIVER_OK)
// { // {
// return (0U); // return (0U);
// } ////TODO: // }
} }
else else
{ {
size_t len = 0; // no active
my_uart_get_buffered_data_len(USART_PORT, &len); TraceIndexI += my_uart_get_rx_buffered_data_len(USART_PORT);
my_uart_flush(USART_PORT); my_uart_flush(USART_PORT);
TraceIndexI += len;
// pUSART->Control(ARM_USART_CONTROL_RX, 0U); // pUSART->Control(ARM_USART_CONTROL_RX, 0U);
// if (pUSART->GetStatus().rx_busy) // if (pUSART->GetStatus().rx_busy)
// { // {
@ -318,20 +245,19 @@ __WEAK uint32_t UART_SWO_Control(uint32_t active)
} }
// Start UART SWO Capture // Start UART SWO Capture
// buf: pointer to buffer for capturing // index: trace buffer index to read
// num: number of bytes to capture // 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; 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 // Get UART SWO Pending Trace Count
// return: number of pending trace data bytes // 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) // if (pUSART->GetStatus().rx_busy)
// { // {
// count = pUSART->GetRxCount(); // count = pUSART->GetRxCount();
@ -340,65 +266,31 @@ __WEAK uint32_t UART_SWO_GetCount(void)
// { // {
// count = 0U; // count = 0U;
// } // }
my_uart_get_buffered_data_len(USART_PORT, &count); return my_uart_get_rx_buffered_data_len(USART_PORT);
return (count);
} }
#endif /* (SWO_UART != 0) */ #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 // Trace status helper functions
// return: actual baudrate or 0 when not configured //
__WEAK uint32_t Manchester_SWO_Baudrate(uint32_t baudrate)
{
return (0U);
}
// 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 // Clear Trace Errors and Data
static void ClearTrace(void) static void ClearTrace(void)
{ {
#if (SWO_STREAM != 0) #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(); // Unfortunately, we cannot abort the transmission
TransferBusy = 0U; // SWO_AbortTransfer();
kSwoTransferBusy = 0U;
} }
} }
#endif #endif
@ -430,18 +322,10 @@ static void ResumeTrace(void)
index_i &= SWO_BUFFER_SIZE - 1U; index_i &= SWO_BUFFER_SIZE - 1U;
switch (TraceMode) switch (TraceMode)
{ {
#if (SWO_UART != 0)
case DAP_SWO_UART: case DAP_SWO_UART:
TraceStatus = DAP_SWO_CAPTURE_ACTIVE; TraceStatus = DAP_SWO_CAPTURE_ACTIVE;
UART_SWO_Capture(&TraceBuf[index_i], 1U); UART_SWO_Capture(index_i, 1U);
break; 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: default:
break; break;
} }
@ -463,20 +347,15 @@ static uint32_t GetTraceCount(void)
count = TraceIndexI - TraceIndexO; count = TraceIndexI - TraceIndexO;
switch (TraceMode) switch (TraceMode)
{ {
#if (SWO_UART != 0)
case DAP_SWO_UART: case DAP_SWO_UART:
count += UART_SWO_GetCount(); count += UART_SWO_GetCount();
break; break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
count += Manchester_SWO_GetCount();
break;
#endif
default: default:
break; break;
} }
vTaskDelay(pdMS_TO_TICKS(10));
} while (TraceUpdate != 0U); } while (TraceUpdate != 0U);
// Synchronously wait for the data to complete
} }
else else
{ {
@ -541,14 +420,7 @@ uint32_t SWO_Transport(const uint8_t *request, uint8_t *response)
result = 0U; result = 0U;
} }
if (result != 0U) *response = result ? DAP_OK : DAP_ERROR;
{
*response = DAP_OK;
}
else
{
*response = DAP_ERROR;
}
return ((1U << 16) | 1U); return ((1U << 16) | 1U);
} }
@ -565,6 +437,7 @@ uint32_t SWO_Mode(const uint8_t *request, uint8_t *response)
mode = *request; mode = *request;
// disable swo mode
switch (TraceMode) switch (TraceMode)
{ {
#if (SWO_UART != 0) #if (SWO_UART != 0)
@ -572,11 +445,7 @@ uint32_t SWO_Mode(const uint8_t *request, uint8_t *response)
UART_SWO_Mode(0U); UART_SWO_Mode(0U);
break; break;
#endif #endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
Manchester_SWO_Mode(0U);
break;
#endif
default: default:
break; break;
} }
@ -591,34 +460,18 @@ uint32_t SWO_Mode(const uint8_t *request, uint8_t *response)
result = UART_SWO_Mode(1U); result = UART_SWO_Mode(1U);
break; break;
#endif #endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
result = Manchester_SWO_Mode(1U);
break;
#endif
default: default:
result = 0U; result = 0U;
break; break;
} }
if (result != 0U)
{ // DAP_SWO_OFF -> has error
TraceMode = mode; TraceMode = result ? mode : DAP_SWO_OFF;
}
else
{
TraceMode = DAP_SWO_OFF;
}
TraceStatus = 0U; TraceStatus = 0U;
if (result != 0U) *response = result ? DAP_OK : DAP_ERROR;
{
*response = DAP_OK;
}
else
{
*response = DAP_ERROR;
}
return ((1U << 16) | 1U); return ((1U << 16) | 1U);
} }
@ -644,11 +497,7 @@ uint32_t SWO_Baudrate(const uint8_t *request, uint8_t *response)
baudrate = UART_SWO_Baudrate(baudrate); baudrate = UART_SWO_Baudrate(baudrate);
break; break;
#endif #endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
baudrate = Manchester_SWO_Baudrate(baudrate);
break;
#endif
default: default:
baudrate = 0U; baudrate = 0U;
break; 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 != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE))
{ {
if (active) // active status: request != now status
if (active) // request: active
{ {
ClearTrace(); ClearTrace();
} }
@ -692,39 +543,32 @@ uint32_t SWO_Control(const uint8_t *request, uint8_t *response)
result = UART_SWO_Control(active); result = UART_SWO_Control(active);
break; break;
#endif #endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
result = Manchester_SWO_Control(active);
break;
#endif
default: default:
result = 0U; result = 0U;
break; break;
} }
if (result != 0U) if (result != 0U)
{ {
// success done
TraceStatus = active; TraceStatus = active;
#if (SWO_STREAM != 0) #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 #endif
} }
} }
else else
{ {
// request: active but already actived
result = 1U; result = 1U;
} }
if (result != 0U)
{ *response = result ? DAP_OK : DAP_ERROR;
*response = DAP_OK;
}
else
{
*response = DAP_ERROR;
}
return ((1U << 16) | 1U); return ((1U << 16) | 1U);
} }
@ -793,6 +637,7 @@ uint32_t SWO_ExtendedStatus(const uint8_t *request, uint8_t *response)
TraceUpdate = 0U; TraceUpdate = 0U;
index = TraceTimestamp.index; index = TraceTimestamp.index;
tick = TraceTimestamp.tick; tick = TraceTimestamp.tick;
vTaskDelay(pdMS_TO_TICKS(10));
} while (TraceUpdate != 0U); } while (TraceUpdate != 0U);
*response++ = (uint8_t)(index >> 0); *response++ = (uint8_t)(index >> 0);
*response++ = (uint8_t)(index >> 8); *response++ = (uint8_t)(index >> 8);
@ -824,6 +669,8 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
status = GetTraceStatus(); status = GetTraceStatus();
count = GetTraceCount(); count = GetTraceCount();
// transport 1: use DAP SWO command
// transport 2: WinUSB
if (TraceTransport == 1U) if (TraceTransport == 1U)
{ {
n = (uint32_t)(*(request + 0) << 0) | n = (uint32_t)(*(request + 0) << 0) |
@ -839,6 +686,7 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
} }
else else
{ {
// if use winusb, then nothing to do.
count = 0U; count = 0U;
} }
@ -852,7 +700,7 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
for (i = index, n = count; n; n--) for (i = index, n = count; n; n--)
{ {
i &= SWO_BUFFER_SIZE - 1U; i &= SWO_BUFFER_SIZE - 1U;
*response++ = TraceBuf[i++]; *response++ = kSwoTraceBuf[i++];
} }
TraceIndexO = index + count; TraceIndexO = index + count;
ResumeTrace(); ResumeTrace();
@ -867,78 +715,171 @@ uint32_t SWO_Data(const uint8_t *request, uint8_t *response)
void SWO_TransferComplete(void) void SWO_TransferComplete(void)
{ {
TraceIndexO += TransferSize; TraceIndexO += TransferSize;
TransferBusy = 0U; kSwoTransferBusy = 0U;
ResumeTrace(); ResumeTrace();
xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA); xEventGroupSetBits(kSwoThreadEventGroup, SWO_GOT_DATA);
} }
// SWO Thread // SWO Thread
void SWO_Thread(void *argument) void SWO_Thread()
{ {
uint32_t timeout;
uint32_t flags; uint32_t flags;
uint32_t count; uint32_t count;
uint32_t index; uint32_t index;
uint32_t i, n; uint32_t i, n;
(void)argument;
timeout = portMAX_DELAY; uint32_t index_i;
uint32_t index_o;
kSWO_Thread_event_group = xEventGroupCreate(); uint32_t remain_trace_block_size;
TickType_t timeout = portMAX_DELAY;
kSwoThreadEventGroup = xEventGroupCreate();
for (;;) 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); 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 else
{ {
timeout = portMAX_DELAY; timeout = pdMS_TO_TICKS(150);
flags = SWO_ERROR_TIME_OUT;
} }
if (TransferBusy == 0U)
if (kSwoTransferBusy)
{ {
count = GetTraceCount(); continue;
if (count != 0U) }
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); count = n;
n = SWO_BUFFER_SIZE - index; }
if (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); n = USB_BLOCK_SIZE - i;
if (i == 0U) if (count >= n)
{ {
count &= ~(USB_BLOCK_SIZE - 1U); count = n; // The number of bytes to be sent exceeds the remain USB block size.
// Take down to the nearest number that is a multiple of USB_BLOCK_SIZE
} }
else else
{ {
n = USB_BLOCK_SIZE - i; count = 0U; // Haven't received a full USB block yet.
if (count >= n)
{
count = n;
}
else
{
count = 0U;
}
} }
} }
if (count != 0U) }
{ // Notify that there is data available for transmission
TransferSize = count; if (count != 0U)
TransferBusy = 1U; {
SWO_QueueTransfer(&TraceBuf[index], count); //through USB 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) */ #endif /* (SWO_STREAM != 0) */

View File

@ -218,6 +218,7 @@ void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
// data: DATA[31:0] // data: DATA[31:0]
// return: ACK[2:0] // return: ACK[2:0]
static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) { 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 // SPI transfer mode does not require operations such as PIN_DELAY
uint8_t ack; uint8_t ack;
// uint32_t bit; // uint32_t bit;
@ -355,7 +356,6 @@ static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) {
} }
else { else {
//// FIXME: bug
/* Protocol error */ /* Protocol error */
DAP_SPI_Disable(); DAP_SPI_Disable();
PIN_SWDIO_TMS_SET(); PIN_SWDIO_TMS_SET();

View File

@ -83,7 +83,7 @@ void DAP_SPI_WriteBits(const uint8_t count, const uint8_t *buf)
// Start transmission // Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
// Wait for sending to complete // 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 // Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
// Wait for reading to complete // 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[0] = DAP_SPI.data_buf[0];
data_buf[1] = DAP_SPI.data_buf[1]; 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 // Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
// Wait for sending to complete // Wait for sending to complete
while (DAP_SPI.cmd.usr); while (DAP_SPI.cmd.usr) continue;
dataBuf = DAP_SPI.data_buf[0]; dataBuf = DAP_SPI.data_buf[0];
*ack = (dataBuf >> 1) & 0b111; *ack = (dataBuf >> 1) & 0b111;
@ -175,7 +175,7 @@ __FORCEINLINE void DAP_SPI_Read_Data(uint32_t *resData, uint8_t *resParity)
// Start transmission // Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
// Wait for sending to complete // Wait for sending to complete
while (DAP_SPI.cmd.usr); while (DAP_SPI.cmd.usr) continue;
pU32Data[0] = DAP_SPI.data_buf[0]; pU32Data[0] = DAP_SPI.data_buf[0];
pU32Data[1] = DAP_SPI.data_buf[1]; 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 // Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
// Wait for sending to complete // 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; DAP_SPI.data_buf[0] = 0x00000000U;
// Start transmission
DAP_SPI.cmd.usr = 1; 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[0] = 0xFFFFFFFFU;
DAP_SPI.data_buf[1] = 0xFFFFFFFFU; DAP_SPI.data_buf[1] = 0xFFFFFFFFU;
// Start transmission
DAP_SPI.cmd.usr = 1; 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[0] = 0xFFFFFFFFU;
DAP_SPI.data_buf[1] = 0xFFFFFFFFU; DAP_SPI.data_buf[1] = 0xFFFFFFFFU;
// Start transmission
DAP_SPI.cmd.usr = 1; DAP_SPI.cmd.usr = 1;
while (DAP_SPI.cmd.usr); // Wait for sending to complete
while (DAP_SPI.cmd.usr) continue;
} }

View File

@ -1,6 +1,6 @@
/** /**
* @brief Made some simple modifications to the official UART * @brief Made some simple modifications to the official UART
* *
*/ */
// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD // Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD
@ -41,6 +41,7 @@
#include "rom/ets_sys.h" #include "rom/ets_sys.h"
#include "uart_modify.h" #include "uart_modify.h"
#include "swo.h"
#include "driver/uart_select.h" #include "driver/uart_select.h"
#define portYIELD_FROM_ISR() taskYIELD() #define portYIELD_FROM_ISR() taskYIELD()
@ -70,6 +71,11 @@ typedef struct
} tx_data; } tx_data;
} uart_tx_data_t; } uart_tx_data_t;
// read:
// hardware FIFO -> `rx_data_buf` -> `rx_ring_buf` -> user buf
typedef struct typedef struct
{ {
uart_port_t uart_num; /*!< UART port number*/ 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]; static uart_isr_func_t uart_isr_func[UART_NUM_MAX];
// SWO modify // 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_ACTIVE (1U << 0)
#define DAP_SWO_CAPTURE_PAUSED (1U << 1) #define DAP_SWO_CAPTURE_PAUSED (1U << 1)
#define DAP_SWO_STREAM_ERROR (1U << 6) #define DAP_SWO_STREAM_ERROR (1U << 6)
#define DAP_SWO_BUFFER_OVERRUN (1U << 7) #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) 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_CHECK((data_bit < UART_DATA_BITS_MAX), "data bit error", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL(); 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) 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); UART_CHECK((data_bit), "empty pointer", ESP_FAIL);
*(data_bit) = UART[uart_num]->conf0.bit_num; *(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) 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_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL(); 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) 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); UART_CHECK((stop_bit), "empty pointer", ESP_FAIL);
(*stop_bit) = UART[uart_num]->conf0.stop_bit_num; (*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) 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)), UART_CHECK(((parity_mode == UART_PARITY_DISABLE) || (parity_mode == UART_PARITY_EVEN) || (parity_mode == UART_PARITY_ODD)),
"parity_mode error", ESP_ERR_INVALID_ARG); "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) 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_CHECK((parity_mode), "empty pointer", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL(); 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) 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_ENTER_CRITICAL();
UART[uart_num]->clk_div.val = (uint32_t)(UART_CLK_FREQ / baud_rate) & 0xFFFFF; UART[uart_num]->clk_div.val = (uint32_t)(UART_CLK_FREQ / baud_rate) & 0xFFFFF;
UART_EXIT_CRITICAL(); 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) 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); UART_CHECK((baudrate), "empty pointer", ESP_ERR_INVALID_ARG);
(*baudrate) = (UART_CLK_FREQ / (UART[uart_num]->clk_div.val & 0xFFFFF)); (*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) 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_CHECK((((inverse_mask & ~UART_LINE_INV_MASK) == 0) || (inverse_mask == 0)), "inverse_mask error", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL(); UART_ENTER_CRITICAL();
@ -377,6 +377,7 @@ static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num)
return ESP_OK; return ESP_OK;
} }
// Clear uart interrupts status.
esp_err_t my_uart_clear_intr_status(uart_port_t uart_num, uint32_t mask) 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); 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; return ESP_OK;
} }
// Set UART interrupt enable
esp_err_t my_uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask) 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); 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; return ESP_OK;
} }
// helper function
esp_err_t my_uart_enable_rx_intr(uart_port_t uart_num) 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); 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; return ESP_OK;
} }
static void uart_intr_service(void *arg) static void uart_intr_service(void *arg)
{ {
// UART intr process // UART intr process
@ -460,6 +468,7 @@ static void uart_intr_service(void *arg)
} while (++uart_num < UART_NUM_MAX); } 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) 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); 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; uart_obj_t *p_uart = (uart_obj_t *)param;
uint8_t uart_num = p_uart->uart_num; uint8_t uart_num = p_uart->uart_num;
uart_dev_t *uart_reg = 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; uint8_t buf_idx = 0;
uint32_t uart_intr_status = UART[uart_num]->int_st.val; uint32_t uart_intr_status = UART[uart_num]->int_st.val;
uart_event_t uart_event; uart_event_t uart_event;
@ -718,7 +727,17 @@ static void uart_rx_intr_handler_default(void *param)
else else
{ {
p_uart->rx_buffered_len += p_uart->rx_stash_len; 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; notify = UART_SELECT_READ_NOTIF;
@ -744,7 +763,7 @@ static void uart_rx_intr_handler_default(void *param)
// SWO modify // SWO modify
// Unfortunately, Overflow occurs usually there is no flow control. // Unfortunately, Overflow occurs usually there is no flow control.
// Although the overflow situation often occurs, // 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. // and there is basically no data loss.
////TODO: Can we get rid of this code? ////TODO: Can we get rid of this code?
SetTraceError(DAP_SWO_BUFFER_OVERRUN); 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, // Fill UART tx_fifo and return a number,
// This function by itself is not thread-safe, always call from within a muxed section. // 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) 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 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) 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)); 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 else
{ {
// nothing receive
xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); xSemaphoreGive(p_uart_obj[uart_num]->rx_mux);
return copy_len; 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; p_uart_obj[uart_num]->rx_buffer_full_flg = false;
UART_EXIT_CRITICAL(); UART_EXIT_CRITICAL();
my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); 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"))); 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) 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); 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_buffered_len += p_uart_obj[uart_num]->rx_stash_len;
p_uart_obj[uart_num]->rx_buffer_full_flg = false; p_uart_obj[uart_num]->rx_buffer_full_flg = false;
UART_EXIT_CRITICAL(); 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_ptr = NULL;
p_uart->rx_cur_remain = 0; p_uart->rx_cur_remain = 0;
p_uart->rx_head_ptr = NULL; 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); my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num);
xSemaphoreGive(p_uart->rx_mux); xSemaphoreGive(p_uart->rx_mux);
return ESP_OK; 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]->rx_buffered_len = 0;
p_uart_obj[uart_num]->wait_tx_done_flg = false; 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) if (uart_queue)
{ {
p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); 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); my_uart_disable_tx_intr(uart_num);
_xt_isr_mask(0x1 << ETS_UART_INUM); _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) if (p_uart_obj[uart_num]->tx_fifo_sem)
{ {
vSemaphoreDelete(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(); UART_EXIT_CRITICAL();
return ESP_OK; return ESP_OK;
} }
// SWO modify
esp_err_t my_uart_read_bytes_async_swo(uint32_t index, uint32_t length)
{
if (kSWO_read_num > 0) {
return ESP_FAIL;
}
xSemaphoreTake(kSWO_read_mux, (portTickType)portMAX_DELAY);
kSWO_read_num = length;
kSWO_read_index = index;
kSWO_uart_notify_enable = 1;
xSemaphoreGive(kSWO_read_mux);
return ESP_OK;
}
int my_uart_get_rx_buffered_data_len(uart_port_t uart_num)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_ARG);
return p_uart_obj[uart_num]->rx_buffered_len;
}

View File

@ -1,21 +1,24 @@
/** /**
* @file DAP_handle.c * @file DAP_handle.c
* @brief Handle DAP packets and transaction push * @brief Handle DAP packets and transaction push
* @version 0.3 * @version 0.4
* @date 2020-02-04 first version * @change: 2020.02.04 first version
* 2020-11-11 support WinUSB mode * 2020.11.11 support WinUSB mode
* * 2021.02.17 support SWO
* @copyright Copyright (c) 2020 *
* * @copyright Copyright (c) 2021
*
*/ */
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "usbip_server.h" #include "usbip_server.h"
#include "DAP_handle.h" #include "DAP_handle.h"
#include "DAP.h" #include "DAP.h"
#include "esp_libc.h" #include "esp_libc.h"
#include "USBd_config.h" #include "USBd_config.h"
#include "swo.h"
#include "dap_configuration.h" #include "dap_configuration.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
@ -55,10 +58,12 @@ static int dap_respond = 0;
// SWO Trace // SWO Trace
static int swo_trace_respond = 0; static uint8_t *swo_data_to_send = NULL;
static uint8_t *swo_data_to_send; static uint32_t swo_data_num;
static uint32_t num_swo_data;
// DAP handle
static RingbufHandle_t dap_dataIN_handle = NULL; static RingbufHandle_t dap_dataIN_handle = NULL;
static RingbufHandle_t dap_dataOUT_handle = NULL; static RingbufHandle_t dap_dataOUT_handle = NULL;
static SemaphoreHandle_t data_response_mux = 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 // 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 // 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); xTaskNotifyGive(kDAPTaskHandle);
#else #else
@ -110,17 +115,17 @@ void handle_dap_data_response(usbip_stage2_header *header)
void handle_swo_trace_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; // busy indicates that there is data to be send
//send_stage2_submit_data(header, 0, (void *)DAPDataProcessed.buf, DAP_PACKET_SIZE); printf("swo use data\r\n");
send_stage2_submit_data(header, 0, (void *)swo_data_to_send, swo_data_num);
SWO_TransferComplete();
} }
else else
{ {
// nothing to send.
send_stage2_submit(header, 0, 0); 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) void SWO_QueueTransfer(uint8_t *buf, uint32_t num)
{ {
swo_data_to_send = buf; swo_data_to_send = buf;
num_swo_data = num; swo_data_num = 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) void DAP_Thread(void *argument)
@ -181,7 +178,7 @@ void DAP_Thread(void *argument)
ulTaskNotifyTake(pdFALSE, portMAX_DELAY); ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
packetSize = 0; packetSize = 0;
item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize, item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataIN_handle, &packetSize,
(1 / portTICK_RATE_MS), DAP_HANDLE_SIZE); pdMS_TO_TICKS(1), DAP_HANDLE_SIZE);
if (packetSize == 0) if (packetSize == 0)
{ {
break; break;
@ -200,7 +197,7 @@ void DAP_Thread(void *argument)
item->buf[0] = ID_DAP_ExecuteCommands; 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 resLength &= 0xFFFF; // res length in lower 16 bits
vRingbufferReturnItem(dap_dataIN_handle, (void *)item); // process done. vRingbufferReturnItem(dap_dataIN_handle, (void *)item); // process done.
@ -229,7 +226,7 @@ int fast_reply(uint8_t *buf, uint32_t length)
DAPPacetDataType *item; DAPPacetDataType *item;
size_t packetSize = 0; size_t packetSize = 0;
item = (DAPPacetDataType *)xRingbufferReceiveUpTo(dap_dataOUT_handle, &packetSize, 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) if (packetSize == DAP_HANDLE_SIZE)
{ {
unpack((uint32_t *)buf, sizeof(usbip_stage2_header)); unpack((uint32_t *)buf, sizeof(usbip_stage2_header));
@ -240,7 +237,7 @@ int fast_reply(uint8_t *buf, uint32_t length)
#else #else
send_stage2_submit_data((usbip_stage2_header *)buf, 0, item->buf, DAP_HANDLE_SIZE); send_stage2_submit_data((usbip_stage2_header *)buf, 0, item->buf, DAP_HANDLE_SIZE);
#endif #endif
if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE) if (xSemaphoreTake(data_response_mux, portMAX_DELAY) == pdTRUE)
{ {
@ -259,7 +256,7 @@ int fast_reply(uint8_t *buf, uint32_t length)
} }
else else
{ {
//// TODO: ep0 dir 0 ? //// TODO: ep0 dir 0 ?
buf[0x3] = 0x3; // command buf[0x3] = 0x3; // command
buf[0xF] = 0; // direction buf[0xF] = 0; // direction
buf[0x16] = 0; buf[0x16] = 0;

View File

@ -26,16 +26,19 @@
#include "tcp_server.h" #include "tcp_server.h"
#include "timer.h" #include "timer.h"
#include "wifi_configuration.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_Setup(void);
extern void DAP_Thread(void *argument); 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 */ /* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group; static EventGroupHandle_t wifi_event_group;
TaskHandle_t kDAPTaskHandle = NULL;
const int IPV4_GOTIP_BIT = BIT0; const int IPV4_GOTIP_BIT = BIT0;
#ifdef CONFIG_EXAMPLE_IPV6 #ifdef CONFIG_EXAMPLE_IPV6
@ -128,15 +131,35 @@ static void wait_for_ip()
void app_main() 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()); ESP_ERROR_CHECK(nvs_flash_init());
initialise_wifi(); initialise_wifi();
wait_for_ip(); 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(tcp_server_task, "tcp_server", 4096, NULL, 14, NULL);
xTaskCreate(DAP_Thread, "DAP_Task", 2048, NULL, 10, &kDAPTaskHandle); xTaskCreate(DAP_Thread, "DAP_Task", 2048, NULL, 10, &kDAPTaskHandle);
// SWO Trace Task // SWO Trace Task
//xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); #if (SWO_FUNCTION_ENABLE == 1)
//xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); xTaskCreate(SWO_Thread, "SWO_Task", 512, NULL, 10, NULL);
#endif
// It seems that the task is overly stressful...
} }

View File

@ -1,29 +1,52 @@
/** /**
* @file timer.c * @file timer.c
* @brief Hardware timer for DAP timestamp * @brief Hardware timer for DAP timestamp
* @version 0.1 * @change: 2021-02-18 Using the FRC2 timer
*
* @version 0.2
* @date 2020-01-22 * @date 2020-01-22
* *
* @copyright Copyright (c) 2020 * @copyright Copyright (c) 2021
* *
*/ */
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "timer.h" #include "timer.h"
#include "hw_timer.h" #include "hw_timer.h"
#include "timer_struct.h" #include "timer_struct.h"
#include "cmsis_compiler.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/event_groups.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(); vPortEnterCritical();
frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz frc2->ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz
frc1.ctrl.intr_type = TIMER_EDGE_INT; frc2->ctrl.intr_type = TIMER_EDGE_INT;
frc1.ctrl.reload = 0x01; frc2->ctrl.reload = 0x01; // enable auto reload
frc1.load.data = 0x7FFFFF; // 23bit?? frc2->load.val = 0x7FFFFFFF; // 31bit max
frc1.ctrl.en = 0x01; frc2->ctrl.en = 0x01;
vPortExitCritical(); vPortExitCritical();
vTaskDelete(NULL); }
// Timing up to 2147483647(0x7FFFFFFF) / 5000000(5MHz) = 429s
// 0.2 micro-second resolution
uint32_t get_timer_count()
{
return (uint32_t)frc2->count.data;
} }

View File

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

View File

@ -104,10 +104,12 @@ CONFIG_USING_NEW_ETS_VPRINTF=y
# CONFIG_LINK_ETS_PRINTF_TO_IRAM is not set # CONFIG_LINK_ETS_PRINTF_TO_IRAM is not set
CONFIG_SOC_FULL_ICACHE=y CONFIG_SOC_FULL_ICACHE=y
CONFIG_SOC_IRAM_SIZE=0x8000 CONFIG_SOC_IRAM_SIZE=0x8000
CONFIG_CONSOLE_UART_DEFAULT=y # CONFIG_CONSOLE_UART_DEFAULT is not set
# CONFIG_CONSOLE_UART_CUSTOM is not set CONFIG_CONSOLE_UART_CUSTOM=y
# CONFIG_CONSOLE_UART_NONE is not set # 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_CONSOLE_UART_BAUDRATE=74880
# CONFIG_UART0_SWAP_IO is not set # CONFIG_UART0_SWAP_IO is not set
# CONFIG_DISABLE_ROM_UART_PRINT is not set # CONFIG_DISABLE_ROM_UART_PRINT is not set