From 1070f630748dd5c6938854e713ebeaf34e6d85fe Mon Sep 17 00:00:00 2001 From: windowsair Date: Tue, 28 Jan 2020 20:21:18 +0800 Subject: [PATCH] feat: DAP function completion 1. Add streaming SWO trace support(Not tested) 2. Fix Unlink function --- components/DAP/CMakeLists.txt | 6 +- components/DAP/config/DAP_config.h | 2 +- components/DAP/include/uart_modify.h | 565 ++++++++++++ components/DAP/source/SWO.c | 790 +++++++++------- components/DAP/source/uart_modify.c | 1256 ++++++++++++++++++++++++++ main/DAP_handle.c | 72 +- main/DAP_handle.h | 1 + main/main.c | 12 +- main/usbip_server.c | 47 +- 9 files changed, 2398 insertions(+), 353 deletions(-) create mode 100644 components/DAP/include/uart_modify.h create mode 100644 components/DAP/source/uart_modify.c diff --git a/components/DAP/CMakeLists.txt b/components/DAP/CMakeLists.txt index 59f8ce1..3eec5a2 100644 --- a/components/DAP/CMakeLists.txt +++ b/components/DAP/CMakeLists.txt @@ -1,5 +1,5 @@ -set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp8266/include/esp8266/") -set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ") -# ./source/SWO.c +set(COMPONENT_ADD_INCLUDEDIRS "config include $ENV{IDF_PATH}/components/esp8266/include/esp8266/ $ENV{IDF_PATH}//components/esp_ringbuf/include/") +set(COMPONENT_SRCS "./source/DAP.c ./source/DAP_vendor.c ./source/JTAG_DP.c ./source/SW_DP.c ./source/SWO.c ./source/uart_modify.c") + register_component() \ No newline at end of file diff --git a/components/DAP/config/DAP_config.h b/components/DAP/config/DAP_config.h index a4ed661..fccf7d3 100644 --- a/components/DAP/config/DAP_config.h +++ b/components/DAP/config/DAP_config.h @@ -113,7 +113,7 @@ This information includes: #define SWO_UART 1 ///< SWO UART: 1 = available, 0 = not available. /// Maximum SWO UART Baudrate. -#define SWO_UART_MAX_BAUDRATE 50000000U ///< SWO UART Maximum Baudrate in Hz. +#define SWO_UART_MAX_BAUDRATE (115200U*40U) ///< SWO UART Maximum Baudrate in Hz. // <<<<<<<<<<<<<<<<<<<<<<<<<<<<< 5MHz //// TODO: uncertain value diff --git a/components/DAP/include/uart_modify.h b/components/DAP/include/uart_modify.h new file mode 100644 index 0000000..3d3a277 --- /dev/null +++ b/components/DAP/include/uart_modify.h @@ -0,0 +1,565 @@ +/** + * @brief Made some simple modifications to the official UART + * + */ + +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _DRIVER_UART_H_ +#define _DRIVER_UART_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_log.h" +#include "freertos/queue.h" + +#define UART_FIFO_LEN (128) /*!< Length of the hardware FIFO buffers */ +#define UART_INTR_MASK 0x1ff /*!< Mask of all UART interrupts */ +#define UART_LINE_INV_MASK (0x3f << 19) /*!< TBD */ + +#define UART_INVERSE_DISABLE (0x0) /*!< Disable UART signal inverse*/ +#define UART_INVERSE_RXD (BIT(19)) /*!< UART RXD input inverse*/ +#define UART_INVERSE_CTS (BIT(20)) /*!< UART CTS input inverse*/ +#define UART_INVERSE_TXD (BIT(22)) /*!< UART TXD output inverse*/ +#define UART_INVERSE_RTS (BIT(23)) /*!< UART RTS output inverse*/ + +/** + * @brief UART mode selection + */ +typedef enum { + UART_MODE_UART = 0x00, /*!< mode: regular UART mode*/ +} uart_mode_t; + +/** + * @brief UART word length constants + */ +typedef enum { + UART_DATA_5_BITS = 0x0, /*!< word length: 5bits*/ + UART_DATA_6_BITS = 0x1, /*!< word length: 6bits*/ + UART_DATA_7_BITS = 0x2, /*!< word length: 7bits*/ + UART_DATA_8_BITS = 0x3, /*!< word length: 8bits*/ + UART_DATA_BITS_MAX = 0x4, +} uart_word_length_t; + +/** + * @brief UART stop bits number + */ +typedef enum { + UART_STOP_BITS_1 = 0x1, /*!< stop bit: 1bit*/ + UART_STOP_BITS_1_5 = 0x2, /*!< stop bit: 1.5bits*/ + UART_STOP_BITS_2 = 0x3, /*!< stop bit: 2bits*/ + UART_STOP_BITS_MAX = 0x4, +} uart_stop_bits_t; + +/** + * @brief UART peripheral number + */ +typedef enum { + UART_NUM_0 = 0x0, + UART_NUM_1 = 0x1, + UART_NUM_MAX, +} uart_port_t; + +/** + * @brief UART parity constants + */ +typedef enum { + UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/ + UART_PARITY_EVEN = 0x2, /*!< Enable UART even parity*/ + UART_PARITY_ODD = 0x3 /*!< Enable UART odd parity*/ +} uart_parity_t; + +/** + * @brief UART hardware flow control modes + */ +typedef enum { + UART_HW_FLOWCTRL_DISABLE = 0x0, /*!< disable hardware flow control*/ + UART_HW_FLOWCTRL_RTS = 0x1, /*!< enable RX hardware flow control (rts)*/ + UART_HW_FLOWCTRL_CTS = 0x2, /*!< enable TX hardware flow control (cts)*/ + UART_HW_FLOWCTRL_CTS_RTS = 0x3, /*!< enable hardware flow control*/ + UART_HW_FLOWCTRL_MAX = 0x4, +} uart_hw_flowcontrol_t; + +/** + * @brief UART configuration parameters for my_uart_param_config function + */ +typedef struct { + int baud_rate; /*!< UART baud rate*/ + uart_word_length_t data_bits; /*!< UART byte size*/ + uart_parity_t parity; /*!< UART parity mode*/ + uart_stop_bits_t stop_bits; /*!< UART stop bits*/ + uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode (cts/rts)*/ + uint8_t rx_flow_ctrl_thresh; /*!< UART HW RTS threshold*/ +} uart_config_t; + +/** + * @brief UART interrupt configuration parameters for my_uart_intr_config function + */ +typedef struct { + uint32_t intr_enable_mask; /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/ + uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold (unit: time of sending one byte)*/ + uint8_t txfifo_empty_intr_thresh; /*!< UART TX empty interrupt threshold.*/ + uint8_t rxfifo_full_thresh; /*!< UART RX full interrupt threshold.*/ +} uart_intr_config_t; + +/** + * @brief UART event types used in the ring buffer + */ +typedef enum { + UART_DATA, /*!< UART data event*/ + UART_BUFFER_FULL, /*!< UART RX buffer full event*/ + UART_FIFO_OVF, /*!< UART FIFO overflow event*/ + UART_FRAME_ERR, /*!< UART RX frame error event*/ + UART_PARITY_ERR, /*!< UART RX parity event*/ + UART_EVENT_MAX, /*!< UART event max index*/ +} uart_event_type_t; + +/** + * @brief Event structure used in UART event queue + */ +typedef struct { + uart_event_type_t type; /*!< UART event type */ + size_t size; /*!< UART data size for UART_DATA event*/ +} uart_event_t; + + +/** + * @brief Set UART data bits. + * + * @param uart_num Uart port number. + * @param data_bit Uart data bits. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit); + +/** + * @brief Get UART data bits. + * + * @param uart_num Uart port number. + * @param data_bit Pointer to accept value of UART data bits. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_word_length(uart_port_t uart_num, uart_word_length_t *data_bit); + +/** + * @brief Set UART stop bits. + * + * @param uart_num Uart port number + * @param stop_bits Uart stop bits + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bits); + +/** + * @brief Get UART stop bits. + * + * @param uart_num Uart port number. + * @param stop_bits Pointer to accept value of UART stop bits. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t *stop_bits); + +/** + * @brief Set UART parity mode. + * + * @param uart_num Uart port number. + * @param parity_mode The enum of uart parity configuration. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode); + +/** + * @brief Get UART parity mode. + * + * @param uart_num Uart port number + * @param parity_mode Pointer to accept value of UART parity mode. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_parity(uart_port_t uart_num, uart_parity_t *parity_mode); + +/** + * @brief Set UART baud rate. + * + * @param uart_num Uart port number + * @param baudrate UART baud rate. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate); + +/** + * @brief Get UART baud rate. + * + * @param uart_num Uart port number. + * @param baudrate Pointer to accept value of Uart baud rate. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_baudrate(uart_port_t uart_num, uint32_t *baudrate); + +/** + * @brief Set UART line inverse mode + * + * @param uart_num UART_NUM_0 + * @param inverse_mask Choose the wires that need to be inverted. + * Inverse_mask should be chosen from + * UART_INVERSE_RXD / UART_INVERSE_TXD / UART_INVERSE_RTS / UART_INVERSE_CTS, + * combined with OR operation. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask); + +/** + * @brief Configure Hardware flow control. + * + * @param uart_num Uart port number. + * @param flow_ctrl Hardware flow control mode. + * @param rx_thresh Threshold of Hardware flow control. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh); + +/** + * @brief Get hardware flow control mode + * + * @param uart_num Uart port number. + * @param flow_ctrl Option for different flow control mode. + * + * @return + * - ESP_OK Success, result will be put in (*flow_ctrl) + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl); + +/** + * @brief UART0 swap. + * Use MTCK as UART0 RX, MTDO as UART0 TX, so ROM log will not output from + * this new UART0. We also need to use MTDO (U0RTS) and MTCK (U0CTS) as UART0 in hardware. + * + * @return + * - ESP_OK Success + */ +esp_err_t my_uart_enable_swap(void); + +/** + * @brief Disable UART0 swap. + * Use the original UART0, not MTCK and MTDO. + * + * @return + * - ESP_OK Success + */ +esp_err_t my_uart_disable_swap(void); + +/** + * @brief Clear uart interrupts status. + * + * @param uart_num Uart port number. + * @param mask Uart interrupt bits mask. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_clear_intr_status(uart_port_t uart_num, uint32_t mask); + +/** + * @brief Set UART interrupt enable + * + * @param uart_num Uart port number + * @param enable_mask Bit mask of the enable bits. + * The bit mask should be composed from the fields of register UART_INT_ENA_REG. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); + +/** + * @brief Clear UART interrupt enable bits + * + * @param uart_num Uart port number + * @param disable_mask Bit mask of the disable bits. + * The bit mask should be composed from the fields of register UART_INT_ENA_REG. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); + +/** + * @brief Enable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_enable_rx_intr(uart_port_t uart_num); + +/** + * @brief Disable UART RX interrupt (RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_disable_rx_intr(uart_port_t uart_num); + +/** + * @brief Disable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_disable_tx_intr(uart_port_t uart_num); + +/** + * @brief Enable UART TX interrupt (TX_FULL & TX_TIMEOUT INTERRUPT) + * + * @param uart_num UART_NUM_0 + * @param enable 1: enable; 0: disable + * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); + +/** + * @brief Register UART interrupt handler (ISR). + * + * @param uart_num UART_NUM_0 + * @param fn Interrupt handler function. + * @param arg parameter for handler function + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_isr_register(uart_port_t uart_num, void (*fn)(void *), void *arg); + +/** + * @brief Config Common parameters of serial ports. + * + * @param uart_num Uart port number. + * @param uart_conf Uart config parameters. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_param_config(uart_port_t uart_num, uart_config_t *uart_conf); + +/** + * @brief Config types of uarts. + * + * @param uart_num Uart port number. + * @param uart_intr_conf Uart interrupt config parameters. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_intr_config(uart_port_t uart_num, uart_intr_config_t *uart_intr_conf); + +/** + * @brief Install UART driver. + * + * @note Rx_buffer_size should be greater than UART_FIFO_LEN. Tx_buffer_size should be either zero or greater than UART_FIFO_LEN. + * + * @param uart_num Uart port number. + * @param rx_buffer_size UART RX ring buffer size. + * @param tx_buffer_size UART TX ring buffer size. + * If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out. + * @param queue_size UART event queue size/depth. + * @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 + */ +esp_err_t my_uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int no_use); + +/** + * @brief Uninstall UART driver. + * + * @param uart_num Uart port number. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_driver_delete(uart_port_t uart_num); + +/** + * @brief Waiting for the last byte of data to be sent + * + * @param uart_num Uart port number. + * @param ticks_to_wait Timeout, count in RTOS ticks + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); + +/** + * @brief Send data to the UART port from a given buffer and length. + * + * This function will not wait for enough space in TX FIFO. It will just fill the available TX FIFO and return when the FIFO is full. + * @note This function should only be used when UART TX buffer is not enabled. + * + * @param uart_num Uart port number. + * @param buffer data buffer address + * @param len data length to send + * + * @return + * - (-1) Parameter error + * - OTHERS (>=0) The number of bytes pushed to the TX FIFO + */ +int my_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len); + +/** + * @brief Send data to the UART port from a given buffer and length, + * + * If the UART driver's parameter 'tx_buffer_size' is set to zero: + * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. + * + * Otherwise, if the 'tx_buffer_size' > 0, this function will return after copying all the data to tx ring buffer, + * UART ISR will then move data from the ring buffer to TX FIFO gradually. + * + * @param uart_num Uart port number. + * @param src data buffer address + * @param size data length to send + * + * @return + * - (-1) Parameter error + * - OTHERS (>=0) The number of bytes pushed to the TX FIFO + */ +int my_uart_write_bytes(uart_port_t uart_num, const char *src, size_t size); + +/** + * @brief UART read bytes from UART buffer + * + * @param uart_num Uart port number. + * @param buf pointer to the buffer. + * @param length data length + * @param ticks_to_wait sTimeout, count in RTOS ticks + * + * @return + * - (-1) Error + * - OTHERS (>=0) The number of bytes read from UART FIFO + */ +int my_uart_read_bytes(uart_port_t uart_num, uint8_t *buf, uint32_t length, TickType_t ticks_to_wait); + +/** + * @brief Alias of my_uart_flush_input. + * UART ring buffer flush. This will discard all data in the UART RX buffer. + * @note Instead of waiting the data sent out, this function will clear UART rx buffer. + * In order to send all the data in tx FIFO, we can use my_uart_wait_tx_done function. + * @param uart_num UART port number. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_flush(uart_port_t uart_num); + +/** + * @brief Clear input buffer, discard all the data is in the ring-buffer. + * @note In order to send all the data in tx FIFO, we can use my_uart_wait_tx_done function. + * @param uart_num UART port number. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_flush_input(uart_port_t uart_num); + +/** + * @brief UART get RX ring buffer cached data length + * + * @param uart_num UART port number. + * @param size Pointer of size_t to accept cached data length + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_get_buffered_data_len(uart_port_t uart_num, size_t *size); + +/** + * @brief UART set threshold timeout for TOUT feature + * + * @param uart_num Uart number to configure + * @param tout_thresh This parameter defines timeout threshold in uart symbol periods. The maximum value of threshold is 126. + * tout_thresh = 1, defines TOUT interrupt timeout equal to transmission time of one symbol (~11 bit) on current baudrate. + * If the time is expired the UART_RXFIFO_TOUT_INT interrupt is triggered. If tout_thresh == 0, + * the TOUT feature is disabled. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t my_uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh); + +#ifdef __cplusplus +} +#endif + +#endif // _DRIVER_UART_H_ diff --git a/components/DAP/source/SWO.c b/components/DAP/source/SWO.c index 241d9cb..d331a0c 100644 --- a/components/DAP/source/SWO.c +++ b/components/DAP/source/SWO.c @@ -1,3 +1,8 @@ +/** + * @brief Modify this file to fit esp8266 Uart + * + */ + /* * Copyright (c) 2013-2017 ARM Limited. All rights reserved. * @@ -27,14 +32,21 @@ #include "DAP_config.h" #include "DAP.h" -/* -#if (SWO_UART != 0) -#include "Driver_USART.h" -#endif -#if (SWO_STREAM != 0) -#include "cmsis_os2.h" -#endif -*/ + +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/event_groups.h" +#include "uart_modify.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 + #if (SWO_STREAM != 0) #ifdef DAP_FW_V1 @@ -44,28 +56,22 @@ #if (SWO_UART != 0) -#ifndef USART_PORT -#define USART_PORT 0 /* USART Port Number */ +#ifndef USART_PORT +#define USART_PORT UART_NUM_0 /* USART Port Number */ #endif -// USART Driver -#define _USART_Driver_(n) Driver_USART##n -#define USART_Driver_(n) _USART_Driver_(n) -extern ARM_DRIVER_USART USART_Driver_(USART_PORT); -#define pUSART (&USART_Driver_(USART_PORT)) + static uint8_t USART_Ready = 0U; -#endif /* (SWO_UART != 0) */ - +#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 50U /* Stream timeout in ms */ - -#define USB_BLOCK_SIZE 512U /* USB Block Size */ -#define TRACE_BLOCK_SIZE 64U /* Trace Block Size (2^n: 32...512) */ +#define USB_BLOCK_SIZE 512U /* USB Block Size */ +#define TRACE_BLOCK_SIZE 64U /* Trace Block Size (2^n: 32...512) */ // Trace State static uint8_t TraceTransport = 0U; /* Trace Transport */ @@ -81,145 +87,190 @@ static volatile uint32_t TraceIndexO = 0U; /* Outgoing Trace Index */ static volatile uint8_t TraceUpdate; /* Trace Update Flag */ static uint32_t TraceBlockSize; /* Current Trace Block Size */ -#if (TIMESTAMP_CLOCK != 0U) +#if (TIMESTAMP_CLOCK != 0U) // Trace Timestamp -static volatile struct { +static volatile struct +{ uint32_t index; uint32_t tick; } TraceTimestamp; #endif // Trace Helper functions -static void ClearTrace (void); -static void ResumeTrace (void); -static uint32_t GetTraceCount (void); -static uint8_t GetTraceStatus (void); -static void SetTraceError (uint8_t flag); +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) -extern osThreadId_t SWO_ThreadId; -static volatile uint8_t TransferBusy = 0U; /* Transfer Busy Flag */ -static uint32_t TransferSize; /* Current Transfer Size */ -#endif +static volatile uint8_t TransferBusy = 0U; /* Transfer Busy Flag */ +static uint32_t TransferSize; /* Current Transfer Size */ +#endif #if (SWO_UART != 0) -// USART Driver Callback function -// event: event mask -static void USART_Callback (uint32_t event) { + +void usart_monitor_task(void *argument) +{ uint32_t index_i; uint32_t index_o; uint32_t count; uint32_t num; + uint32_t flags; - if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) { -#if (TIMESTAMP_CLOCK != 0U) - TraceTimestamp.tick = TIMESTAMP_GET(); + 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; + 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)); - count = index_i - index_o; - if (count <= (SWO_BUFFER_SIZE - num)) { - index_i &= SWO_BUFFER_SIZE - 1U; - TraceBlockSize = num; - pUSART->Receive(&TraceBuf[index_i], num); - } else { - 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)))) { - osThreadFlagsSet(SWO_ThreadId, 1U); + + 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); - } + + // 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) { +__WEAK uint32_t UART_SWO_Mode(uint32_t enable) +{ int32_t status; USART_Ready = 0U; + uart_config_t uart_config = { + .baud_rate = 115200, + .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); - if (enable != 0U) { - status = pUSART->Initialize(USART_Callback); - if (status != ARM_DRIVER_OK) { +#define BUF_SIZE (1024) + my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0); + + if (enable != 0U) + { + my_uart_param_config(USART_PORT, &uart_config); + status = my_uart_driver_install(USART_PORT, BUF_SIZE, 0, 0, NULL, 0); + if (status != ESP_OK) + { return (0U); } - status = pUSART->PowerControl(ARM_POWER_FULL); - if (status != ARM_DRIVER_OK) { - pUSART->Uninitialize(); - return (0U); - } - } else { - pUSART->Control(ARM_USART_CONTROL_RX, 0U); - pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); - pUSART->PowerControl(ARM_POWER_OFF); - pUSART->Uninitialize(); + } + else + { + my_uart_driver_delete(USART_PORT); } return (1U); + + } // Configure UART SWO Baudrate // baudrate: requested baudrate // return: actual baudrate or 0 when not configured -__WEAK uint32_t UART_SWO_Baudrate (uint32_t baudrate) { - int32_t status; +__WEAK uint32_t UART_SWO_Baudrate(uint32_t baudrate) +{ + int32_t status; uint32_t index; uint32_t num; - if (baudrate > SWO_UART_MAX_BAUDRATE) { + if (baudrate > SWO_UART_MAX_BAUDRATE) + { baudrate = SWO_UART_MAX_BAUDRATE; } - if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { - pUSART->Control(ARM_USART_CONTROL_RX, 0U); - if (pUSART->GetStatus().rx_busy) { - TraceIndexI += pUSART->GetRxCount(); - pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); - } + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) + { + size_t len = 0; + my_uart_get_buffered_data_len(USART_PORT, &len); + my_uart_flush(USART_PORT); + TraceIndexI += len; + // pUSART->Control(ARM_USART_CONTROL_RX, 0U); + // if (pUSART->GetStatus().rx_busy) + // { + // TraceIndexI += pUSART->GetRxCount(); + // pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); + // } } - status = pUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | - ARM_USART_DATA_BITS_8 | - ARM_USART_PARITY_NONE | - ARM_USART_STOP_BITS_1, - baudrate); + ///////////// + status = my_uart_set_baudrate(USART_PORT, baudrate); - if (status == ARM_DRIVER_OK) { + if (status == ESP_OK) + { USART_Ready = 1U; - } else { + } + else + { USART_Ready = 0U; return (0U); } - - if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { - if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 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); + //pUSART->Receive(&TraceBuf[index], num); + my_uart_read_bytes(USART_PORT, &TraceBuf[index], num, 20 / portTICK_RATE_MS); } - pUSART->Control(ARM_USART_CONTROL_RX, 1U); + //pUSART->Control(ARM_USART_CONTROL_RX, 1U); ////TODO: } return (baudrate); @@ -228,28 +279,40 @@ __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) { +__WEAK uint32_t UART_SWO_Control(uint32_t active) +{ int32_t status; - if (active) { - if (!USART_Ready) { + if (active) + { + if (!USART_Ready) + { return (0U); } TraceBlockSize = 1U; - status = pUSART->Receive(&TraceBuf[0], 1U); - if (status != ARM_DRIVER_OK) { + status = my_uart_read_bytes(USART_PORT, &TraceBuf[0], 1U, 20 / portTICK_RATE_MS); + if (status == ESP_FAIL) + { return (0U); } - status = pUSART->Control(ARM_USART_CONTROL_RX, 1U); - if (status != ARM_DRIVER_OK) { - return (0U); - } - } else { - pUSART->Control(ARM_USART_CONTROL_RX, 0U); - if (pUSART->GetStatus().rx_busy) { - TraceIndexI += pUSART->GetRxCount(); - pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); - } + // status = pUSART->Control(ARM_USART_CONTROL_RX, 1U); + // if (status != ARM_DRIVER_OK) + // { + // return (0U); + // } ////TODO: + } + else + { + size_t len = 0; + my_uart_get_buffered_data_len(USART_PORT, &len); + my_uart_flush(USART_PORT); + TraceIndexI += len; + // pUSART->Control(ARM_USART_CONTROL_RX, 0U); + // if (pUSART->GetStatus().rx_busy) + // { + // TraceIndexI += pUSART->GetRxCount(); + // pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U); + // } } return (1U); } @@ -257,70 +320,83 @@ __WEAK uint32_t UART_SWO_Control (uint32_t active) { // Start UART SWO Capture // buf: pointer to buffer for capturing // num: number of bytes to capture -__WEAK void UART_SWO_Capture (uint8_t *buf, uint32_t num) { +__WEAK void UART_SWO_Capture(uint8_t *buf, uint32_t num) +{ TraceBlockSize = num; - pUSART->Receive(buf, num); + my_uart_read_bytes(USART_PORT, buf, num, 20 / portTICK_RATE_MS); } // Get UART SWO Pending Trace Count // return: number of pending trace data bytes -__WEAK uint32_t UART_SWO_GetCount (void) { +__WEAK uint32_t UART_SWO_GetCount(void) +{ uint32_t count; - if (pUSART->GetStatus().rx_busy) { - count = pUSART->GetRxCount(); - } else { - count = 0U; - } + // if (pUSART->GetStatus().rx_busy) + // { + // count = pUSART->GetRxCount(); + // } + // else + // { + // count = 0U; + // } + my_uart_get_buffered_data_len(USART_PORT, &count); 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) { +__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) { +__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) { +__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) { +__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) { +__WEAK uint32_t Manchester_SWO_GetCount(void) +{ + return (0U); } -#endif /* (SWO_MANCHESTER != 0) */ - +#endif /* (SWO_MANCHESTER != 0) */ // Clear Trace Errors and Data -static void ClearTrace (void) { +static void ClearTrace(void) +{ #if (SWO_STREAM != 0) - if (TraceTransport == 2U) { - if (TransferBusy != 0U) { + if (TraceTransport == 2U) + { + if (TransferBusy != 0U) + { SWO_AbortTransfer(); TransferBusy = 0U; } @@ -329,41 +405,45 @@ static void ClearTrace (void) { TraceError[0] = 0U; TraceError[1] = 0U; - TraceError_n = 0U; - TraceIndexI = 0U; - TraceIndexO = 0U; + TraceError_n = 0U; + TraceIndexI = 0U; + TraceIndexO = 0U; -#if (TIMESTAMP_CLOCK != 0U) +#if (TIMESTAMP_CLOCK != 0U) TraceTimestamp.index = 0U; - TraceTimestamp.tick = 0U; + TraceTimestamp.tick = 0U; #endif } // Resume Trace Capture -static void ResumeTrace (void) { +static void ResumeTrace(void) +{ uint32_t index_i; uint32_t index_o; - if (TraceStatus == (DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED)) { + if (TraceStatus == (DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED)) + { index_i = TraceIndexI; index_o = TraceIndexO; - if ((index_i - index_o) < SWO_BUFFER_SIZE) { + if ((index_i - index_o) < SWO_BUFFER_SIZE) + { index_i &= SWO_BUFFER_SIZE - 1U; - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - TraceStatus = DAP_SWO_CAPTURE_ACTIVE; - UART_SWO_Capture(&TraceBuf[index_i], 1U); - break; + case DAP_SWO_UART: + TraceStatus = DAP_SWO_CAPTURE_ACTIVE; + UART_SWO_Capture(&TraceBuf[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; + case DAP_SWO_MANCHESTER: + TraceStatus = DAP_SWO_CAPTURE_ACTIVE; + Manchester_SWO_Capture(&TraceBuf[index_i], 1U); + break; #endif - default: - break; + default: + break; } } } @@ -371,29 +451,35 @@ static void ResumeTrace (void) { // Get Trace Count // return: number of available data bytes in trace buffer -static uint32_t GetTraceCount (void) { +static uint32_t GetTraceCount(void) +{ uint32_t count; - if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) { - do { + if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) + { + do + { TraceUpdate = 0U; count = TraceIndexI - TraceIndexO; - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - count += UART_SWO_GetCount(); - break; + case DAP_SWO_UART: + count += UART_SWO_GetCount(); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - count += Manchester_SWO_GetCount(); - break; + case DAP_SWO_MANCHESTER: + count += Manchester_SWO_GetCount(); + break; #endif - default: - break; + default: + break; } } while (TraceUpdate != 0U); - } else { + } + else + { count = TraceIndexI - TraceIndexO; } @@ -402,8 +488,9 @@ static uint32_t GetTraceCount (void) { // Get Trace Status (clear Error flags) // return: Trace Status (Active flag and Error flags) -static uint8_t GetTraceStatus (void) { - uint8_t status; +static uint8_t GetTraceStatus(void) +{ + uint8_t status; uint32_t n; n = TraceError_n; @@ -416,235 +503,263 @@ static uint8_t GetTraceStatus (void) { // Set Trace Error flag(s) // flag: error flag(s) to set -static void SetTraceError (uint8_t flag) { +void SetTraceError(uint8_t flag) +{ TraceError[TraceError_n] |= flag; } - // Process SWO Transport command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Transport (const uint8_t *request, uint8_t *response) { - uint8_t transport; +uint32_t SWO_Transport(const uint8_t *request, uint8_t *response) +{ + uint8_t transport; uint32_t result; - if ((TraceStatus & DAP_SWO_CAPTURE_ACTIVE) == 0U) { + if ((TraceStatus & DAP_SWO_CAPTURE_ACTIVE) == 0U) + { transport = *request; - switch (transport) { - case 0U: - case 1U: + switch (transport) + { + case 0U: + case 1U: #if (SWO_STREAM != 0) - case 2U: + case 2U: #endif - TraceTransport = transport; - result = 1U; - break; - default: - result = 0U; - break; + TraceTransport = transport; + result = 1U; + break; + default: + result = 0U; + break; } - } else { + } + else + { result = 0U; } - if (result != 0U) { + if (result != 0U) + { *response = DAP_OK; - } else { + } + else + { *response = DAP_ERROR; } return ((1U << 16) | 1U); } - // Process SWO Mode command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Mode (const uint8_t *request, uint8_t *response) { - uint8_t mode; +uint32_t SWO_Mode(const uint8_t *request, uint8_t *response) +{ + uint8_t mode; uint32_t result; mode = *request; - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - UART_SWO_Mode(0U); - break; + case DAP_SWO_UART: + UART_SWO_Mode(0U); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - Manchester_SWO_Mode(0U); - break; + case DAP_SWO_MANCHESTER: + Manchester_SWO_Mode(0U); + break; #endif - default: - break; + default: + break; } - switch (mode) { - case DAP_SWO_OFF: - result = 1U; - break; + switch (mode) + { + case DAP_SWO_OFF: + result = 1U; + break; #if (SWO_UART != 0) - case DAP_SWO_UART: - result = UART_SWO_Mode(1U); - break; + case DAP_SWO_UART: + result = UART_SWO_Mode(1U); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - result = Manchester_SWO_Mode(1U); - break; + case DAP_SWO_MANCHESTER: + result = Manchester_SWO_Mode(1U); + break; #endif - default: - result = 0U; - break; + default: + result = 0U; + break; } - if (result != 0U) { + if (result != 0U) + { TraceMode = mode; - } else { + } + else + { TraceMode = DAP_SWO_OFF; } TraceStatus = 0U; - if (result != 0U) { + if (result != 0U) + { *response = DAP_OK; - } else { + } + else + { *response = DAP_ERROR; } return ((1U << 16) | 1U); } - // Process SWO Baudrate command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response) { +uint32_t SWO_Baudrate(const uint8_t *request, uint8_t *response) +{ uint32_t baudrate; - baudrate = (uint32_t)(*(request+0) << 0) | - (uint32_t)(*(request+1) << 8) | - (uint32_t)(*(request+2) << 16) | - (uint32_t)(*(request+3) << 24); + baudrate = (uint32_t)(*(request + 0) << 0) | + (uint32_t)(*(request + 1) << 8) | + (uint32_t)(*(request + 2) << 16) | + (uint32_t)(*(request + 3) << 24); - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - baudrate = UART_SWO_Baudrate(baudrate); - break; + case DAP_SWO_UART: + baudrate = UART_SWO_Baudrate(baudrate); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - baudrate = Manchester_SWO_Baudrate(baudrate); - break; + case DAP_SWO_MANCHESTER: + baudrate = Manchester_SWO_Baudrate(baudrate); + break; #endif - default: - baudrate = 0U; - break; + default: + baudrate = 0U; + break; } - if (baudrate == 0U) { + if (baudrate == 0U) + { TraceStatus = 0U; } - *response++ = (uint8_t)(baudrate >> 0); - *response++ = (uint8_t)(baudrate >> 8); + *response++ = (uint8_t)(baudrate >> 0); + *response++ = (uint8_t)(baudrate >> 8); *response++ = (uint8_t)(baudrate >> 16); - *response = (uint8_t)(baudrate >> 24); + *response = (uint8_t)(baudrate >> 24); return ((4U << 16) | 4U); } - // Process SWO Control command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Control (const uint8_t *request, uint8_t *response) { - uint8_t active; +uint32_t SWO_Control(const uint8_t *request, uint8_t *response) +{ + uint8_t active; uint32_t result; active = *request & DAP_SWO_CAPTURE_ACTIVE; - if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) { - if (active) { + if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) + { + if (active) + { ClearTrace(); } - switch (TraceMode) { + switch (TraceMode) + { #if (SWO_UART != 0) - case DAP_SWO_UART: - result = UART_SWO_Control(active); - break; + case DAP_SWO_UART: + result = UART_SWO_Control(active); + break; #endif #if (SWO_MANCHESTER != 0) - case DAP_SWO_MANCHESTER: - result = Manchester_SWO_Control(active); - break; + case DAP_SWO_MANCHESTER: + result = Manchester_SWO_Control(active); + break; #endif - default: - result = 0U; - break; + default: + result = 0U; + break; } - if (result != 0U) { + if (result != 0U) + { TraceStatus = active; #if (SWO_STREAM != 0) - if (TraceTransport == 2U) { - osThreadFlagsSet(SWO_ThreadId, 1U); + if (TraceTransport == 2U) + { + xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA); } #endif } - } else { + } + else + { result = 1U; } - if (result != 0U) { + if (result != 0U) + { *response = DAP_OK; - } else { + } + else + { *response = DAP_ERROR; } return ((1U << 16) | 1U); } - // Process SWO Status command and prepare response // response: pointer to response data // return: number of bytes in response -uint32_t SWO_Status (uint8_t *response) { - uint8_t status; +uint32_t SWO_Status(uint8_t *response) +{ + uint8_t status; uint32_t count; status = GetTraceStatus(); - count = GetTraceCount(); + count = GetTraceCount(); *response++ = status; - *response++ = (uint8_t)(count >> 0); - *response++ = (uint8_t)(count >> 8); + *response++ = (uint8_t)(count >> 0); + *response++ = (uint8_t)(count >> 8); *response++ = (uint8_t)(count >> 16); - *response = (uint8_t)(count >> 24); + *response = (uint8_t)(count >> 24); return (5U); } - // Process SWO Extended Status command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response) { - uint8_t cmd; - uint8_t status; +uint32_t SWO_ExtendedStatus(const uint8_t *request, uint8_t *response) +{ + uint8_t cmd; + uint8_t status; uint32_t count; -#if (TIMESTAMP_CLOCK != 0U) +#if (TIMESTAMP_CLOCK != 0U) uint32_t index; uint32_t tick; #endif @@ -653,36 +768,40 @@ uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response) { num = 0U; cmd = *request; - if (cmd & 0x01U) { + if (cmd & 0x01U) + { status = GetTraceStatus(); *response++ = status; num += 1U; } - if (cmd & 0x02U) { + if (cmd & 0x02U) + { count = GetTraceCount(); - *response++ = (uint8_t)(count >> 0); - *response++ = (uint8_t)(count >> 8); + *response++ = (uint8_t)(count >> 0); + *response++ = (uint8_t)(count >> 8); *response++ = (uint8_t)(count >> 16); *response++ = (uint8_t)(count >> 24); num += 4U; } -#if (TIMESTAMP_CLOCK != 0U) - if (cmd & 0x04U) { - do { +#if (TIMESTAMP_CLOCK != 0U) + if (cmd & 0x04U) + { + do + { TraceUpdate = 0U; index = TraceTimestamp.index; - tick = TraceTimestamp.tick; + tick = TraceTimestamp.tick; } while (TraceUpdate != 0U); - *response++ = (uint8_t)(index >> 0); - *response++ = (uint8_t)(index >> 8); + *response++ = (uint8_t)(index >> 0); + *response++ = (uint8_t)(index >> 8); *response++ = (uint8_t)(index >> 16); *response++ = (uint8_t)(index >> 24); - *response++ = (uint8_t)(tick >> 0); - *response++ = (uint8_t)(tick >> 8); - *response++ = (uint8_t)(tick >> 16); - *response++ = (uint8_t)(tick >> 24); + *response++ = (uint8_t)(tick >> 0); + *response++ = (uint8_t)(tick >> 8); + *response++ = (uint8_t)(tick >> 16); + *response++ = (uint8_t)(tick >> 24); num += 4U; } #endif @@ -690,31 +809,36 @@ uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response) { return ((1U << 16) | num); } - // Process SWO Data command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response (lower 16 bits) // number of bytes in request (upper 16 bits) -uint32_t SWO_Data (const uint8_t *request, uint8_t *response) { - uint8_t status; +uint32_t SWO_Data(const uint8_t *request, uint8_t *response) +{ + uint8_t status; uint32_t count; uint32_t index; uint32_t n, i; status = GetTraceStatus(); - count = GetTraceCount(); + count = GetTraceCount(); - if (TraceTransport == 1U) { - n = (uint32_t)(*(request+0) << 0) | - (uint32_t)(*(request+1) << 8); - if (n > (DAP_PACKET_SIZE - 4U)) { + if (TraceTransport == 1U) + { + n = (uint32_t)(*(request + 0) << 0) | + (uint32_t)(*(request + 1) << 8); + if (n > (DAP_PACKET_SIZE - 4U)) + { n = DAP_PACKET_SIZE - 4U; } - if (count > n) { + if (count > n) + { count = n; } - } else { + } + else + { count = 0U; } @@ -722,9 +846,11 @@ uint32_t SWO_Data (const uint8_t *request, uint8_t *response) { *response++ = (uint8_t)(count >> 0); *response++ = (uint8_t)(count >> 8); - if (TraceTransport == 1U) { + if (TraceTransport == 1U) + { index = TraceIndexO; - for (i = index, n = count; n; n--) { + for (i = index, n = count; n; n--) + { i &= SWO_BUFFER_SIZE - 1U; *response++ = TraceBuf[i++]; } @@ -735,68 +861,86 @@ uint32_t SWO_Data (const uint8_t *request, uint8_t *response) { return ((2U << 16) | (3U + count)); } - #if (SWO_STREAM != 0) // SWO Data Transfer complete callback -void SWO_TransferComplete (void) { +void SWO_TransferComplete(void) +{ TraceIndexO += TransferSize; TransferBusy = 0U; ResumeTrace(); - osThreadFlagsSet(SWO_ThreadId, 1U); + xEventGroupSetBits(kSWO_Thread_event_group, SWO_GOT_DATA); } // SWO Thread -__NO_RETURN void SWO_Thread (void *argument) { +void SWO_Thread(void *argument) +{ uint32_t timeout; uint32_t flags; uint32_t count; uint32_t index; uint32_t i, n; - (void) argument; + (void)argument; - timeout = osWaitForever; - - for (;;) { - flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout); - if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) { + timeout = portMAX_DELAY; + + kSWO_Thread_event_group = xEventGroupCreate(); + for (;;) + { + flags = xEventGroupWaitBits(kSWO_Thread_event_group, SWO_GOT_DATA | SWO_ERROR_TIME_OUT, + pdTRUE, pdFALSE, timeout); + if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) + { timeout = SWO_STREAM_TIMEOUT; - } else { - timeout = osWaitForever; - flags = osFlagsErrorTimeout; } - if (TransferBusy == 0U) { + else + { + timeout = portMAX_DELAY; + flags = SWO_ERROR_TIME_OUT; + } + if (TransferBusy == 0U) + { count = GetTraceCount(); - if (count != 0U) { + if (count != 0U) + { index = TraceIndexO & (SWO_BUFFER_SIZE - 1U); n = SWO_BUFFER_SIZE - index; - if (count > n) { + if (count > n) + { count = n; } - if (flags != osFlagsErrorTimeout) { + if ((flags & SWO_ERROR_TIME_OUT) == 0) + { i = index & (USB_BLOCK_SIZE - 1U); - if (i == 0U) { + if (i == 0U) + { count &= ~(USB_BLOCK_SIZE - 1U); - } else { + // Take down to the nearest number that is a multiple of USB_BLOCK_SIZE + } + else + { n = USB_BLOCK_SIZE - i; - if (count >= n) { + if (count >= n) + { count = n; - } else { + } + else + { count = 0U; } } } - if (count != 0U) { + if (count != 0U) + { TransferSize = count; TransferBusy = 1U; - SWO_QueueTransfer(&TraceBuf[index], count); + SWO_QueueTransfer(&TraceBuf[index], count); //through USB } } } } } -#endif /* (SWO_STREAM != 0) */ +#endif /* (SWO_STREAM != 0) */ - -#endif /* ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) */ +#endif /* ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) */ diff --git a/components/DAP/source/uart_modify.c b/components/DAP/source/uart_modify.c new file mode 100644 index 0000000..e485482 --- /dev/null +++ b/components/DAP/source/uart_modify.c @@ -0,0 +1,1256 @@ +/** + * @brief Made some simple modifications to the official UART + * + */ + +// Copyright 2018-2025 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/ringbuf.h" +#include "freertos/event_groups.h" + +#include "esp_err.h" +#include "esp_log.h" +#include "esp_attr.h" + +// SWO modify +#include "DAP_config.h" +#include "esp8266/uart_struct.h" +#include "esp8266/uart_register.h" +#include "esp8266/pin_mux_register.h" +#include "esp8266/eagle_soc.h" +#include "esp8266/rom_functions.h" + +#include "rom/ets_sys.h" + +#include "uart_modify.h" +#include "driver/uart_select.h" + +#define portYIELD_FROM_ISR() taskYIELD() + +#define UART_ENTER_CRITICAL() portENTER_CRITICAL() +#define UART_EXIT_CRITICAL() portEXIT_CRITICAL() + +static const char *UART_TAG = "uart"; +#define UART_CHECK(a, str, ret_val) \ + if (!(a)) \ + { \ + ESP_LOGE(UART_TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \ + return (ret_val); \ + } + +#define UART_EMPTY_THRESH_DEFAULT (10) +#define UART_FULL_THRESH_DEFAULT (120) +#define UART_TOUT_THRESH_DEFAULT (10) + +typedef struct +{ + uart_event_type_t type; /*!< UART TX data type */ + struct + { + size_t size; + uint8_t data[0]; + } tx_data; +} uart_tx_data_t; + +typedef struct +{ + uart_port_t uart_num; /*!< UART port number*/ + int queue_size; /*!< UART event queue size*/ + QueueHandle_t xQueueUart; /*!< UART queue handler*/ + uart_mode_t uart_mode; /*!< UART controller actual mode set by uart_set_mode() */ + + // rx parameters + int rx_buffered_len; /*!< UART cached data length */ + SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/ + int rx_buf_size; /*!< RX ring buffer size */ + RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler*/ + bool rx_buffer_full_flg; /*!< RX ring buffer full flag. */ + int rx_cur_remain; /*!< Data number that waiting to be read out in ring buffer item*/ + uint8_t *rx_ptr; /*!< pointer to the current data in ring buffer*/ + uint8_t *rx_head_ptr; /*!< pointer to the head of RX item*/ + uint8_t rx_data_buf[UART_FIFO_LEN]; /*!< Data buffer to stash FIFO data*/ + uint8_t rx_stash_len; /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */ + + // tx parameters + SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ + SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ + SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ + int tx_buf_size; /*!< TX ring buffer size */ + RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ + bool tx_waiting_fifo; /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/ + uint8_t *tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ + uart_tx_data_t *tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ + uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ + uint32_t tx_len_cur; + bool wait_tx_done_flg; + uart_select_notif_callback_t uart_select_notif_callback; /*!< Notification about select() events */ +} uart_obj_t; + +static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; +// DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR +static DRAM_ATTR uart_dev_t *const UART[UART_NUM_MAX] = {&uart0, &uart1}; + +typedef void (*uart_isr_t)(void *); +typedef struct +{ + uart_isr_t fn; /*!< isr function */ + void *args; /*!< isr function args */ +} uart_isr_func_t; + +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) +// + +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(); + UART[uart_num]->conf0.bit_num = data_bit; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +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; + return ESP_OK; +} + +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(); + UART[uart_num]->conf0.stop_bit_num = stop_bit; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +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; + return ESP_OK; +} + +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); + + UART_ENTER_CRITICAL(); + UART[uart_num]->conf0.parity = (parity_mode & 0x1); + UART[uart_num]->conf0.parity_en = ((parity_mode >> 1) & 0x1); + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +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(); + + if (UART[uart_num]->conf0.parity_en) + { + if (UART[uart_num]->conf0.parity) + { + (*parity_mode) = UART_PARITY_ODD; + } + else + { + (*parity_mode) = UART_PARITY_EVEN; + } + } + else + { + (*parity_mode) = UART_PARITY_DISABLE; + } + + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +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(); + return ESP_OK; +} + +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)); + return ESP_OK; +} + +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(); + UART[uart_num]->conf0.val &= ~UART_LINE_INV_MASK; + UART[uart_num]->conf0.val |= inverse_mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((flow_ctrl < UART_HW_FLOWCTRL_MAX), "uart_flow ctrl error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + + if (flow_ctrl & UART_HW_FLOWCTRL_RTS) + { + UART[uart_num]->conf1.rx_flow_thrhd = rx_thresh; + UART[uart_num]->conf1.rx_flow_en = 1; + } + else + { + UART[uart_num]->conf1.rx_flow_en = 0; + } + + if (flow_ctrl & UART_HW_FLOWCTRL_CTS) + { + UART[uart_num]->conf0.tx_flow_en = 1; + } + else + { + UART[uart_num]->conf0.tx_flow_en = 0; + } + + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t *flow_ctrl) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + uart_hw_flowcontrol_t val = UART_HW_FLOWCTRL_DISABLE; + + if (UART[uart_num]->conf1.rx_flow_en) + { + val |= UART_HW_FLOWCTRL_RTS; + } + + if (UART[uart_num]->conf0.tx_flow_en) + { + val |= UART_HW_FLOWCTRL_CTS; + } + + (*flow_ctrl) = val; + return ESP_OK; +} + +esp_err_t my_uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) +{ + 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); + uint32_t baudrate; + uint32_t byte_delay_us = 0; + BaseType_t res; + portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; + + // Take tx_mux + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); + if (res == pdFALSE) + { + return ESP_ERR_TIMEOUT; + } + + if (false == p_uart_obj[uart_num]->wait_tx_done_flg) + { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_OK; + } + + my_uart_get_baudrate(uart_num, &baudrate); + byte_delay_us = (uint32_t)(10000000 / baudrate); // (1/baudrate)*10*1000_000 us + + ticks_to_wait = ticks_end - xTaskGetTickCount(); + // wait for tx done sem. + if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, ticks_to_wait)) + { + while (1) + { + if (UART[uart_num]->status.txfifo_cnt == 0) + { + ets_delay_us(byte_delay_us); // Delay one byte time to guarantee transmission completion + break; + } + } + p_uart_obj[uart_num]->wait_tx_done_flg = false; + } + else + { + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_ERR_TIMEOUT; + } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return ESP_OK; +} + +esp_err_t my_uart_enable_swap(void) +{ + // wait for tx done. + my_uart_wait_tx_done(UART_NUM_0, portMAX_DELAY); + + UART_ENTER_CRITICAL(); + // MTCK -> UART0_CTS -> U0RXD + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); + // MTD0 -> UART0_RTS -> U0TXD + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_UART0_RTS); + // enable swap U0TXD <-> UART0_RTS and U0RXD <-> UART0_CTS + SET_PERI_REG_MASK(UART_SWAP_REG, 0x4); + UART_EXIT_CRITICAL(); + + return ESP_OK; +} + +esp_err_t my_uart_disable_swap(void) +{ + // wait for tx done. + my_uart_wait_tx_done(UART_NUM_0, portMAX_DELAY); + + UART_ENTER_CRITICAL(); + // disable swap U0TXD <-> UART0_RTS and U0RXD <-> UART0_CTS + CLEAR_PERI_REG_MASK(UART_SWAP_REG, 0x4); + UART_EXIT_CRITICAL(); + + return ESP_OK; +} + +static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->conf0.rxfifo_rst = 0x1; + UART[uart_num]->conf0.rxfifo_rst = 0x0; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +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_ENTER_CRITICAL(); + UART[uart_num]->int_clr.val |= mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +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_ENTER_CRITICAL(); + UART[uart_num]->int_ena.val |= enable_mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->int_ena.val &= ~disable_mask; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +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); +} + +esp_err_t my_uart_disable_rx_intr(uart_port_t uart_num) +{ + return my_uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA); +} + +esp_err_t my_uart_disable_tx_intr(uart_port_t uart_num) +{ + return my_uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA); +} + +esp_err_t my_uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((thresh < UART_FIFO_LEN), "empty intr threshold error", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + UART[uart_num]->int_clr.txfifo_empty = 1; + UART[uart_num]->conf1.txfifo_empty_thrhd = thresh & 0x7f; + UART[uart_num]->int_ena.txfifo_empty = enable & 0x1; + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +static void uart_intr_service(void *arg) +{ + // UART intr process + uint32_t uart_num = 0; + // read status to get interrupt status for UART0-1 + uint32_t uart_intr_status = UART[uart_num]->int_st.val; + + if (uart_isr_func == NULL) + { + return; + } + + do + { + uart_intr_status = UART[uart_num]->int_st.val; + if (uart_intr_status != 0) + { + if (uart_isr_func[uart_num].fn != NULL) + { + uart_isr_func[uart_num].fn(uart_isr_func[uart_num].args); + } + } + } while (++uart_num < UART_NUM_MAX); +} + +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_ENTER_CRITICAL(); + _xt_isr_mask(1 << ETS_UART_INUM); + _xt_isr_attach(ETS_UART_INUM, uart_intr_service, NULL); + uart_isr_func[uart_num].fn = fn; + uart_isr_func[uart_num].args = arg; + _xt_isr_unmask(1 << ETS_UART_INUM); + UART_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t my_uart_param_config(uart_port_t uart_num, uart_config_t *uart_conf) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + if (uart_num == UART_NUM_1) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); + } + else + { + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); + + if (uart_conf->flow_ctrl & UART_HW_FLOWCTRL_RTS) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); + } + + if (uart_conf->flow_ctrl & UART_HW_FLOWCTRL_CTS) + { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); + } + + my_uart_set_hw_flow_ctrl(uart_num, uart_conf->flow_ctrl, uart_conf->rx_flow_ctrl_thresh); + } + + my_uart_set_baudrate(uart_num, uart_conf->baud_rate); + my_uart_set_word_length(uart_num, uart_conf->data_bits); + my_uart_set_stop_bits(uart_num, uart_conf->stop_bits); + my_uart_set_parity(uart_num, uart_conf->parity); + uart_reset_rx_fifo(uart_num); + + return ESP_OK; +} + +esp_err_t my_uart_intr_config(uart_port_t uart_num, uart_intr_config_t *intr_conf) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + my_uart_clear_intr_status(uart_num, UART_INTR_MASK); + UART_ENTER_CRITICAL(); + UART[uart_num]->int_clr.val = UART_INTR_MASK; + + if (intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) + { + UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & 0x7f); + UART[uart_num]->conf1.rx_tout_en = 1; + } + else + { + UART[uart_num]->conf1.rx_tout_en = 0; + } + + if (intr_conf->intr_enable_mask & UART_RXFIFO_FULL_INT_ENA_M) + { + UART[uart_num]->conf1.rxfifo_full_thrhd = intr_conf->rxfifo_full_thresh; + } + + if (intr_conf->intr_enable_mask & UART_TXFIFO_EMPTY_INT_ENA_M) + { + UART[uart_num]->conf1.txfifo_empty_thrhd = intr_conf->txfifo_empty_intr_thresh; + } + + // my_uart_clear_intr_status(UART[uart_num], mask); + UART[uart_num]->int_ena.val = intr_conf->intr_enable_mask; + _xt_isr_unmask(0x1 << ETS_UART_INUM); + UART_EXIT_CRITICAL(); + + return ESP_OK; +} + +// internal isr handler for default driver code. +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; + uint8_t buf_idx = 0; + uint32_t uart_intr_status = UART[uart_num]->int_st.val; + uart_event_t uart_event; + BaseType_t task_woken = 0; + + + while (uart_intr_status != 0x0) + { + uart_select_notif_t notify = UART_SELECT_ERROR_NOTIF; + + buf_idx = 0; + uart_event.type = UART_EVENT_MAX; + + if (uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) + { + my_uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M); + my_uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA_M); + + // TX semaphore will only be used when tx_buf_size is zero. + if (p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) + { + p_uart->tx_waiting_fifo = false; + xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, &task_woken); + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else + { + // We don't use TX ring buffer, because the size is zero. + if (p_uart->tx_buf_size == 0) + { + continue; + } + + int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt; + bool en_tx_flg = false; + + // We need to put a loop here, in case all the buffer items are very short. + // That would cause a watch_dog reset because empty interrupt happens so often. + // Although this is a loop in ISR, this loop will execute at most 128 turns. + while (tx_fifo_rem) + { + if (p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) + { + size_t size; + p_uart->tx_head = (uart_tx_data_t *)xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + + if (p_uart->tx_head) + { + // The first item is the data description + // Get the first item to get the data information + if (p_uart->tx_len_tot == 0) + { + p_uart->tx_ptr = NULL; + p_uart->tx_len_tot = p_uart->tx_head->tx_data.size; + // We have saved the data description from the 1st item, return buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &task_woken); + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else if (p_uart->tx_ptr == NULL) + { + // Update the TX item pointer, we will need this to return item to buffer. + p_uart->tx_ptr = (uint8_t *)p_uart->tx_head; + en_tx_flg = true; + p_uart->tx_len_cur = size; + } + } + else + { + // Can not get data from ring buffer, return; + break; + } + } + + if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) + { + // To fill the TX FIFO. + int send_len = p_uart->tx_len_cur > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_cur; + + for (buf_idx = 0; buf_idx < send_len; buf_idx++) + { + UART[uart_num]->fifo.rw_byte = *(p_uart->tx_ptr++) & 0xff; + } + + p_uart->tx_len_tot -= send_len; + p_uart->tx_len_cur -= send_len; + tx_fifo_rem -= send_len; + + if (p_uart->tx_len_cur == 0) + { + // Return item to ring buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &task_woken); + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + + p_uart->tx_head = NULL; + p_uart->tx_ptr = NULL; + } + + if (p_uart->tx_len_tot == 0) + { + en_tx_flg = false; + xSemaphoreGiveFromISR(p_uart->tx_done_sem, &task_woken); + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else + { + en_tx_flg = true; + } + } + } + + if (en_tx_flg) + { + my_uart_clear_intr_status(uart_num, UART_TXFIFO_EMPTY_INT_CLR_M); + my_uart_enable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA_M); + } + } + } + else if ((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) + { + rx_fifo_len = uart_reg->status.rxfifo_cnt; + + if (p_uart->rx_buffer_full_flg == false) + { + // We have to read out all data in RX FIFO to clear the interrupt signal + while (buf_idx < rx_fifo_len) + { + p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte; + } + + // Get the buffer from the FIFO + // After Copying the Data From FIFO ,Clear intr_status + my_uart_clear_intr_status(uart_num, UART_RXFIFO_TOUT_INT_CLR_M | UART_RXFIFO_FULL_INT_CLR_M); + uart_event.type = UART_DATA; + uart_event.size = rx_fifo_len; + p_uart->rx_stash_len = rx_fifo_len; + + // If we fail to push data to ring buffer, we will have to stash the data, and send next time. + // Mainly for applications that uses flow control or small ring buffer. + if (pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &task_woken)) + { + my_uart_disable_intr_mask(uart_num, UART_RXFIFO_TOUT_INT_ENA_M | UART_RXFIFO_FULL_INT_ENA_M); + uart_event.type = UART_BUFFER_FULL; + p_uart->rx_buffer_full_flg = true; + // SWO modify + // When we cannot write to the ring buffer, we also think that the serial port is "overflow". + SetTraceError(DAP_SWO_BUFFER_OVERRUN); + } + else + { + p_uart->rx_buffered_len += p_uart->rx_stash_len; + xEventGroupSetBitsFromISR(kUART_Monitoe_event_group, UART_GOT_DATA, pdFALSE); + } + + notify = UART_SELECT_READ_NOTIF; + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + else + { + my_uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M); + my_uart_clear_intr_status(uart_num, UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M); + } + } + else if (uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) + { + // When fifo overflows, we reset the fifo. + uart_reset_rx_fifo(uart_num); + uart_reg->int_clr.rxfifo_ovf = 1; + uart_event.type = UART_FIFO_OVF; + notify = UART_SELECT_ERROR_NOTIF; + // 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, + // and there is basically no data loss. + ////TODO: Can we get rid of this code? + SetTraceError(DAP_SWO_BUFFER_OVERRUN); + } + else if (uart_intr_status & UART_FRM_ERR_INT_ST_M) + { + uart_reg->int_clr.frm_err = 1; + uart_event.type = UART_FRAME_ERR; + notify = UART_SELECT_ERROR_NOTIF; + // SWO modify + SetTraceError(DAP_SWO_STREAM_ERROR); + } + else if (uart_intr_status & UART_PARITY_ERR_INT_ST_M) + { + uart_reg->int_clr.parity_err = 1; + uart_event.type = UART_PARITY_ERR; + notify = UART_SELECT_ERROR_NOTIF; + // SWO modify + SetTraceError(DAP_SWO_STREAM_ERROR); + } + else + { + uart_reg->int_clr.val = uart_intr_status; // simply clear all other intr status + uart_event.type = UART_EVENT_MAX; + notify = UART_SELECT_ERROR_NOTIF; + // SWO modify + SetTraceError(DAP_SWO_STREAM_ERROR); + } + +#ifdef CONFIG_USING_ESP_VFS + if (uart_event.type != UART_EVENT_MAX && p_uart->uart_select_notif_callback) + { + p_uart->uart_select_notif_callback(uart_num, notify, &task_woken); + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } +#else + (void)notify; +#endif + + if (uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) + { + if (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void *)&uart_event, &task_woken)) + { + ESP_EARLY_LOGV(UART_TAG, "UART event queue full"); + } + + if (task_woken == pdTRUE) + { + portYIELD_FROM_ISR(); + } + } + + uart_intr_status = uart_reg->int_st.val; + } +} + +// 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) +{ + uint8_t i = 0; + uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt; + uint8_t tx_remain_fifo_cnt = (UART_FIFO_LEN - tx_fifo_cnt); + uint8_t copy_cnt = (len >= tx_remain_fifo_cnt ? tx_remain_fifo_cnt : len); + + for (i = 0; i < copy_cnt; i++) + { + UART[uart_num]->fifo.rw_byte = buffer[i]; + } + + return copy_cnt; +} + +int my_uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + UART_CHECK(buffer, "buffer null", (-1)); + + if (len == 0) + { + return 0; + } + + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); + int tx_len = uart_fill_fifo(uart_num, (const char *)buffer, len); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return tx_len; +} + +static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size) +{ + if (size == 0) + { + return 0; + } + + size_t original_size = size; + + // lock for uart_tx + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); + p_uart_obj[uart_num]->wait_tx_done_flg = true; + if (p_uart_obj[uart_num]->tx_buf_size > 0) + { + int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); + int offset = 0; + uart_tx_data_t evt; + evt.tx_data.size = size; + evt.type = UART_DATA; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)&evt, sizeof(uart_tx_data_t), portMAX_DELAY); + + while (size > 0) + { + int send_size = size > max_size / 2 ? max_size / 2 : size; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)(src + offset), send_size, portMAX_DELAY); + size -= send_size; + offset += send_size; + my_uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); + } + } + else + { + while (size) + { + // semaphore for tx_fifo available + if (pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) + { + size_t sent = uart_fill_fifo(uart_num, (char *)src, size); + + if (sent < size) + { + p_uart_obj[uart_num]->tx_waiting_fifo = true; + my_uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); + } + + size -= sent; + src += sent; + } + } + + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); + } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return original_size; +} + +int my_uart_write_bytes(uart_port_t uart_num, const char *src, size_t size) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + UART_CHECK(src, "buffer null", (-1)); + + return uart_tx_all(uart_num, src, size); +} + +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((buf), "uart data null", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + + uint8_t *data = NULL; + size_t size; + size_t copy_len = 0; + int len_tmp; + + if (xSemaphoreTake(p_uart_obj[uart_num]->rx_mux, (portTickType)ticks_to_wait) != pdTRUE) + { + return -1; + } + + while (length) + { + if (p_uart_obj[uart_num]->rx_cur_remain == 0) + { + data = (uint8_t *)xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType)ticks_to_wait); + + if (data) + { + p_uart_obj[uart_num]->rx_head_ptr = data; + p_uart_obj[uart_num]->rx_ptr = data; + p_uart_obj[uart_num]->rx_cur_remain = size; + } + else + { + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); + return copy_len; + } + } + + if (p_uart_obj[uart_num]->rx_cur_remain > length) + { + len_tmp = length; + } + else + { + len_tmp = p_uart_obj[uart_num]->rx_cur_remain; + } + + memcpy(buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp); + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len -= len_tmp; + p_uart_obj[uart_num]->rx_ptr += len_tmp; + UART_EXIT_CRITICAL(); + p_uart_obj[uart_num]->rx_cur_remain -= len_tmp; + copy_len += len_tmp; + length -= len_tmp; + + if (p_uart_obj[uart_num]->rx_cur_remain == 0) + { + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ptr = NULL; + + if (p_uart_obj[uart_num]->rx_buffer_full_flg) + { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); + + if (res == pdTRUE) + { + UART_ENTER_CRITICAL(); + 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(); + my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); + } + } + } + } + + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); + return copy_len; +} + +esp_err_t my_uart_get_buffered_data_len(uart_port_t uart_num, size_t *size) +{ + 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); + + *size = p_uart_obj[uart_num]->rx_buffered_len; + return ESP_OK; +} + +esp_err_t my_uart_flush(uart_port_t uart_num) __attribute__((alias("my_uart_flush_input"))); + +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((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_ARG); + uart_obj_t *p_uart = p_uart_obj[uart_num]; + uint8_t *data; + size_t size; + + // rx sem protect the ring buffer read related functions + xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY); + my_uart_disable_rx_intr(p_uart_obj[uart_num]->uart_num); + + while (true) + { + if (p_uart->rx_head_ptr) + { + vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr); + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len -= p_uart->rx_cur_remain; + UART_EXIT_CRITICAL(); + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; + } + + data = (uint8_t *)xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType)0); + + if (data == NULL) + { + if (p_uart_obj[uart_num]->rx_buffered_len != 0) + { + ESP_LOGE(UART_TAG, "rx_buffered_len error"); + p_uart_obj[uart_num]->rx_buffered_len = 0; + } + + // We also need to clear the `rx_buffer_full_flg` here. + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + UART_EXIT_CRITICAL(); + break; + } + + UART_ENTER_CRITICAL(); + p_uart_obj[uart_num]->rx_buffered_len -= size; + UART_EXIT_CRITICAL(); + vRingbufferReturnItem(p_uart->rx_ring_buf, data); + + if (p_uart_obj[uart_num]->rx_buffer_full_flg) + { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); + + if (res == pdTRUE) + { + UART_ENTER_CRITICAL(); + 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(); + } + } + } + + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; + uart_reset_rx_fifo(uart_num); + my_uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); + xSemaphoreGive(p_uart->rx_mux); + return ESP_OK; +} + +esp_err_t my_uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int no_use) +{ + esp_err_t r; + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((rx_buffer_size > UART_FIFO_LEN) || ((uart_num == UART_NUM_1) && (rx_buffer_size == 0)), "uart rx buffer length error(>128)", ESP_ERR_INVALID_ARG); + UART_CHECK((tx_buffer_size > UART_FIFO_LEN) || (tx_buffer_size == 0), "uart tx buffer length error(>128 or 0)", ESP_ERR_INVALID_ARG); + UART_CHECK((queue_size >= 0), "queue_size error(>=0)", ESP_ERR_INVALID_ARG); + + if (p_uart_obj[uart_num] == NULL) + { + p_uart_obj[uart_num] = (uart_obj_t *)calloc(1, sizeof(uart_obj_t)); + + if (p_uart_obj[uart_num] == NULL) + { + ESP_LOGE(UART_TAG, "UART driver malloc error"); + return ESP_FAIL; + } + + p_uart_obj[uart_num]->uart_num = uart_num; + p_uart_obj[uart_num]->uart_mode = UART_MODE_UART; + p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary(); + p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->queue_size = queue_size; + p_uart_obj[uart_num]->tx_ptr = NULL; + p_uart_obj[uart_num]->tx_head = NULL; + p_uart_obj[uart_num]->tx_len_tot = 0; + p_uart_obj[uart_num]->rx_buffered_len = 0; + p_uart_obj[uart_num]->wait_tx_done_flg = false; + + if (uart_queue) + { + p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); + *uart_queue = p_uart_obj[uart_num]->xQueueUart; + ESP_LOGI(UART_TAG, "queue free spaces: %d", (int)uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); + } + else + { + p_uart_obj[uart_num]->xQueueUart = NULL; + } + + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + p_uart_obj[uart_num]->tx_waiting_fifo = false; + p_uart_obj[uart_num]->rx_ptr = NULL; + p_uart_obj[uart_num]->rx_cur_remain = 0; + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF); + p_uart_obj[uart_num]->rx_buf_size = rx_buffer_size; + + if (tx_buffer_size > 0) + { + p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT); + p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; + } + else + { + p_uart_obj[uart_num]->tx_ring_buf = NULL; + p_uart_obj[uart_num]->tx_buf_size = 0; + } + + p_uart_obj[uart_num]->uart_select_notif_callback = NULL; + } + else + { + ESP_LOGE(UART_TAG, "UART driver already installed"); + return ESP_FAIL; + } + + r = my_uart_isr_register(uart_num, uart_rx_intr_handler_default, p_uart_obj[uart_num]); + + if (r != ESP_OK) + { + goto err; + } + + uart_intr_config_t uart_intr = { + .intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M | UART_RXFIFO_TOUT_INT_ENA_M | UART_FRM_ERR_INT_ENA_M | UART_RXFIFO_OVF_INT_ENA_M, + .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT, + .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT, + .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT}; + r = my_uart_intr_config(uart_num, &uart_intr); + + if (r != ESP_OK) + { + goto err; + } + + return r; + +err: + ESP_LOGE(UART_TAG, "driver install error"); + my_uart_driver_delete(uart_num); + return r; +} + +// Make sure no other tasks are still using UART before you call this function +esp_err_t my_uart_driver_delete(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + + if (p_uart_obj[uart_num] == NULL) + { + ESP_LOGI(UART_TAG, "ALREADY NULL"); + return ESP_OK; + } + + my_uart_disable_rx_intr(uart_num); + my_uart_disable_tx_intr(uart_num); + _xt_isr_mask(0x1 << ETS_UART_INUM); + + if (p_uart_obj[uart_num]->tx_fifo_sem) + { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_fifo_sem = NULL; + } + + if (p_uart_obj[uart_num]->tx_done_sem) + { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem); + p_uart_obj[uart_num]->tx_done_sem = NULL; + } + + if (p_uart_obj[uart_num]->tx_mux) + { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux); + p_uart_obj[uart_num]->tx_mux = NULL; + } + + if (p_uart_obj[uart_num]->rx_mux) + { + vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux); + p_uart_obj[uart_num]->rx_mux = NULL; + } + + if (p_uart_obj[uart_num]->xQueueUart) + { + vQueueDelete(p_uart_obj[uart_num]->xQueueUart); + p_uart_obj[uart_num]->xQueueUart = NULL; + } + + if (p_uart_obj[uart_num]->rx_ring_buf) + { + vRingbufferDelete(p_uart_obj[uart_num]->rx_ring_buf); + p_uart_obj[uart_num]->rx_ring_buf = NULL; + } + + if (p_uart_obj[uart_num]->tx_ring_buf) + { + vRingbufferDelete(p_uart_obj[uart_num]->tx_ring_buf); + p_uart_obj[uart_num]->tx_ring_buf = NULL; + } + + free(p_uart_obj[uart_num]); + p_uart_obj[uart_num] = NULL; + + return ESP_OK; +} + +void uart_set_select_notif_callback(uart_port_t uart_num, uart_select_notif_callback_t uart_select_notif_callback) +{ + if (uart_num < UART_NUM_MAX && p_uart_obj[uart_num]) + { + p_uart_obj[uart_num]->uart_select_notif_callback = (uart_select_notif_callback_t)uart_select_notif_callback; + } +} + +esp_err_t my_uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG); + UART_CHECK((tout_thresh < 127), "tout_thresh max value is 126", ESP_ERR_INVALID_ARG); + + UART_ENTER_CRITICAL(); + + // The tout_thresh = 1, defines TOUT interrupt timeout equal to + // transmission time of one symbol (~11 bit) on current baudrate + if (tout_thresh > 0) + { + UART[uart_num]->conf1.rx_tout_thrhd = (tout_thresh & 0x7f); + UART[uart_num]->conf1.rx_tout_en = 1; + } + else + { + UART[uart_num]->conf1.rx_tout_en = 0; + } + + UART_EXIT_CRITICAL(); + return ESP_OK; +} diff --git a/main/DAP_handle.c b/main/DAP_handle.c index 98d26c8..02975b9 100644 --- a/main/DAP_handle.c +++ b/main/DAP_handle.c @@ -14,32 +14,70 @@ #include "DAP.h" ////TODO: Merge this -#define DAP_PACKET_SIZE 512 +#define DAP_PACKET_SIZE 512 +static uint8_t data_out[DAP_PACKET_SIZE]; +static int dap_respond = 0; -uint8_t data_out[DAP_PACKET_SIZE]; -int respond = 0; - +// SWO Trace +static int swo_trace_respond = 0; +static uint8_t *swo_data_to_send; +static uint32_t num_swo_data; void handle_dap_data_request(usbip_stage2_header *header) { - uint8_t * data_in = (uint8_t *)header; + uint8_t *data_in = (uint8_t *)header; data_in = &(data_in[sizeof(usbip_stage2_header)]); // Point to the beginning of the URB packet - respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); + dap_respond = DAP_ProcessCommand((uint8_t *)data_in, (uint8_t *)data_out); send_stage2_submit(header, 0, 0); - } void handle_dap_data_response(usbip_stage2_header *header) { - if (respond) { - respond = 0; - //os_printf("*** Will respond"); - send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); - - //os_printf("*** RESPONDED ***"); - } else { - //os_printf("*** Will NOT respond"); - send_stage2_submit(header, 0, 0); - } + if (dap_respond) + { + dap_respond = 0; + //os_printf("*** Will respond"); + send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); + + //os_printf("*** RESPONDED ***"); + } + else + { + //os_printf("*** Will NOT respond"); + send_stage2_submit(header, 0, 0); + } +} + +void handle_swo_trace_response(usbip_stage2_header *header) +{ + if (swo_trace_respond) + { + swo_trace_respond = 0; + //os_printf("*** Will respond"); + send_stage2_submit_data(header, 0, data_out, DAP_PACKET_SIZE); + + //os_printf("*** RESPONDED ***"); + } + else + { + //os_printf("*** Will NOT respond"); + send_stage2_submit(header, 0, 0); + } +} + + +// SWO Data Queue Transfer +// buf: pointer to buffer with data +// num: number of bytes to transfer +void SWO_QueueTransfer (uint8_t *buf, uint32_t num) { + swo_data_to_send = buf; + num_swo_data = num; + swo_trace_respond = 1; +} + +// SWO Data Abort Transfer +void SWO_AbortTransfer (void) { + //USBD_EndpointAbort(0U, USB_ENDPOINT_IN(2U)); + ////TODO: unlink might be useful ... } \ No newline at end of file diff --git a/main/DAP_handle.h b/main/DAP_handle.h index 903bc58..5ac91f2 100644 --- a/main/DAP_handle.h +++ b/main/DAP_handle.h @@ -5,4 +5,5 @@ void handle_dap_data_request(usbip_stage2_header *header); void handle_dap_data_response(usbip_stage2_header *header); +void handle_swo_trace_response(usbip_stage2_header *header); #endif \ No newline at end of file diff --git a/main/main.c b/main/main.c index 03f5354..b658cec 100644 --- a/main/main.c +++ b/main/main.c @@ -26,13 +26,14 @@ #include "tcp_server.h" #include "timer.h" #include "wifi_configuration.h" - /* The examples use simple WiFi configuration that you can set via 'make menuconfig'. If you'd rather not, just change the below entries to strings with the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" */ +extern void SWO_Thread(void *argument); +extern void usart_monitor_task(void *argument); /* FreeRTOS event group to signal when we are connected & ready to make a request */ static EventGroupHandle_t wifi_event_group; @@ -95,6 +96,7 @@ static void initialise_wifi(void) { tcpip_adapter_init(); wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL)); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); @@ -109,7 +111,7 @@ static void initialise_wifi(void) ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); - + } static void wait_for_ip() @@ -135,6 +137,10 @@ void app_main() initialise_wifi(); wait_for_ip(); - xTaskCreate(timer_create_task, "timer_create", 1024, NULL, 10, NULL); + xTaskCreate(timer_create_task, "timer_create", 512, NULL, 10, NULL); xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL); + // SWO Trace Task + xTaskCreate(SWO_Thread, "swo_task", 1024, NULL, 6, NULL); + xTaskCreate(usart_monitor_task, "uart_task", 512, NULL, 6, NULL); + } diff --git a/main/usbip_server.c b/main/usbip_server.c index 0317f6f..cf87a53 100644 --- a/main/usbip_server.c +++ b/main/usbip_server.c @@ -27,6 +27,10 @@ static void unpack(void *data, int size); static int handle_submit(usbip_stage2_header *header); static int read_stage2_command(usbip_stage2_header *header, uint32_t length); +static void handle_unlink(usbip_stage2_header *header); +// unlink helper function +static void send_stage2_unlink(usbip_stage2_header *req_header); + int attach(uint8_t *buffer, uint32_t length) { int command = read_stage1_command(buffer, length); @@ -41,7 +45,7 @@ int attach(uint8_t *buffer, uint32_t length) handle_device_list(buffer, length); break; - case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT + case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT handle_device_attach(buffer, length); break; @@ -176,7 +180,7 @@ static void send_interface_info() int emulate(uint8_t *buffer, uint32_t length) { // usbip_stage2_header header; - int command = read_stage2_command((usbip_stage2_header *)buffer, length); + int command = read_stage2_command((usbip_stage2_header *)buffer, length); if (command < 0) { return -1; @@ -258,7 +262,6 @@ static void unpack(void *data, int size) } } - /** * @brief * @@ -272,7 +275,7 @@ static int handle_submit(usbip_stage2_header *header) handleUSBControlRequest(header); break; - // data + // endpoint 1 data receicve and response case 0x01: if (header->base.direction == 0) { @@ -285,7 +288,19 @@ static int handle_submit(usbip_stage2_header *header) handle_dap_data_response(header); } break; - + // endpoint 2 for SWO trace + case 0x02: + if (header->base.direction == 0) + { + // os_printf("EP 02 DATA FROM HOST"); + send_stage2_submit(header, 0, 0); + } + else + { + // os_printf("EP 02 DATA TO HOST"); + handle_swo_trace_response(header); + } + break; // request to save data to device case 0x81: if (header->base.direction == 0) @@ -320,7 +335,7 @@ void send_stage2_submit(usbip_stage2_header *req_header, int32_t status, int32_t send(kSock, req_header, sizeof(usbip_stage2_header), 0); } -void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void * const data, int32_t data_length) +void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, const void *const data, int32_t data_length) { send_stage2_submit(req_header, status, data_length); @@ -329,4 +344,24 @@ void send_stage2_submit_data(usbip_stage2_header *req_header, int32_t status, co { send(kSock, data, data_length, 0); } +} + +static void handle_unlink(usbip_stage2_header *header) +{ + os_printf("s2 handling cmd unlink...\r\n"); + send_stage2_unlink(header); +} +static void send_stage2_unlink(usbip_stage2_header *req_header) +{ + + req_header->base.command = USBIP_STAGE2_RSP_UNLINK; + req_header->base.direction = USBIP_DIR_OUT; + + memset(&(req_header->u.ret_unlink), 0, sizeof(usbip_stage2_header_ret_unlink)); + + // req_header.u.ret_unlink.status = 0; + + pack(req_header, sizeof(usbip_stage2_header)); + + send(kSock, req_header, sizeof(usbip_stage2_header), 0); } \ No newline at end of file