summaryrefslogtreecommitdiffstats
path: root/Drivers/CMSIS/DAP/Firmware/Source/UART.c
diff options
context:
space:
mode:
Diffstat (limited to 'Drivers/CMSIS/DAP/Firmware/Source/UART.c')
-rw-r--r--Drivers/CMSIS/DAP/Firmware/Source/UART.c652
1 files changed, 652 insertions, 0 deletions
diff --git a/Drivers/CMSIS/DAP/Firmware/Source/UART.c b/Drivers/CMSIS/DAP/Firmware/Source/UART.c
new file mode 100644
index 0000000..8e9eae5
--- /dev/null
+++ b/Drivers/CMSIS/DAP/Firmware/Source/UART.c
@@ -0,0 +1,652 @@
+/*
+ * Copyright (c) 2021 ARM Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ----------------------------------------------------------------------
+ *
+ * $Date: 1. March 2021
+ * $Revision: V1.0.0
+ *
+ * Project: CMSIS-DAP Source
+ * Title: UART.c CMSIS-DAP UART
+ *
+ *---------------------------------------------------------------------------*/
+
+#include "DAP_config.h"
+#include "DAP.h"
+
+#if (DAP_UART != 0)
+
+#ifdef DAP_FW_V1
+#error "UART Communication Port not supported in DAP V1!"
+#endif
+
+#include "Driver_USART.h"
+
+#include "cmsis_os2.h"
+#include <string.h>
+
+#define UART_RX_BLOCK_SIZE 32U /* Uart Rx Block Size (must be 2^n) */
+
+// USART Driver
+#define _USART_Driver_(n) Driver_USART##n
+#define USART_Driver_(n) _USART_Driver_(n)
+extern ARM_DRIVER_USART USART_Driver_(DAP_UART_DRIVER);
+#define pUSART (&USART_Driver_(DAP_UART_DRIVER))
+
+// UART Configuration
+#if (DAP_UART_USB_COM_PORT != 0)
+static uint8_t UartTransport = DAP_UART_TRANSPORT_USB_COM_PORT;
+#else
+static uint8_t UartTransport = DAP_UART_TRANSPORT_NONE;
+#endif
+
+// UART Flags
+static uint8_t UartConfigured = 0U;
+static uint8_t UartReceiveEnabled = 0U;
+static uint8_t UartTransmitEnabled = 0U;
+static uint8_t UartTransmitActive = 0U;
+
+// UART TX Buffer
+static uint8_t UartTxBuf[DAP_UART_TX_BUFFER_SIZE];
+static volatile uint32_t UartTxIndexI = 0U;
+static volatile uint32_t UartTxIndexO = 0U;
+
+// UART RX Buffer
+static uint8_t UartRxBuf[DAP_UART_RX_BUFFER_SIZE];
+static volatile uint32_t UartRxIndexI = 0U;
+static volatile uint32_t UartRxIndexO = 0U;
+
+// Uart Errors
+static volatile uint8_t UartErrorRxDataLost = 0U;
+static volatile uint8_t UartErrorFraming = 0U;
+static volatile uint8_t UartErrorParity = 0U;
+
+// UART Transmit
+static uint32_t UartTxNum = 0U;
+
+// Function prototypes
+static uint8_t UART_Init (void);
+static void UART_Uninit (void);
+static uint8_t UART_Get_Status (void);
+static uint8_t UART_Receive_Enable (void);
+static uint8_t UART_Transmit_Enable (void);
+static void UART_Receive_Disable (void);
+static void UART_Transmit_Disable (void);
+static void UART_Receive_Flush (void);
+static void UART_Transmit_Flush (void);
+static void UART_Receive (void);
+static void UART_Transmit (void);
+
+
+// USART Driver Callback function
+// event: event mask
+static void USART_Callback (uint32_t event) {
+ if (event & ARM_USART_EVENT_SEND_COMPLETE) {
+ UartTxIndexO += UartTxNum;
+ UartTransmitActive = 0U;
+ UART_Transmit();
+ }
+ if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) {
+ UartRxIndexI += UART_RX_BLOCK_SIZE;
+ UART_Receive();
+ }
+ if (event & ARM_USART_EVENT_RX_OVERFLOW) {
+ UartErrorRxDataLost = 1U;
+ }
+ if (event & ARM_USART_EVENT_RX_FRAMING_ERROR) {
+ UartErrorFraming = 1U;
+ }
+ if (event & ARM_USART_EVENT_RX_PARITY_ERROR) {
+ UartErrorParity = 1U;
+ }
+}
+
+// Init UART
+// return: DAP_OK or DAP_ERROR
+static uint8_t UART_Init (void) {
+ int32_t status;
+ uint8_t ret = DAP_ERROR;
+
+ UartConfigured = 0U;
+ UartReceiveEnabled = 0U;
+ UartTransmitEnabled = 0U;
+ UartTransmitActive = 0U;
+ UartErrorRxDataLost = 0U;
+ UartErrorFraming = 0U;
+ UartErrorParity = 0U;
+ UartTxIndexI = 0U;
+ UartTxIndexO = 0U;
+ UartRxIndexI = 0U;
+ UartRxIndexO = 0U;
+ UartTxNum = 0U;
+
+ status = pUSART->Initialize(USART_Callback);
+ if (status == ARM_DRIVER_OK) {
+ status = pUSART->PowerControl(ARM_POWER_FULL);
+ }
+ if (status == ARM_DRIVER_OK) {
+ ret = DAP_OK;
+ }
+
+ return (ret);
+}
+
+// Un-Init UART
+static void UART_Uninit (void) {
+ UartConfigured = 0U;
+
+ pUSART->PowerControl(ARM_POWER_OFF);
+ pUSART->Uninitialize();
+}
+
+// Get UART Status
+// return: status
+static uint8_t UART_Get_Status (void) {
+ uint8_t status = 0U;
+
+ if (UartReceiveEnabled != 0U) {
+ status |= DAP_UART_STATUS_RX_ENABLED;
+ }
+ if (UartErrorRxDataLost != 0U) {
+ UartErrorRxDataLost = 0U;
+ status |= DAP_UART_STATUS_RX_DATA_LOST;
+ }
+ if (UartErrorFraming != 0U) {
+ UartErrorFraming = 0U;
+ status |= DAP_UART_STATUS_FRAMING_ERROR;
+ }
+ if (UartErrorParity != 0U) {
+ UartErrorParity = 0U;
+ status |= DAP_UART_STATUS_PARITY_ERROR;
+ }
+ if (UartTransmitEnabled != 0U) {
+ status |= DAP_UART_STATUS_TX_ENABLED;
+ }
+
+ return (status);
+}
+
+// Enable UART Receive
+// return: DAP_OK or DAP_ERROR
+static uint8_t UART_Receive_Enable (void) {
+ int32_t status;
+ uint8_t ret = DAP_ERROR;
+
+ if (UartReceiveEnabled == 0U) {
+ // Flush Buffers
+ UartRxIndexI = 0U;
+ UartRxIndexO = 0U;
+
+ UART_Receive();
+ status = pUSART->Control(ARM_USART_CONTROL_RX, 1U);
+ if (status == ARM_DRIVER_OK) {
+ UartReceiveEnabled = 1U;
+ ret = DAP_OK;
+ }
+ } else {
+ ret = DAP_OK;
+ }
+
+ return (ret);
+}
+
+// Enable UART Transmit
+// return: DAP_OK or DAP_ERROR
+static uint8_t UART_Transmit_Enable (void) {
+ int32_t status;
+ uint8_t ret = DAP_ERROR;
+
+ if (UartTransmitEnabled == 0U) {
+ // Flush Buffers
+ UartTransmitActive = 0U;
+ UartTxIndexI = 0U;
+ UartTxIndexO = 0U;
+ UartTxNum = 0U;
+
+ status = pUSART->Control(ARM_USART_CONTROL_TX, 1U);
+ if (status == ARM_DRIVER_OK) {
+ UartTransmitEnabled = 1U;
+ ret = DAP_OK;
+ }
+ } else {
+ ret = DAP_OK;
+ }
+
+ return (ret);
+}
+
+// Disable UART Receive
+static void UART_Receive_Disable (void) {
+ if (UartReceiveEnabled != 0U) {
+ pUSART->Control(ARM_USART_CONTROL_RX, 0U);
+ pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
+ UartReceiveEnabled = 0U;
+ }
+}
+
+// Disable UART Transmit
+static void UART_Transmit_Disable (void) {
+ if (UartTransmitEnabled != 0U) {
+ pUSART->Control(ARM_USART_ABORT_SEND, 0U);
+ pUSART->Control(ARM_USART_CONTROL_TX, 0U);
+ UartTransmitActive = 0U;
+ UartTransmitEnabled = 0U;
+ }
+}
+
+// Flush UART Receive buffer
+static void UART_Receive_Flush (void) {
+ pUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
+ UartRxIndexI = 0U;
+ UartRxIndexO = 0U;
+ if (UartReceiveEnabled != 0U) {
+ UART_Receive();
+ }
+}
+
+// Flush UART Transmit buffer
+static void UART_Transmit_Flush (void) {
+ pUSART->Control(ARM_USART_ABORT_SEND, 0U);
+ UartTransmitActive = 0U;
+ UartTxIndexI = 0U;
+ UartTxIndexO = 0U;
+ UartTxNum = 0U;
+}
+
+// Receive data from target via UART
+static void UART_Receive (void) {
+ uint32_t index;
+
+ index = UartRxIndexI & (DAP_UART_RX_BUFFER_SIZE - 1U);
+ pUSART->Receive(&UartRxBuf[index], UART_RX_BLOCK_SIZE);
+}
+
+// Transmit available data to target via UART
+static void UART_Transmit (void) {
+ uint32_t count;
+ uint32_t index;
+
+ count = UartTxIndexI - UartTxIndexO;
+ index = UartTxIndexO & (DAP_UART_TX_BUFFER_SIZE - 1U);
+
+ if (count != 0U) {
+ if ((index + count) <= DAP_UART_TX_BUFFER_SIZE) {
+ UartTxNum = count;
+ } else {
+ UartTxNum = DAP_UART_TX_BUFFER_SIZE - index;
+ }
+ UartTransmitActive = 1U;
+ pUSART->Send(&UartTxBuf[index], UartTxNum);
+ }
+}
+
+// Process UART 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 UART_Transport (const uint8_t *request, uint8_t *response) {
+ uint8_t transport;
+ uint8_t ret = DAP_ERROR;
+
+ transport = *request;
+ switch (transport) {
+ case DAP_UART_TRANSPORT_NONE:
+ switch (UartTransport) {
+ case DAP_UART_TRANSPORT_NONE:
+ ret = DAP_OK;
+ break;
+ case DAP_UART_TRANSPORT_USB_COM_PORT:
+#if (DAP_UART_USB_COM_PORT != 0)
+ USB_COM_PORT_Activate(0U);
+ UartTransport = DAP_UART_TRANSPORT_NONE;
+ ret = DAP_OK;
+#endif
+ break;
+ case DAP_UART_TRANSPORT_DAP_COMMAND:
+ UART_Receive_Disable();
+ UART_Transmit_Disable();
+ UART_Uninit();
+ UartTransport = DAP_UART_TRANSPORT_NONE;
+ ret= DAP_OK;
+ break;
+ }
+ break;
+ case DAP_UART_TRANSPORT_USB_COM_PORT:
+ switch (UartTransport) {
+ case DAP_UART_TRANSPORT_NONE:
+#if (DAP_UART_USB_COM_PORT != 0)
+ if (USB_COM_PORT_Activate(1U) == 0U) {
+ UartTransport = DAP_UART_TRANSPORT_USB_COM_PORT;
+ ret = DAP_OK;
+ }
+#endif
+ break;
+ case DAP_UART_TRANSPORT_USB_COM_PORT:
+ ret = DAP_OK;
+ break;
+ case DAP_UART_TRANSPORT_DAP_COMMAND:
+ UART_Receive_Disable();
+ UART_Transmit_Disable();
+ UART_Uninit();
+ UartTransport = DAP_UART_TRANSPORT_NONE;
+#if (DAP_UART_USB_COM_PORT != 0)
+ if (USB_COM_PORT_Activate(1U) == 0U) {
+ UartTransport = DAP_UART_TRANSPORT_USB_COM_PORT;
+ ret = DAP_OK;
+ }
+#endif
+ break;
+ }
+ break;
+ case DAP_UART_TRANSPORT_DAP_COMMAND:
+ switch (UartTransport) {
+ case DAP_UART_TRANSPORT_NONE:
+ ret = UART_Init();
+ if (ret == DAP_OK) {
+ UartTransport = DAP_UART_TRANSPORT_DAP_COMMAND;
+ }
+ break;
+ case DAP_UART_TRANSPORT_USB_COM_PORT:
+#if (DAP_UART_USB_COM_PORT != 0)
+ USB_COM_PORT_Activate(0U);
+ UartTransport = DAP_UART_TRANSPORT_NONE;
+#endif
+ ret = UART_Init();
+ if (ret == DAP_OK) {
+ UartTransport = DAP_UART_TRANSPORT_DAP_COMMAND;
+ }
+ break;
+ case DAP_UART_TRANSPORT_DAP_COMMAND:
+ ret = DAP_OK;
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ *response = ret;
+
+ return ((1U << 16) | 1U);
+}
+
+// Process UART Configure 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 UART_Configure (const uint8_t *request, uint8_t *response) {
+ uint8_t control, status;
+ uint32_t baudrate;
+ int32_t result;
+
+ if (UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) {
+ status = DAP_UART_CFG_ERROR_DATA_BITS |
+ DAP_UART_CFG_ERROR_PARITY |
+ DAP_UART_CFG_ERROR_STOP_BITS;
+ baudrate = 0U; // baudrate error
+ } else {
+
+ status = 0U;
+ control = *request;
+ baudrate = (uint32_t)(*(request+1) << 0) |
+ (uint32_t)(*(request+2) << 8) |
+ (uint32_t)(*(request+3) << 16) |
+ (uint32_t)(*(request+4) << 24);
+
+ result = pUSART->Control(control |
+ ARM_USART_MODE_ASYNCHRONOUS |
+ ARM_USART_FLOW_CONTROL_NONE,
+ baudrate);
+ if (result == ARM_DRIVER_OK) {
+ UartConfigured = 1U;
+ } else {
+ UartConfigured = 0U;
+ switch (result) {
+ case ARM_USART_ERROR_BAUDRATE:
+ status = 0U;
+ baudrate = 0U;
+ break;
+ case ARM_USART_ERROR_DATA_BITS:
+ status = DAP_UART_CFG_ERROR_DATA_BITS;
+ break;
+ case ARM_USART_ERROR_PARITY:
+ status = DAP_UART_CFG_ERROR_PARITY;
+ break;
+ case ARM_USART_ERROR_STOP_BITS:
+ status = DAP_UART_CFG_ERROR_STOP_BITS;
+ break;
+ default:
+ status = DAP_UART_CFG_ERROR_DATA_BITS |
+ DAP_UART_CFG_ERROR_PARITY |
+ DAP_UART_CFG_ERROR_STOP_BITS;
+ baudrate = 0U;
+ break;
+ }
+ }
+ }
+
+ *response++ = status;
+ *response++ = (uint8_t)(baudrate >> 0);
+ *response++ = (uint8_t)(baudrate >> 8);
+ *response++ = (uint8_t)(baudrate >> 16);
+ *response = (uint8_t)(baudrate >> 24);
+
+ return ((5U << 16) | 5U);
+}
+
+// Process UART 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 UART_Control (const uint8_t *request, uint8_t *response) {
+ uint8_t control;
+ uint8_t result;
+ uint8_t ret = DAP_OK;
+
+ if (UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) {
+ ret = DAP_ERROR;
+ } else {
+
+ control = *request;
+
+ if ((control & DAP_UART_CONTROL_RX_DISABLE) != 0U) {
+ // Receive disable
+ UART_Receive_Disable();
+ } else if ((control & DAP_UART_CONTROL_RX_ENABLE) != 0U) {
+ // Receive enable
+ if (UartConfigured != 0U) {
+ result = UART_Receive_Enable();
+ if (result != DAP_OK) {
+ ret = DAP_ERROR;
+ }
+ } else {
+ ret = DAP_ERROR;
+ }
+ }
+ if ((control & DAP_UART_CONTROL_RX_BUF_FLUSH) != 0U) {
+ UART_Receive_Flush();
+ }
+
+ if ((control & DAP_UART_CONTROL_TX_DISABLE) != 0U) {
+ // Transmit disable
+ UART_Transmit_Disable();
+ } else if ((control & DAP_UART_CONTROL_TX_ENABLE) != 0U) {
+ // Transmit enable
+ if (UartConfigured != 0U) {
+ result = UART_Transmit_Enable();
+ if (result != DAP_OK) {
+ ret = DAP_ERROR;
+ }
+ } else {
+ ret = DAP_ERROR;
+ }
+ }
+ if ((control & DAP_UART_CONTROL_TX_BUF_FLUSH) != 0U) {
+ UART_Transmit_Flush();
+ }
+ }
+
+ *response = ret;
+
+ return ((1U << 16) | 1U);
+}
+
+// Process UART Status command and prepare response
+// response: pointer to response data
+// return: number of bytes in response (lower 16 bits)
+// number of bytes in request (upper 16 bits)
+uint32_t UART_Status (uint8_t *response) {
+ uint32_t rx_cnt, tx_cnt;
+ uint32_t cnt;
+ uint8_t status;
+
+ if ((UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) ||
+ (UartConfigured == 0U)) {
+ rx_cnt = 0U;
+ tx_cnt = 0U;
+ status = 0U;
+ } else {
+
+ rx_cnt = UartRxIndexI - UartRxIndexO;
+ rx_cnt += pUSART->GetRxCount();
+ if (rx_cnt > (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2))) {
+ // Overflow
+ UartErrorRxDataLost = 1U;
+ rx_cnt = (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2));
+ UartRxIndexO = UartRxIndexI - rx_cnt;
+ }
+
+ tx_cnt = UartTxIndexI - UartTxIndexO;
+ cnt = pUSART->GetTxCount();
+ if (UartTransmitActive != 0U) {
+ tx_cnt -= cnt;
+ }
+
+ status = UART_Get_Status();
+ }
+
+ *response++ = status;
+ *response++ = (uint8_t)(rx_cnt >> 0);
+ *response++ = (uint8_t)(rx_cnt >> 8);
+ *response++ = (uint8_t)(rx_cnt >> 16);
+ *response++ = (uint8_t)(rx_cnt >> 24);
+ *response++ = (uint8_t)(tx_cnt >> 0);
+ *response++ = (uint8_t)(tx_cnt >> 8);
+ *response++ = (uint8_t)(tx_cnt >> 16);
+ *response = (uint8_t)(tx_cnt >> 24);
+
+ return ((0U << 16) | 9U);
+}
+
+// Process UART Transfer 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 UART_Transfer (const uint8_t *request, uint8_t *response) {
+ uint32_t rx_cnt, tx_cnt;
+ uint32_t rx_num, tx_num;
+ uint8_t *rx_data;
+ const
+ uint8_t *tx_data;
+ uint32_t num;
+ uint32_t index;
+ uint8_t status;
+
+ if (UartTransport != DAP_UART_TRANSPORT_DAP_COMMAND) {
+ status = 0U;
+ rx_cnt = 0U;
+ tx_cnt = 0U;
+ } else {
+
+ // RX Data
+ rx_cnt = ((uint32_t)(*(request+0) << 0) |
+ (uint32_t)(*(request+1) << 8));
+
+ if (rx_cnt > (DAP_PACKET_SIZE - 6U)) {
+ rx_cnt = (DAP_PACKET_SIZE - 6U);
+ }
+ rx_num = UartRxIndexI - UartRxIndexO;
+ rx_num += pUSART->GetRxCount();
+ if (rx_num > (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2))) {
+ // Overflow
+ UartErrorRxDataLost = 1U;
+ rx_num = (DAP_UART_RX_BUFFER_SIZE - (UART_RX_BLOCK_SIZE*2));
+ UartRxIndexO = UartRxIndexI - rx_num;
+ }
+ if (rx_cnt > rx_num) {
+ rx_cnt = rx_num;
+ }
+
+ rx_data = (response+5);
+ index = UartRxIndexO & (DAP_UART_RX_BUFFER_SIZE - 1U);
+ if ((index + rx_cnt) <= DAP_UART_RX_BUFFER_SIZE) {
+ memcpy( rx_data, &UartRxBuf[index], rx_cnt);
+ } else {
+ num = DAP_UART_RX_BUFFER_SIZE - index;
+ memcpy( rx_data, &UartRxBuf[index], num);
+ memcpy(&rx_data[num], &UartRxBuf[0], rx_cnt - num);
+ }
+ UartRxIndexO += rx_cnt;
+
+ // TX Data
+ tx_cnt = ((uint32_t)(*(request+2) << 0) |
+ (uint32_t)(*(request+3) << 8));
+ tx_data = (request+4);
+
+ if (tx_cnt > (DAP_PACKET_SIZE - 5U)) {
+ tx_cnt = (DAP_PACKET_SIZE - 5U);
+ }
+ tx_num = UartTxIndexI - UartTxIndexO;
+ num = pUSART->GetTxCount();
+ if (UartTransmitActive != 0U) {
+ tx_num -= num;
+ }
+ if (tx_cnt > (DAP_UART_TX_BUFFER_SIZE - tx_num)) {
+ tx_cnt = (DAP_UART_TX_BUFFER_SIZE - tx_num);
+ }
+
+ index = UartTxIndexI & (DAP_UART_TX_BUFFER_SIZE - 1U);
+ if ((index + tx_cnt) <= DAP_UART_TX_BUFFER_SIZE) {
+ memcpy(&UartTxBuf[index], tx_data, tx_cnt);
+ } else {
+ num = DAP_UART_TX_BUFFER_SIZE - index;
+ memcpy(&UartTxBuf[index], tx_data, num);
+ memcpy(&UartTxBuf[0], &tx_data[num], tx_cnt - num);
+ }
+ UartTxIndexI += tx_cnt;
+
+ if (UartTransmitActive == 0U) {
+ UART_Transmit();
+ }
+
+ status = UART_Get_Status();
+ }
+
+ *response++ = status;
+ *response++ = (uint8_t)(tx_cnt >> 0);
+ *response++ = (uint8_t)(tx_cnt >> 8);
+ *response++ = (uint8_t)(rx_cnt >> 0);
+ *response = (uint8_t)(rx_cnt >> 8);
+
+ return (((4U + tx_cnt) << 16) | (5U + rx_cnt));
+}
+
+#endif /* DAP_UART */