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/
build/
tmp/
tmp/
.history/

View File

@ -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 <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.
#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 <b>Capabilities</b>.
#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();
}
///@}

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_Baudrate (uint32_t baudrate);
extern uint32_t UART_SWO_Control (uint32_t active);
extern void UART_SWO_Capture (uint8_t *buf, uint32_t num);
extern uint32_t UART_SWO_GetCount (void);
// extern void UART_SWO_Capture (uint8_t *buf, uint32_t num);
// extern uint32_t UART_SWO_GetCount (void);
extern uint32_t Manchester_SWO_Mode (uint32_t enable);
extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate);

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
}

View File

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

View File

@ -1,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 <stdint.h>
#include <string.h>
#include "usbip_server.h"
#include "DAP_handle.h"
#include "DAP.h"
#include "esp_libc.h"
#include "USBd_config.h"
#include "swo.h"
#include "dap_configuration.h"
#include "freertos/FreeRTOS.h"
@ -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;

View File

@ -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...
}

View File

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

View File

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

View File

@ -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