В модель добавлена библиотека CMSIS-DSP и вообще все либы CMSIS

This commit is contained in:
2025-11-13 17:14:43 +03:00
parent 75bed20511
commit 5299cc5b12
1074 changed files with 380657 additions and 7 deletions

View File

@@ -0,0 +1,1812 @@
/*
* Copyright (c) 2013-2022 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: 26. April 2022
* $Revision: V2.1.1
*
* Project: CMSIS-DAP Source
* Title: DAP.c CMSIS-DAP Commands
*
*---------------------------------------------------------------------------*/
#include <string.h>
#include "DAP_config.h"
#include "DAP.h"
#if (DAP_PACKET_SIZE < 64U)
#error "Minimum Packet Size is 64!"
#endif
#if (DAP_PACKET_SIZE > 32768U)
#error "Maximum Packet Size is 32768!"
#endif
#if (DAP_PACKET_COUNT < 1U)
#error "Minimum Packet Count is 1!"
#endif
#if (DAP_PACKET_COUNT > 255U)
#error "Maximum Packet Count is 255!"
#endif
// Clock Macros
#define MAX_SWJ_CLOCK(delay_cycles) \
((CPU_CLOCK/2U) / (IO_PORT_WRITE_CYCLES + delay_cycles))
DAP_Data_t DAP_Data; // DAP Data
volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag
static const char DAP_FW_Ver [] = DAP_FW_VER;
// Common clock delay calculation routine
// clock: requested SWJ frequency in Hertz
static void Set_Clock_Delay(uint32_t clock) {
uint32_t delay;
if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) {
DAP_Data.fast_clock = 1U;
DAP_Data.clock_delay = 1U;
} else {
DAP_Data.fast_clock = 0U;
delay = ((CPU_CLOCK/2U) + (clock - 1U)) / clock;
if (delay > IO_PORT_WRITE_CYCLES) {
delay -= IO_PORT_WRITE_CYCLES;
delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES;
} else {
delay = 1U;
}
DAP_Data.clock_delay = delay;
}
}
// Get DAP Information
// id: info identifier
// info: pointer to info data
// return: number of bytes in info data
static uint8_t DAP_Info(uint8_t id, uint8_t *info) {
uint8_t length = 0U;
switch (id) {
case DAP_ID_VENDOR:
length = DAP_GetVendorString((char *)info);
break;
case DAP_ID_PRODUCT:
length = DAP_GetProductString((char *)info);
break;
case DAP_ID_SER_NUM:
length = DAP_GetSerNumString((char *)info);
break;
case DAP_ID_DAP_FW_VER:
length = (uint8_t)sizeof(DAP_FW_Ver);
memcpy(info, DAP_FW_Ver, length);
break;
case DAP_ID_DEVICE_VENDOR:
length = DAP_GetTargetDeviceVendorString((char *)info);
break;
case DAP_ID_DEVICE_NAME:
length = DAP_GetTargetDeviceNameString((char *)info);
break;
case DAP_ID_BOARD_VENDOR:
length = DAP_GetTargetBoardVendorString((char *)info);
break;
case DAP_ID_BOARD_NAME:
length = DAP_GetTargetBoardNameString((char *)info);
break;
case DAP_ID_PRODUCT_FW_VER:
length = DAP_GetProductFirmwareVersionString((char *)info);
break;
case DAP_ID_CAPABILITIES:
info[0] = ((DAP_SWD != 0) ? (1U << 0) : 0U) |
((DAP_JTAG != 0) ? (1U << 1) : 0U) |
((SWO_UART != 0) ? (1U << 2) : 0U) |
((SWO_MANCHESTER != 0) ? (1U << 3) : 0U) |
/* Atomic Commands */ (1U << 4) |
((TIMESTAMP_CLOCK != 0U) ? (1U << 5) : 0U) |
((SWO_STREAM != 0U) ? (1U << 6) : 0U) |
((DAP_UART != 0U) ? (1U << 7) : 0U);
info[1] = ((DAP_UART_USB_COM_PORT != 0) ? (1U << 0) : 0U);
length = 2U;
break;
case DAP_ID_TIMESTAMP_CLOCK:
#if (TIMESTAMP_CLOCK != 0U)
info[0] = (uint8_t)(TIMESTAMP_CLOCK >> 0);
info[1] = (uint8_t)(TIMESTAMP_CLOCK >> 8);
info[2] = (uint8_t)(TIMESTAMP_CLOCK >> 16);
info[3] = (uint8_t)(TIMESTAMP_CLOCK >> 24);
length = 4U;
#endif
break;
case DAP_ID_UART_RX_BUFFER_SIZE:
#if (DAP_UART != 0)
info[0] = (uint8_t)(DAP_UART_RX_BUFFER_SIZE >> 0);
info[1] = (uint8_t)(DAP_UART_RX_BUFFER_SIZE >> 8);
info[2] = (uint8_t)(DAP_UART_RX_BUFFER_SIZE >> 16);
info[3] = (uint8_t)(DAP_UART_RX_BUFFER_SIZE >> 24);
length = 4U;
#endif
break;
case DAP_ID_UART_TX_BUFFER_SIZE:
#if (DAP_UART != 0)
info[0] = (uint8_t)(DAP_UART_TX_BUFFER_SIZE >> 0);
info[1] = (uint8_t)(DAP_UART_TX_BUFFER_SIZE >> 8);
info[2] = (uint8_t)(DAP_UART_TX_BUFFER_SIZE >> 16);
info[3] = (uint8_t)(DAP_UART_TX_BUFFER_SIZE >> 24);
length = 4U;
#endif
break;
case DAP_ID_SWO_BUFFER_SIZE:
#if ((SWO_UART != 0) || (SWO_MANCHESTER != 0))
info[0] = (uint8_t)(SWO_BUFFER_SIZE >> 0);
info[1] = (uint8_t)(SWO_BUFFER_SIZE >> 8);
info[2] = (uint8_t)(SWO_BUFFER_SIZE >> 16);
info[3] = (uint8_t)(SWO_BUFFER_SIZE >> 24);
length = 4U;
#endif
break;
case DAP_ID_PACKET_SIZE:
info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0);
info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8);
length = 2U;
break;
case DAP_ID_PACKET_COUNT:
info[0] = DAP_PACKET_COUNT;
length = 1U;
break;
default:
break;
}
return (length);
}
// Delay for specified time
// delay: delay time in ms
void Delayms(uint32_t delay) {
delay *= ((CPU_CLOCK/1000U) + (DELAY_SLOW_CYCLES-1U)) / DELAY_SLOW_CYCLES;
PIN_DELAY_SLOW(delay);
}
// Process Delay 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)
static uint32_t DAP_Delay(const uint8_t *request, uint8_t *response) {
uint32_t delay;
delay = (uint32_t)(*(request+0)) |
(uint32_t)(*(request+1) << 8);
delay *= ((CPU_CLOCK/1000000U) + (DELAY_SLOW_CYCLES-1U)) / DELAY_SLOW_CYCLES;
PIN_DELAY_SLOW(delay);
*response = DAP_OK;
return ((2U << 16) | 1U);
}
// Process Host 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)
static uint32_t DAP_HostStatus(const uint8_t *request, uint8_t *response) {
switch (*request) {
case DAP_DEBUGGER_CONNECTED:
LED_CONNECTED_OUT((*(request+1) & 1U));
break;
case DAP_TARGET_RUNNING:
LED_RUNNING_OUT((*(request+1) & 1U));
break;
default:
*response = DAP_ERROR;
return ((2U << 16) | 1U);
}
*response = DAP_OK;
return ((2U << 16) | 1U);
}
// Process Connect 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)
static uint32_t DAP_Connect(const uint8_t *request, uint8_t *response) {
uint32_t port;
if (*request == DAP_PORT_AUTODETECT) {
port = DAP_DEFAULT_PORT;
} else {
port = *request;
}
switch (port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
DAP_Data.debug_port = DAP_PORT_SWD;
PORT_SWD_SETUP();
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
DAP_Data.debug_port = DAP_PORT_JTAG;
PORT_JTAG_SETUP();
break;
#endif
default:
port = DAP_PORT_DISABLED;
break;
}
*response = (uint8_t)port;
return ((1U << 16) | 1U);
}
// Process Disconnect command and prepare response
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_Disconnect(uint8_t *response) {
DAP_Data.debug_port = DAP_PORT_DISABLED;
PORT_OFF();
*response = DAP_OK;
return (1U);
}
// Process Reset Target command and prepare response
// response: pointer to response data
// return: number of bytes in response
static uint32_t DAP_ResetTarget(uint8_t *response) {
*(response+1) = RESET_TARGET();
*(response+0) = DAP_OK;
return (2U);
}
// Process SWJ Pins 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)
static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) {
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
uint32_t value;
uint32_t select;
uint32_t wait;
uint32_t timestamp;
value = (uint32_t) *(request+0);
select = (uint32_t) *(request+1);
wait = (uint32_t)(*(request+2) << 0) |
(uint32_t)(*(request+3) << 8) |
(uint32_t)(*(request+4) << 16) |
(uint32_t)(*(request+5) << 24);
if ((select & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) {
if ((value & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) {
PIN_SWCLK_TCK_SET();
} else {
PIN_SWCLK_TCK_CLR();
}
}
if ((select & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) {
if ((value & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) {
PIN_SWDIO_TMS_SET();
} else {
PIN_SWDIO_TMS_CLR();
}
}
if ((select & (1U << DAP_SWJ_TDI)) != 0U) {
PIN_TDI_OUT(value >> DAP_SWJ_TDI);
}
if ((select & (1U << DAP_SWJ_nTRST)) != 0U) {
PIN_nTRST_OUT(value >> DAP_SWJ_nTRST);
}
if ((select & (1U << DAP_SWJ_nRESET)) != 0U){
PIN_nRESET_OUT(value >> DAP_SWJ_nRESET);
}
if (wait != 0U) {
#if (TIMESTAMP_CLOCK != 0U)
if (wait > 3000000U) {
wait = 3000000U;
}
#if (TIMESTAMP_CLOCK >= 1000000U)
wait *= TIMESTAMP_CLOCK / 1000000U;
#else
wait /= 1000000U / TIMESTAMP_CLOCK;
#endif
#else
wait = 1U;
#endif
timestamp = TIMESTAMP_GET();
do {
if ((select & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) {
if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) {
continue;
}
}
if ((select & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) {
if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) {
continue;
}
}
if ((select & (1U << DAP_SWJ_TDI)) != 0U) {
if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) {
continue;
}
}
if ((select & (1U << DAP_SWJ_nTRST)) != 0U) {
if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) {
continue;
}
}
if ((select & (1U << DAP_SWJ_nRESET)) != 0U) {
if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) {
continue;
}
}
break;
} while ((TIMESTAMP_GET() - timestamp) < wait);
}
value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) |
(PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) |
(PIN_TDI_IN() << DAP_SWJ_TDI) |
(PIN_TDO_IN() << DAP_SWJ_TDO) |
(PIN_nTRST_IN() << DAP_SWJ_nTRST) |
(PIN_nRESET_IN() << DAP_SWJ_nRESET);
*response = (uint8_t)value;
#else
*response = 0U;
#endif
return ((6U << 16) | 1U);
}
// Process SWJ Clock 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)
static uint32_t DAP_SWJ_Clock(const uint8_t *request, uint8_t *response) {
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
uint32_t clock;
uint32_t delay;
clock = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
if (clock == 0U) {
*response = DAP_ERROR;
return ((4U << 16) | 1U);
}
Set_Clock_Delay(clock);
*response = DAP_OK;
#else
*response = DAP_ERROR;
#endif
return ((4U << 16) | 1U);
}
// Process SWJ Sequence 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)
static uint32_t DAP_SWJ_Sequence(const uint8_t *request, uint8_t *response) {
uint32_t count;
count = *request++;
if (count == 0U) {
count = 256U;
}
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
SWJ_Sequence(count, request);
*response = DAP_OK;
#else
*response = DAP_ERROR;
#endif
count = (count + 7U) >> 3;
return (((count + 1U) << 16) | 1U);
}
// Process SWD 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)
static uint32_t DAP_SWD_Configure(const uint8_t *request, uint8_t *response) {
#if (DAP_SWD != 0)
uint8_t value;
value = *request;
DAP_Data.swd_conf.turnaround = (value & 0x03U) + 1U;
DAP_Data.swd_conf.data_phase = (value & 0x04U) ? 1U : 0U;
*response = DAP_OK;
#else
*response = DAP_ERROR;
#endif
return ((1U << 16) | 1U);
}
// Process SWD Sequence 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)
static uint32_t DAP_SWD_Sequence(const uint8_t *request, uint8_t *response) {
uint32_t sequence_info;
uint32_t sequence_count;
uint32_t request_count;
uint32_t response_count;
uint32_t count;
#if (DAP_SWD != 0)
*response++ = DAP_OK;
#else
*response++ = DAP_ERROR;
#endif
request_count = 1U;
response_count = 1U;
sequence_count = *request++;
while (sequence_count--) {
sequence_info = *request++;
count = sequence_info & SWD_SEQUENCE_CLK;
if (count == 0U) {
count = 64U;
}
count = (count + 7U) / 8U;
#if (DAP_SWD != 0)
if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) {
PIN_SWDIO_OUT_DISABLE();
} else {
PIN_SWDIO_OUT_ENABLE();
}
SWD_Sequence(sequence_info, request, response);
if (sequence_count == 0U) {
PIN_SWDIO_OUT_ENABLE();
}
#endif
if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) {
request_count++;
#if (DAP_SWD != 0)
response += count;
response_count += count;
#endif
} else {
request += count;
request_count += count + 1U;
}
}
return ((request_count << 16) | response_count);
}
// Process JTAG Sequence 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)
static uint32_t DAP_JTAG_Sequence(const uint8_t *request, uint8_t *response) {
uint32_t sequence_info;
uint32_t sequence_count;
uint32_t request_count;
uint32_t response_count;
uint32_t count;
#if (DAP_JTAG != 0)
*response++ = DAP_OK;
#else
*response++ = DAP_ERROR;
#endif
request_count = 1U;
response_count = 1U;
sequence_count = *request++;
while (sequence_count--) {
sequence_info = *request++;
count = sequence_info & JTAG_SEQUENCE_TCK;
if (count == 0U) {
count = 64U;
}
count = (count + 7U) / 8U;
#if (DAP_JTAG != 0)
JTAG_Sequence(sequence_info, request, response);
#endif
request += count;
request_count += count + 1U;
#if (DAP_JTAG != 0)
if ((sequence_info & JTAG_SEQUENCE_TDO) != 0U) {
response += count;
response_count += count;
}
#endif
}
return ((request_count << 16) | response_count);
}
// Process JTAG 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)
static uint32_t DAP_JTAG_Configure(const uint8_t *request, uint8_t *response) {
uint32_t count;
#if (DAP_JTAG != 0)
uint32_t length;
uint32_t bits;
uint32_t n;
count = *request++;
DAP_Data.jtag_dev.count = (uint8_t)count;
bits = 0U;
for (n = 0U; n < count; n++) {
length = *request++;
DAP_Data.jtag_dev.ir_length[n] = (uint8_t)length;
DAP_Data.jtag_dev.ir_before[n] = (uint16_t)bits;
bits += length;
}
for (n = 0U; n < count; n++) {
bits -= DAP_Data.jtag_dev.ir_length[n];
DAP_Data.jtag_dev.ir_after[n] = (uint16_t)bits;
}
*response = DAP_OK;
#else
count = *request;
*response = DAP_ERROR;
#endif
return (((count + 1U) << 16) | 1U);
}
// Process JTAG IDCODE 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)
static uint32_t DAP_JTAG_IDCode(const uint8_t *request, uint8_t *response) {
#if (DAP_JTAG != 0)
uint32_t data;
if (DAP_Data.debug_port != DAP_PORT_JTAG) {
goto id_error;
}
// Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
goto id_error;
}
// Select JTAG chain
JTAG_IR(JTAG_IDCODE);
// Read IDCODE register
data = JTAG_ReadIDCode();
// Store Data
*(response+0) = DAP_OK;
*(response+1) = (uint8_t)(data >> 0);
*(response+2) = (uint8_t)(data >> 8);
*(response+3) = (uint8_t)(data >> 16);
*(response+4) = (uint8_t)(data >> 24);
return ((1U << 16) | 5U);
id_error:
#endif
*response = DAP_ERROR;
return ((1U << 16) | 1U);
}
// Process Transfer 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)
static uint32_t DAP_TransferConfigure(const uint8_t *request, uint8_t *response) {
DAP_Data.transfer.idle_cycles = *(request+0);
DAP_Data.transfer.retry_count = (uint16_t) *(request+1) |
(uint16_t)(*(request+2) << 8);
DAP_Data.transfer.match_retry = (uint16_t) *(request+3) |
(uint16_t)(*(request+4) << 8);
*response = DAP_OK;
return ((5U << 16) | 1U);
}
// Process SWD 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)
#if (DAP_SWD != 0)
static uint32_t DAP_SWD_Transfer(const uint8_t *request, uint8_t *response) {
const
uint8_t *request_head;
uint32_t request_count;
uint32_t request_value;
uint8_t *response_head;
uint32_t response_count;
uint32_t response_value;
uint32_t post_read;
uint32_t check_write;
uint32_t match_value;
uint32_t match_retry;
uint32_t retry;
uint32_t data;
#if (TIMESTAMP_CLOCK != 0U)
uint32_t timestamp;
#endif
request_head = request;
response_count = 0U;
response_value = 0U;
response_head = response;
response += 2;
DAP_TransferAbort = 0U;
post_read = 0U;
check_write = 0U;
request++; // Ignore DAP index
request_count = *request++;
for (; request_count != 0U; request_count--) {
request_value = *request++;
if ((request_value & DAP_TRANSFER_RnW) != 0U) {
// Read register
if (post_read) {
// Read was posted before
retry = DAP_Data.transfer.retry_count;
if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) {
// Read previous AP data and post next AP read
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
} else {
// Read previous AP data
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
post_read = 0U;
}
if (response_value != DAP_TRANSFER_OK) {
break;
}
// Store previous AP data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
#if (TIMESTAMP_CLOCK != 0U)
if (post_read) {
// Store Timestamp of next AP read
if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) {
timestamp = DAP_Data.timestamp;
*response++ = (uint8_t) timestamp;
*response++ = (uint8_t)(timestamp >> 8);
*response++ = (uint8_t)(timestamp >> 16);
*response++ = (uint8_t)(timestamp >> 24);
}
}
#endif
}
if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) {
// Read with value match
match_value = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
request += 4;
match_retry = DAP_Data.transfer.match_retry;
if ((request_value & DAP_TRANSFER_APnDP) != 0U) {
// Post AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
}
do {
// Read register until its value matches or retry counter expires
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
} while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort);
if ((data & DAP_Data.transfer.match_mask) != match_value) {
response_value |= DAP_TRANSFER_MISMATCH;
}
if (response_value != DAP_TRANSFER_OK) {
break;
}
} else {
// Normal read
retry = DAP_Data.transfer.retry_count;
if ((request_value & DAP_TRANSFER_APnDP) != 0U) {
// Read AP register
if (post_read == 0U) {
// Post AP read
do {
response_value = SWD_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
#if (TIMESTAMP_CLOCK != 0U)
// Store Timestamp
if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) {
timestamp = DAP_Data.timestamp;
*response++ = (uint8_t) timestamp;
*response++ = (uint8_t)(timestamp >> 8);
*response++ = (uint8_t)(timestamp >> 16);
*response++ = (uint8_t)(timestamp >> 24);
}
#endif
post_read = 1U;
}
} else {
// Read DP register
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
#if (TIMESTAMP_CLOCK != 0U)
// Store Timestamp
if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) {
timestamp = DAP_Data.timestamp;
*response++ = (uint8_t) timestamp;
*response++ = (uint8_t)(timestamp >> 8);
*response++ = (uint8_t)(timestamp >> 16);
*response++ = (uint8_t)(timestamp >> 24);
}
#endif
// Store data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
}
}
check_write = 0U;
} else {
// Write register
if (post_read) {
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
post_read = 0U;
}
// Load data
data = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
request += 4;
if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) {
// Write match mask
DAP_Data.transfer.match_mask = data;
response_value = DAP_TRANSFER_OK;
} else {
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
#if (TIMESTAMP_CLOCK != 0U)
// Store Timestamp
if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) {
timestamp = DAP_Data.timestamp;
*response++ = (uint8_t) timestamp;
*response++ = (uint8_t)(timestamp >> 8);
*response++ = (uint8_t)(timestamp >> 16);
*response++ = (uint8_t)(timestamp >> 24);
}
#endif
check_write = 1U;
}
}
response_count++;
if (DAP_TransferAbort) {
break;
}
}
for (; request_count != 0U; request_count--) {
// Process canceled requests
request_value = *request++;
if ((request_value & DAP_TRANSFER_RnW) != 0U) {
// Read register
if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) {
// Read with value match
request += 4;
}
} else {
// Write register
request += 4;
}
}
if (response_value == DAP_TRANSFER_OK) {
if (post_read) {
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
} else if (check_write) {
// Check last write
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
}
}
end:
*(response_head+0) = (uint8_t)response_count;
*(response_head+1) = (uint8_t)response_value;
return (((uint32_t)(request - request_head) << 16) | (uint32_t)(response - response_head));
}
#endif
// Process JTAG 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)
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_Transfer(const uint8_t *request, uint8_t *response) {
const
uint8_t *request_head;
uint32_t request_count;
uint32_t request_value;
uint32_t request_ir;
uint8_t *response_head;
uint32_t response_count;
uint32_t response_value;
uint32_t post_read;
uint32_t match_value;
uint32_t match_retry;
uint32_t retry;
uint32_t data;
uint32_t ir;
#if (TIMESTAMP_CLOCK != 0U)
uint32_t timestamp;
#endif
request_head = request;
response_count = 0U;
response_value = 0U;
response_head = response;
response += 2;
DAP_TransferAbort = 0U;
ir = 0U;
post_read = 0U;
// Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request++;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
goto end;
}
request_count = *request++;
for (; request_count != 0U; request_count--) {
request_value = *request++;
request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC;
if ((request_value & DAP_TRANSFER_RnW) != 0U) {
// Read register
if (post_read) {
// Read was posted before
retry = DAP_Data.transfer.retry_count;
if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == 0U)) {
// Read previous data and post next read
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
} else {
// Select JTAG chain
if (ir != JTAG_DPACC) {
ir = JTAG_DPACC;
JTAG_IR(ir);
}
// Read previous data
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
post_read = 0U;
}
if (response_value != DAP_TRANSFER_OK) {
break;
}
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
#if (TIMESTAMP_CLOCK != 0U)
if (post_read) {
// Store Timestamp of next AP read
if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) {
timestamp = DAP_Data.timestamp;
*response++ = (uint8_t) timestamp;
*response++ = (uint8_t)(timestamp >> 8);
*response++ = (uint8_t)(timestamp >> 16);
*response++ = (uint8_t)(timestamp >> 24);
}
}
#endif
}
if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) {
// Read with value match
match_value = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
request += 4;
match_retry = DAP_Data.transfer.match_retry;
// Select JTAG chain
if (ir != request_ir) {
ir = request_ir;
JTAG_IR(ir);
}
// Post DP/AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
do {
// Read register until its value matches or retry counter expires
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
} while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort);
if ((data & DAP_Data.transfer.match_mask) != match_value) {
response_value |= DAP_TRANSFER_MISMATCH;
}
if (response_value != DAP_TRANSFER_OK) {
break;
}
} else {
// Normal read
if (post_read == 0U) {
// Select JTAG chain
if (ir != request_ir) {
ir = request_ir;
JTAG_IR(ir);
}
// Post DP/AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
#if (TIMESTAMP_CLOCK != 0U)
// Store Timestamp
if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) {
timestamp = DAP_Data.timestamp;
*response++ = (uint8_t) timestamp;
*response++ = (uint8_t)(timestamp >> 8);
*response++ = (uint8_t)(timestamp >> 16);
*response++ = (uint8_t)(timestamp >> 24);
}
#endif
post_read = 1U;
}
}
} else {
// Write register
if (post_read) {
// Select JTAG chain
if (ir != JTAG_DPACC) {
ir = JTAG_DPACC;
JTAG_IR(ir);
}
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
post_read = 0U;
}
// Load data
data = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
request += 4;
if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) {
// Write match mask
DAP_Data.transfer.match_mask = data;
response_value = DAP_TRANSFER_OK;
} else {
// Select JTAG chain
if (ir != request_ir) {
ir = request_ir;
JTAG_IR(ir);
}
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
break;
}
#if (TIMESTAMP_CLOCK != 0U)
// Store Timestamp
if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) {
timestamp = DAP_Data.timestamp;
*response++ = (uint8_t) timestamp;
*response++ = (uint8_t)(timestamp >> 8);
*response++ = (uint8_t)(timestamp >> 16);
*response++ = (uint8_t)(timestamp >> 24);
}
#endif
}
}
response_count++;
if (DAP_TransferAbort) {
break;
}
}
for (; request_count != 0U; request_count--) {
// Process canceled requests
request_value = *request++;
if ((request_value & DAP_TRANSFER_RnW) != 0U) {
// Read register
if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) {
// Read with value match
request += 4;
}
} else {
// Write register
request += 4;
}
}
if (response_value == DAP_TRANSFER_OK) {
// Select JTAG chain
if (ir != JTAG_DPACC) {
ir = JTAG_DPACC;
JTAG_IR(ir);
}
if (post_read) {
// Read previous data
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
// Store previous data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
} else {
// Check last write
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
}
}
end:
*(response_head+0) = (uint8_t)response_count;
*(response_head+1) = (uint8_t)response_value;
return (((uint32_t)(request - request_head) << 16) | (uint32_t)(response - response_head));
}
#endif
// Process Dummy 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)
static uint32_t DAP_Dummy_Transfer(const uint8_t *request, uint8_t *response) {
const
uint8_t *request_head;
uint32_t request_count;
uint32_t request_value;
request_head = request;
request++; // Ignore DAP index
request_count = *request++;
for (; request_count != 0U; request_count--) {
// Process dummy requests
request_value = *request++;
if ((request_value & DAP_TRANSFER_RnW) != 0U) {
// Read register
if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) {
// Read with value match
request += 4;
}
} else {
// Write register
request += 4;
}
}
*(response+0) = 0U; // Response count
*(response+1) = 0U; // Response value
return (((uint32_t)(request - request_head) << 16) | 2U);
}
// Process 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)
static uint32_t DAP_Transfer(const uint8_t *request, uint8_t *response) {
uint32_t num;
switch (DAP_Data.debug_port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
num = DAP_SWD_Transfer(request, response);
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
num = DAP_JTAG_Transfer(request, response);
break;
#endif
default:
num = DAP_Dummy_Transfer(request, response);
break;
}
return (num);
}
// Process SWD Transfer Block command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_SWD != 0)
static uint32_t DAP_SWD_TransferBlock(const uint8_t *request, uint8_t *response) {
uint32_t request_count;
uint32_t request_value;
uint32_t response_count;
uint32_t response_value;
uint8_t *response_head;
uint32_t retry;
uint32_t data;
response_count = 0U;
response_value = 0U;
response_head = response;
response += 3;
DAP_TransferAbort = 0U;
request++; // Ignore DAP index
request_count = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8);
request += 2;
if (request_count == 0U) {
goto end;
}
request_value = *request++;
if ((request_value & DAP_TRANSFER_RnW) != 0U) {
// Read register block
if ((request_value & DAP_TRANSFER_APnDP) != 0U) {
// Post AP read
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
}
while (request_count--) {
// Read DP/AP register
if ((request_count == 0U) && ((request_value & DAP_TRANSFER_APnDP) != 0U)) {
// Last AP read
request_value = DP_RDBUFF | DAP_TRANSFER_RnW;
}
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
// Store data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
response_count++;
}
} else {
// Write register block
while (request_count--) {
// Load data
data = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
request += 4;
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
response_count++;
}
// Check last write
retry = DAP_Data.transfer.retry_count;
do {
response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
}
end:
*(response_head+0) = (uint8_t)(response_count >> 0);
*(response_head+1) = (uint8_t)(response_count >> 8);
*(response_head+2) = (uint8_t) response_value;
return ((uint32_t)(response - response_head));
}
#endif
// Process JTAG Transfer Block command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_TransferBlock(const uint8_t *request, uint8_t *response) {
uint32_t request_count;
uint32_t request_value;
uint32_t response_count;
uint32_t response_value;
uint8_t *response_head;
uint32_t retry;
uint32_t data;
uint32_t ir;
response_count = 0U;
response_value = 0U;
response_head = response;
response += 3;
DAP_TransferAbort = 0U;
// Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request++;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
goto end;
}
request_count = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8);
request += 2;
if (request_count == 0U) {
goto end;
}
request_value = *request++;
// Select JTAG chain
ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC;
JTAG_IR(ir);
if ((request_value & DAP_TRANSFER_RnW) != 0U) {
// Post read
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
// Read register block
while (request_count--) {
// Read DP/AP register
if (request_count == 0U) {
// Last read
if (ir != JTAG_DPACC) {
JTAG_IR(JTAG_DPACC);
}
request_value = DP_RDBUFF | DAP_TRANSFER_RnW;
}
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
// Store data
*response++ = (uint8_t) data;
*response++ = (uint8_t)(data >> 8);
*response++ = (uint8_t)(data >> 16);
*response++ = (uint8_t)(data >> 24);
response_count++;
}
} else {
// Write register block
while (request_count--) {
// Load data
data = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
request += 4;
// Write DP/AP register
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(request_value, &data);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
if (response_value != DAP_TRANSFER_OK) {
goto end;
}
response_count++;
}
// Check last write
if (ir != JTAG_DPACC) {
JTAG_IR(JTAG_DPACC);
}
retry = DAP_Data.transfer.retry_count;
do {
response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL);
} while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort);
}
end:
*(response_head+0) = (uint8_t)(response_count >> 0);
*(response_head+1) = (uint8_t)(response_count >> 8);
*(response_head+2) = (uint8_t) response_value;
return ((uint32_t)(response - response_head));
}
#endif
// Process Transfer Block 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)
static uint32_t DAP_TransferBlock(const uint8_t *request, uint8_t *response) {
uint32_t num;
switch (DAP_Data.debug_port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
num = DAP_SWD_TransferBlock (request, response);
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
num = DAP_JTAG_TransferBlock(request, response);
break;
#endif
default:
*(response+0) = 0U; // Response count [7:0]
*(response+1) = 0U; // Response count[15:8]
*(response+2) = 0U; // Response value
num = 3U;
break;
}
if ((*(request+3) & DAP_TRANSFER_RnW) != 0U) {
// Read register block
num |= 4U << 16;
} else {
// Write register block
num |= (4U + (((uint32_t)(*(request+1)) | (uint32_t)(*(request+2) << 8)) * 4)) << 16;
}
return (num);
}
// Process SWD Write ABORT command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_SWD != 0)
static uint32_t DAP_SWD_WriteAbort(const uint8_t *request, uint8_t *response) {
uint32_t data;
// Load data (Ignore DAP index)
data = (uint32_t)(*(request+1) << 0) |
(uint32_t)(*(request+2) << 8) |
(uint32_t)(*(request+3) << 16) |
(uint32_t)(*(request+4) << 24);
// Write Abort register
SWD_Transfer(DP_ABORT, &data);
*response = DAP_OK;
return (1U);
}
#endif
// Process JTAG Write ABORT command and prepare response
// request: pointer to request data
// response: pointer to response data
// return: number of bytes in response
#if (DAP_JTAG != 0)
static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) {
uint32_t data;
// Device index (JTAP TAP)
DAP_Data.jtag_dev.index = *request;
if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) {
*response = DAP_ERROR;
return (1U);
}
// Select JTAG chain
JTAG_IR(JTAG_ABORT);
// Load data
data = (uint32_t)(*(request+1) << 0) |
(uint32_t)(*(request+2) << 8) |
(uint32_t)(*(request+3) << 16) |
(uint32_t)(*(request+4) << 24);
// Write Abort register
JTAG_WriteAbort(data);
*response = DAP_OK;
return (1U);
}
#endif
// Process Write ABORT 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)
static uint32_t DAP_WriteAbort(const uint8_t *request, uint8_t *response) {
uint32_t num;
switch (DAP_Data.debug_port) {
#if (DAP_SWD != 0)
case DAP_PORT_SWD:
num = DAP_SWD_WriteAbort (request, response);
break;
#endif
#if (DAP_JTAG != 0)
case DAP_PORT_JTAG:
num = DAP_JTAG_WriteAbort(request, response);
break;
#endif
default:
*response = DAP_ERROR;
num = 1U;
break;
}
return ((5U << 16) | num);
}
// Process DAP Vendor command request and prepare response
// Default function (can be overridden)
// 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)
__WEAK uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) {
(void)request;
*response = ID_DAP_Invalid;
return ((1U << 16) | 1U);
}
// Process DAP command request 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 DAP_ProcessCommand(const uint8_t *request, uint8_t *response) {
uint32_t num;
if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) {
return DAP_ProcessVendorCommand(request, response);
}
*response++ = *request;
switch (*request++) {
case ID_DAP_Info:
num = DAP_Info(*request, response+1);
*response = (uint8_t)num;
return ((2U << 16) + 2U + num);
case ID_DAP_HostStatus:
num = DAP_HostStatus(request, response);
break;
case ID_DAP_Connect:
num = DAP_Connect(request, response);
break;
case ID_DAP_Disconnect:
num = DAP_Disconnect(response);
break;
case ID_DAP_Delay:
num = DAP_Delay(request, response);
break;
case ID_DAP_ResetTarget:
num = DAP_ResetTarget(response);
break;
case ID_DAP_SWJ_Pins:
num = DAP_SWJ_Pins(request, response);
break;
case ID_DAP_SWJ_Clock:
num = DAP_SWJ_Clock(request, response);
break;
case ID_DAP_SWJ_Sequence:
num = DAP_SWJ_Sequence(request, response);
break;
case ID_DAP_SWD_Configure:
num = DAP_SWD_Configure(request, response);
break;
case ID_DAP_SWD_Sequence:
num = DAP_SWD_Sequence(request, response);
break;
case ID_DAP_JTAG_Sequence:
num = DAP_JTAG_Sequence(request, response);
break;
case ID_DAP_JTAG_Configure:
num = DAP_JTAG_Configure(request, response);
break;
case ID_DAP_JTAG_IDCODE:
num = DAP_JTAG_IDCode(request, response);
break;
case ID_DAP_TransferConfigure:
num = DAP_TransferConfigure(request, response);
break;
case ID_DAP_Transfer:
num = DAP_Transfer(request, response);
break;
case ID_DAP_TransferBlock:
num = DAP_TransferBlock(request, response);
break;
case ID_DAP_WriteABORT:
num = DAP_WriteAbort(request, response);
break;
#if ((SWO_UART != 0) || (SWO_MANCHESTER != 0))
case ID_DAP_SWO_Transport:
num = SWO_Transport(request, response);
break;
case ID_DAP_SWO_Mode:
num = SWO_Mode(request, response);
break;
case ID_DAP_SWO_Baudrate:
num = SWO_Baudrate(request, response);
break;
case ID_DAP_SWO_Control:
num = SWO_Control(request, response);
break;
case ID_DAP_SWO_Status:
num = SWO_Status(response);
break;
case ID_DAP_SWO_ExtendedStatus:
num = SWO_ExtendedStatus(request, response);
break;
case ID_DAP_SWO_Data:
num = SWO_Data(request, response);
break;
#endif
#if (DAP_UART != 0)
case ID_DAP_UART_Transport:
num = UART_Transport(request, response);
break;
case ID_DAP_UART_Configure:
num = UART_Configure(request, response);
break;
case ID_DAP_UART_Control:
num = UART_Control(request, response);
break;
case ID_DAP_UART_Status:
num = UART_Status(response);
break;
case ID_DAP_UART_Transfer:
num = UART_Transfer(request, response);
break;
#endif
default:
*(response-1) = ID_DAP_Invalid;
return ((1U << 16) | 1U);
}
return ((1U << 16) + 1U + num);
}
// Execute DAP command (process request 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 DAP_ExecuteCommand(const uint8_t *request, uint8_t *response) {
uint32_t cnt, num, n;
if (*request == ID_DAP_ExecuteCommands) {
*response++ = *request++;
cnt = *request++;
*response++ = (uint8_t)cnt;
num = (2U << 16) | 2U;
while (cnt--) {
n = DAP_ProcessCommand(request, response);
num += n;
request += (uint16_t)(n >> 16);
response += (uint16_t) n;
}
return (num);
}
return DAP_ProcessCommand(request, response);
}
// Setup DAP
void DAP_Setup(void) {
// Default settings
DAP_Data.debug_port = 0U;
DAP_Data.transfer.idle_cycles = 0U;
DAP_Data.transfer.retry_count = 100U;
DAP_Data.transfer.match_retry = 0U;
DAP_Data.transfer.match_mask = 0x00000000U;
#if (DAP_SWD != 0)
DAP_Data.swd_conf.turnaround = 1U;
DAP_Data.swd_conf.data_phase = 0U;
#endif
#if (DAP_JTAG != 0)
DAP_Data.jtag_dev.count = 0U;
#endif
// Sets DAP_Data.fast_clock and DAP_Data.clock_delay.
Set_Clock_Delay(DAP_DEFAULT_SWJ_CLOCK);
DAP_SETUP(); // Device specific setup
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2013-2017 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. December 2017
* $Revision: V2.0.0
*
* Project: CMSIS-DAP Source
* Title: DAP_vendor.c CMSIS-DAP Vendor Commands
*
*---------------------------------------------------------------------------*/
#include "DAP_config.h"
#include "DAP.h"
//**************************************************************************************************
/**
\defgroup DAP_Vendor_Adapt_gr Adapt Vendor Commands
\ingroup DAP_Vendor_gr
@{
The file DAP_vendor.c provides template source code for extension of a Debug Unit with
Vendor Commands. Copy this file to the project folder of the Debug Unit and add the
file to the MDK-ARM project under the file group Configuration.
*/
/** Process DAP Vendor Command and prepare Response Data
\param request pointer to request data
\param response pointer to response data
\return number of bytes in response (lower 16 bits)
number of bytes in request (upper 16 bits)
*/
uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) {
uint32_t num = (1U << 16) | 1U;
*response++ = *request; // copy Command ID
switch (*request++) { // first byte in request is Command ID
case ID_DAP_Vendor0:
#if 0 // example user command
num += 1U << 16; // increment request count
if (*request == 1U) { // when first command data byte is 1
*response++ = 'X'; // send 'X' as response
num++; // increment response count
}
#endif
break;
case ID_DAP_Vendor1: break;
case ID_DAP_Vendor2: break;
case ID_DAP_Vendor3: break;
case ID_DAP_Vendor4: break;
case ID_DAP_Vendor5: break;
case ID_DAP_Vendor6: break;
case ID_DAP_Vendor7: break;
case ID_DAP_Vendor8: break;
case ID_DAP_Vendor9: break;
case ID_DAP_Vendor10: break;
case ID_DAP_Vendor11: break;
case ID_DAP_Vendor12: break;
case ID_DAP_Vendor13: break;
case ID_DAP_Vendor14: break;
case ID_DAP_Vendor15: break;
case ID_DAP_Vendor16: break;
case ID_DAP_Vendor17: break;
case ID_DAP_Vendor18: break;
case ID_DAP_Vendor19: break;
case ID_DAP_Vendor20: break;
case ID_DAP_Vendor21: break;
case ID_DAP_Vendor22: break;
case ID_DAP_Vendor23: break;
case ID_DAP_Vendor24: break;
case ID_DAP_Vendor25: break;
case ID_DAP_Vendor26: break;
case ID_DAP_Vendor27: break;
case ID_DAP_Vendor28: break;
case ID_DAP_Vendor29: break;
case ID_DAP_Vendor30: break;
case ID_DAP_Vendor31: break;
}
return (num);
}
///@}

View File

@@ -0,0 +1,370 @@
/*
* Copyright (c) 2013-2017 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. December 2017
* $Revision: V2.0.0
*
* Project: CMSIS-DAP Source
* Title: JTAG_DP.c CMSIS-DAP JTAG DP I/O
*
*---------------------------------------------------------------------------*/
#include "DAP_config.h"
#include "DAP.h"
// JTAG Macros
#define PIN_TCK_SET PIN_SWCLK_TCK_SET
#define PIN_TCK_CLR PIN_SWCLK_TCK_CLR
#define PIN_TMS_SET PIN_SWDIO_TMS_SET
#define PIN_TMS_CLR PIN_SWDIO_TMS_CLR
#define JTAG_CYCLE_TCK() \
PIN_TCK_CLR(); \
PIN_DELAY(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define JTAG_CYCLE_TDI(tdi) \
PIN_TDI_OUT(tdi); \
PIN_TCK_CLR(); \
PIN_DELAY(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define JTAG_CYCLE_TDO(tdo) \
PIN_TCK_CLR(); \
PIN_DELAY(); \
tdo = PIN_TDO_IN(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define JTAG_CYCLE_TDIO(tdi,tdo) \
PIN_TDI_OUT(tdi); \
PIN_TCK_CLR(); \
PIN_DELAY(); \
tdo = PIN_TDO_IN(); \
PIN_TCK_SET(); \
PIN_DELAY()
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
#if (DAP_JTAG != 0)
// Generate JTAG Sequence
// info: sequence information
// tdi: pointer to TDI generated data
// tdo: pointer to TDO captured data
// return: none
void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo) {
uint32_t i_val;
uint32_t o_val;
uint32_t bit;
uint32_t n, k;
n = info & JTAG_SEQUENCE_TCK;
if (n == 0U) {
n = 64U;
}
if (info & JTAG_SEQUENCE_TMS) {
PIN_TMS_SET();
} else {
PIN_TMS_CLR();
}
while (n) {
i_val = *tdi++;
o_val = 0U;
for (k = 8U; k && n; k--, n--) {
JTAG_CYCLE_TDIO(i_val, bit);
i_val >>= 1;
o_val >>= 1;
o_val |= bit << 7;
}
o_val >>= k;
if (info & JTAG_SEQUENCE_TDO) {
*tdo++ = (uint8_t)o_val;
}
}
}
// JTAG Set IR
// ir: IR value
// return: none
#define JTAG_IR_Function(speed) /**/ \
static void JTAG_IR_##speed (uint32_t ir) { \
uint32_t n; \
\
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \
JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Capture-IR */ \
JTAG_CYCLE_TCK(); /* Shift-IR */ \
\
PIN_TDI_OUT(1U); \
for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass before data */ \
} \
for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1U; n; n--) { \
JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \
ir >>= 1; \
} \
n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \
if (n) { \
JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \
PIN_TDI_OUT(1U); \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \
} \
\
JTAG_CYCLE_TCK(); /* Update-IR */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Idle */ \
PIN_TDI_OUT(1U); \
}
// JTAG Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
#define JTAG_TransferFunction(speed) /**/ \
static uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \
uint32_t ack; \
uint32_t bit; \
uint32_t val; \
uint32_t n; \
\
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Capture-DR */ \
JTAG_CYCLE_TCK(); /* Shift-DR */ \
\
for (n = DAP_Data.jtag_dev.index; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass before data */ \
} \
\
JTAG_CYCLE_TDIO(request >> 1, bit); /* Set RnW, Get ACK.0 */ \
ack = bit << 1; \
JTAG_CYCLE_TDIO(request >> 2, bit); /* Set A2, Get ACK.1 */ \
ack |= bit << 0; \
JTAG_CYCLE_TDIO(request >> 3, bit); /* Set A3, Get ACK.2 */ \
ack |= bit << 2; \
\
if (ack != DAP_TRANSFER_OK) { \
/* Exit on error */ \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Exit1-DR */ \
goto exit; \
} \
\
if (request & DAP_TRANSFER_RnW) { \
/* Read Transfer */ \
val = 0U; \
for (n = 31U; n; n--) { \
JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \
val |= bit << 31; \
val >>= 1; \
} \
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \
if (n) { \
JTAG_CYCLE_TDO(bit); /* Get D31 */ \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \
} \
val |= bit << 31; \
if (data) { *data = val; } \
} else { \
/* Write Transfer */ \
val = *data; \
for (n = 31U; n; n--) { \
JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \
val >>= 1; \
} \
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U; \
if (n) { \
JTAG_CYCLE_TDI(val); /* Set D31 */ \
for (--n; n; n--) { \
JTAG_CYCLE_TCK(); /* Bypass after data */ \
} \
PIN_TMS_SET(); \
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \
} else { \
PIN_TMS_SET(); \
JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \
} \
} \
\
exit: \
JTAG_CYCLE_TCK(); /* Update-DR */ \
PIN_TMS_CLR(); \
JTAG_CYCLE_TCK(); /* Idle */ \
PIN_TDI_OUT(1U); \
\
/* Capture Timestamp */ \
if (request & DAP_TRANSFER_TIMESTAMP) { \
DAP_Data.timestamp = TIMESTAMP_GET(); \
} \
\
/* Idle cycles */ \
n = DAP_Data.transfer.idle_cycles; \
while (n--) { \
JTAG_CYCLE_TCK(); /* Idle */ \
} \
\
return ((uint8_t)ack); \
}
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_FAST()
JTAG_IR_Function(Fast)
JTAG_TransferFunction(Fast)
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
JTAG_IR_Function(Slow)
JTAG_TransferFunction(Slow)
// JTAG Read IDCODE register
// return: value read
uint32_t JTAG_ReadIDCode (void) {
uint32_t bit;
uint32_t val;
uint32_t n;
PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Select-DR-Scan */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Capture-DR */
JTAG_CYCLE_TCK(); /* Shift-DR */
for (n = DAP_Data.jtag_dev.index; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass before data */
}
val = 0U;
for (n = 31U; n; n--) {
JTAG_CYCLE_TDO(bit); /* Get D0..D30 */
val |= bit << 31;
val >>= 1;
}
PIN_TMS_SET();
JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */
val |= bit << 31;
JTAG_CYCLE_TCK(); /* Update-DR */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Idle */
return (val);
}
// JTAG Write ABORT register
// data: value to write
// return: none
void JTAG_WriteAbort (uint32_t data) {
uint32_t n;
PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Select-DR-Scan */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Capture-DR */
JTAG_CYCLE_TCK(); /* Shift-DR */
for (n = DAP_Data.jtag_dev.index; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass before data */
}
PIN_TDI_OUT(0U);
JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */
JTAG_CYCLE_TCK(); /* Set A2=0 */
JTAG_CYCLE_TCK(); /* Set A3=0 */
for (n = 31U; n; n--) {
JTAG_CYCLE_TDI(data); /* Set D0..D30 */
data >>= 1;
}
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U;
if (n) {
JTAG_CYCLE_TDI(data); /* Set D31 */
for (--n; n; n--) {
JTAG_CYCLE_TCK(); /* Bypass after data */
}
PIN_TMS_SET();
JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */
} else {
PIN_TMS_SET();
JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */
}
JTAG_CYCLE_TCK(); /* Update-DR */
PIN_TMS_CLR();
JTAG_CYCLE_TCK(); /* Idle */
PIN_TDI_OUT(1U);
}
// JTAG Set IR
// ir: IR value
// return: none
void JTAG_IR (uint32_t ir) {
if (DAP_Data.fast_clock) {
JTAG_IR_Fast(ir);
} else {
JTAG_IR_Slow(ir);
}
}
// JTAG Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) {
if (DAP_Data.fast_clock) {
return JTAG_TransferFast(request, data);
} else {
return JTAG_TransferSlow(request, data);
}
}
#endif /* (DAP_JTAG != 0) */

View File

@@ -0,0 +1,798 @@
/*
* Copyright (c) 2013-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: 29. March 2021
* $Revision: V2.0.1
*
* Project: CMSIS-DAP Source
* Title: SWO.c CMSIS-DAP SWO I/O
*
*---------------------------------------------------------------------------*/
#include "DAP_config.h"
#include "DAP.h"
#if (SWO_UART != 0)
#include "Driver_USART.h"
#endif
#if (SWO_STREAM != 0)
#include "cmsis_os2.h"
#define osObjectsExternal
#include "osObjects.h"
#endif
#if (SWO_STREAM != 0)
#ifdef DAP_FW_V1
#error "SWO Streaming Trace not supported in DAP V1!"
#endif
#endif
#if (SWO_UART != 0)
// USART Driver
#define _USART_Driver_(n) Driver_USART##n
#define USART_Driver_(n) _USART_Driver_(n)
extern ARM_DRIVER_USART USART_Driver_(SWO_UART_DRIVER);
#define pUSART (&USART_Driver_(SWO_UART_DRIVER))
static uint8_t USART_Ready = 0U;
#endif /* (SWO_UART != 0) */
#if ((SWO_UART != 0) || (SWO_MANCHESTER != 0))
#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) */
// Trace State
static uint8_t TraceTransport = 0U; /* Trace Transport */
static uint8_t TraceMode = 0U; /* Trace Mode */
static uint8_t TraceStatus = 0U; /* Trace Status without Errors */
static uint8_t TraceError[2] = {0U, 0U}; /* Trace Error flags (banked) */
static uint8_t TraceError_n = 0U; /* Active Trace Error bank */
// Trace Buffer
static uint8_t TraceBuf[SWO_BUFFER_SIZE]; /* Trace Buffer (must be 2^n) */
static volatile uint32_t TraceIndexI = 0U; /* Incoming Trace Index */
static volatile uint32_t TraceIndexO = 0U; /* Outgoing Trace Index */
static volatile uint8_t TraceUpdate; /* Trace Update Flag */
static uint32_t TraceBlockSize; /* Current Trace Block Size */
#if (TIMESTAMP_CLOCK != 0U)
// Trace Timestamp
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);
#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
#if (SWO_UART != 0)
// USART Driver Callback function
// event: event mask
static void USART_Callback (uint32_t event) {
uint32_t index_i;
uint32_t index_o;
uint32_t count;
uint32_t num;
if (event & ARM_USART_EVENT_RECEIVE_COMPLETE) {
#if (TIMESTAMP_CLOCK != 0U)
TraceTimestamp.tick = TIMESTAMP_GET();
#endif
index_o = TraceIndexO;
index_i = TraceIndexI;
index_i += TraceBlockSize;
TraceIndexI = index_i;
#if (TIMESTAMP_CLOCK != 0U)
TraceTimestamp.index = index_i;
#endif
num = TRACE_BLOCK_SIZE - (index_i & (TRACE_BLOCK_SIZE - 1U));
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);
}
}
#endif
}
if (event & ARM_USART_EVENT_RX_OVERFLOW) {
SetTraceError(DAP_SWO_BUFFER_OVERRUN);
}
if (event & (ARM_USART_EVENT_RX_BREAK |
ARM_USART_EVENT_RX_FRAMING_ERROR |
ARM_USART_EVENT_RX_PARITY_ERROR)) {
SetTraceError(DAP_SWO_STREAM_ERROR);
}
}
// Enable or disable SWO Mode (UART)
// enable: enable flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t SWO_Mode_UART (uint32_t enable) {
int32_t status;
USART_Ready = 0U;
if (enable != 0U) {
status = pUSART->Initialize(USART_Callback);
if (status != ARM_DRIVER_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();
}
return (1U);
}
// Configure SWO Baudrate (UART)
// baudrate: requested baudrate
// return: actual baudrate or 0 when not configured
__WEAK uint32_t SWO_Baudrate_UART (uint32_t baudrate) {
int32_t status;
uint32_t index;
uint32_t num;
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);
}
}
status = pUSART->Control(ARM_USART_MODE_ASYNCHRONOUS |
ARM_USART_DATA_BITS_8 |
ARM_USART_PARITY_NONE |
ARM_USART_STOP_BITS_1,
baudrate);
if (status == ARM_DRIVER_OK) {
USART_Ready = 1U;
} else {
USART_Ready = 0U;
return (0U);
}
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
if ((TraceStatus & DAP_SWO_CAPTURE_PAUSED) == 0U) {
index = TraceIndexI & (SWO_BUFFER_SIZE - 1U);
num = TRACE_BLOCK_SIZE - (index & (TRACE_BLOCK_SIZE - 1U));
TraceBlockSize = num;
pUSART->Receive(&TraceBuf[index], num);
}
pUSART->Control(ARM_USART_CONTROL_RX, 1U);
}
return (baudrate);
}
// Control SWO Capture (UART)
// active: active flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t SWO_Control_UART (uint32_t active) {
int32_t status;
if (active) {
if (!USART_Ready) {
return (0U);
}
TraceBlockSize = 1U;
status = pUSART->Receive(&TraceBuf[0], 1U);
if (status != ARM_DRIVER_OK) {
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);
}
}
return (1U);
}
// Start SWO Capture (UART)
// buf: pointer to buffer for capturing
// num: number of bytes to capture
__WEAK void SWO_Capture_UART (uint8_t *buf, uint32_t num) {
TraceBlockSize = num;
pUSART->Receive(buf, num);
}
// Get SWO Pending Trace Count (UART)
// return: number of pending trace data bytes
__WEAK uint32_t SWO_GetCount_UART (void) {
uint32_t count;
if (pUSART->GetStatus().rx_busy) {
count = pUSART->GetRxCount();
} else {
count = 0U;
}
return (count);
}
#endif /* (SWO_UART != 0) */
#if (SWO_MANCHESTER != 0)
// Enable or disable SWO Mode (Manchester)
// enable: enable flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t SWO_Mode_Manchester (uint32_t enable) {
return (0U);
}
// Configure SWO Baudrate (Manchester)
// baudrate: requested baudrate
// return: actual baudrate or 0 when not configured
__WEAK uint32_t SWO_Baudrate_Manchester (uint32_t baudrate) {
return (0U);
}
// Control SWO Capture (Manchester)
// active: active flag
// return: 1 - Success, 0 - Error
__WEAK uint32_t SWO_Control_Manchester (uint32_t active) {
return (0U);
}
// Start SWO Capture (Manchester)
// buf: pointer to buffer for capturing
// num: number of bytes to capture
__WEAK void SWO_Capture_Manchester (uint8_t *buf, uint32_t num) {
}
// Get SWO Pending Trace Count (Manchester)
// return: number of pending trace data bytes
__WEAK uint32_t SWO_GetCount_Manchester (void) {
}
#endif /* (SWO_MANCHESTER != 0) */
// Clear Trace Errors and Data
static void ClearTrace (void) {
#if (SWO_STREAM != 0)
if (TraceTransport == 2U) {
if (TransferBusy != 0U) {
SWO_AbortTransfer();
TransferBusy = 0U;
}
}
#endif
TraceError[0] = 0U;
TraceError[1] = 0U;
TraceError_n = 0U;
TraceIndexI = 0U;
TraceIndexO = 0U;
#if (TIMESTAMP_CLOCK != 0U)
TraceTimestamp.index = 0U;
TraceTimestamp.tick = 0U;
#endif
}
// Resume Trace Capture
static void ResumeTrace (void) {
uint32_t index_i;
uint32_t index_o;
if (TraceStatus == (DAP_SWO_CAPTURE_ACTIVE | DAP_SWO_CAPTURE_PAUSED)) {
index_i = TraceIndexI;
index_o = TraceIndexO;
if ((index_i - index_o) < SWO_BUFFER_SIZE) {
index_i &= SWO_BUFFER_SIZE - 1U;
switch (TraceMode) {
#if (SWO_UART != 0)
case DAP_SWO_UART:
TraceStatus = DAP_SWO_CAPTURE_ACTIVE;
SWO_Capture_UART(&TraceBuf[index_i], 1U);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
TraceStatus = DAP_SWO_CAPTURE_ACTIVE;
SWO_Capture_Manchester(&TraceBuf[index_i], 1U);
break;
#endif
default:
break;
}
}
}
}
// Get Trace Count
// return: number of available data bytes in trace buffer
static uint32_t GetTraceCount (void) {
uint32_t count;
if (TraceStatus == DAP_SWO_CAPTURE_ACTIVE) {
do {
TraceUpdate = 0U;
count = TraceIndexI - TraceIndexO;
switch (TraceMode) {
#if (SWO_UART != 0)
case DAP_SWO_UART:
count += SWO_GetCount_UART();
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
count += SWO_GetCount_Manchester();
break;
#endif
default:
break;
}
} while (TraceUpdate != 0U);
} else {
count = TraceIndexI - TraceIndexO;
}
return (count);
}
// Get Trace Status (clear Error flags)
// return: Trace Status (Active flag and Error flags)
static uint8_t GetTraceStatus (void) {
uint8_t status;
uint32_t n;
n = TraceError_n;
TraceError_n ^= 1U;
status = TraceStatus | TraceError[n];
TraceError[n] = 0U;
return (status);
}
// Set Trace Error flag(s)
// flag: error flag(s) to set
static 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 result;
if ((TraceStatus & DAP_SWO_CAPTURE_ACTIVE) == 0U) {
transport = *request;
switch (transport) {
case 0U:
case 1U:
#if (SWO_STREAM != 0)
case 2U:
#endif
TraceTransport = transport;
result = 1U;
break;
default:
result = 0U;
break;
}
} else {
result = 0U;
}
if (result != 0U) {
*response = DAP_OK;
} 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 result;
mode = *request;
switch (TraceMode) {
#if (SWO_UART != 0)
case DAP_SWO_UART:
SWO_Mode_UART(0U);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
SWO_Mode_Manchester(0U);
break;
#endif
default:
break;
}
switch (mode) {
case DAP_SWO_OFF:
result = 1U;
break;
#if (SWO_UART != 0)
case DAP_SWO_UART:
result = SWO_Mode_UART(1U);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
result = SWO_Mode_Manchester(1U);
break;
#endif
default:
result = 0U;
break;
}
if (result != 0U) {
TraceMode = mode;
} else {
TraceMode = DAP_SWO_OFF;
}
TraceStatus = 0U;
if (result != 0U) {
*response = DAP_OK;
} 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 baudrate;
baudrate = (uint32_t)(*(request+0) << 0) |
(uint32_t)(*(request+1) << 8) |
(uint32_t)(*(request+2) << 16) |
(uint32_t)(*(request+3) << 24);
switch (TraceMode) {
#if (SWO_UART != 0)
case DAP_SWO_UART:
baudrate = SWO_Baudrate_UART(baudrate);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
baudrate = SWO_Baudrate_Manchester(baudrate);
break;
#endif
default:
baudrate = 0U;
break;
}
if (baudrate == 0U) {
TraceStatus = 0U;
}
*response++ = (uint8_t)(baudrate >> 0);
*response++ = (uint8_t)(baudrate >> 8);
*response++ = (uint8_t)(baudrate >> 16);
*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 result;
active = *request & DAP_SWO_CAPTURE_ACTIVE;
if (active != (TraceStatus & DAP_SWO_CAPTURE_ACTIVE)) {
if (active) {
ClearTrace();
}
switch (TraceMode) {
#if (SWO_UART != 0)
case DAP_SWO_UART:
result = SWO_Control_UART(active);
break;
#endif
#if (SWO_MANCHESTER != 0)
case DAP_SWO_MANCHESTER:
result = SWO_Control_Manchester(active);
break;
#endif
default:
result = 0U;
break;
}
if (result != 0U) {
TraceStatus = active;
#if (SWO_STREAM != 0)
if (TraceTransport == 2U) {
osThreadFlagsSet(SWO_ThreadId, 1U);
}
#endif
}
} else {
result = 1U;
}
if (result != 0U) {
*response = DAP_OK;
} 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 count;
status = GetTraceStatus();
count = GetTraceCount();
*response++ = status;
*response++ = (uint8_t)(count >> 0);
*response++ = (uint8_t)(count >> 8);
*response++ = (uint8_t)(count >> 16);
*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 count;
#if (TIMESTAMP_CLOCK != 0U)
uint32_t index;
uint32_t tick;
#endif
uint32_t num;
num = 0U;
cmd = *request;
if (cmd & 0x01U) {
status = GetTraceStatus();
*response++ = status;
num += 1U;
}
if (cmd & 0x02U) {
count = GetTraceCount();
*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 {
TraceUpdate = 0U;
index = TraceTimestamp.index;
tick = TraceTimestamp.tick;
} while (TraceUpdate != 0U);
*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);
num += 4U;
}
#endif
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 count;
uint32_t index;
uint32_t n, i;
status = GetTraceStatus();
count = GetTraceCount();
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) {
count = n;
}
} else {
count = 0U;
}
*response++ = status;
*response++ = (uint8_t)(count >> 0);
*response++ = (uint8_t)(count >> 8);
if (TraceTransport == 1U) {
index = TraceIndexO;
for (i = index, n = count; n; n--) {
i &= SWO_BUFFER_SIZE - 1U;
*response++ = TraceBuf[i++];
}
TraceIndexO = index + count;
ResumeTrace();
}
return ((2U << 16) | (3U + count));
}
#if (SWO_STREAM != 0)
// SWO Data Transfer complete callback
void SWO_TransferComplete (void) {
TraceIndexO += TransferSize;
TransferBusy = 0U;
ResumeTrace();
osThreadFlagsSet(SWO_ThreadId, 1U);
}
// SWO Thread
__NO_RETURN void SWO_Thread (void *argument) {
uint32_t timeout;
uint32_t flags;
uint32_t count;
uint32_t index;
uint32_t i, n;
(void) argument;
timeout = osWaitForever;
for (;;) {
flags = osThreadFlagsWait(1U, osFlagsWaitAny, timeout);
if (TraceStatus & DAP_SWO_CAPTURE_ACTIVE) {
timeout = SWO_STREAM_TIMEOUT;
} else {
timeout = osWaitForever;
flags = osFlagsErrorTimeout;
}
if (TransferBusy == 0U) {
count = GetTraceCount();
if (count != 0U) {
index = TraceIndexO & (SWO_BUFFER_SIZE - 1U);
n = SWO_BUFFER_SIZE - index;
if (count > n) {
count = n;
}
if (flags != osFlagsErrorTimeout) {
i = index & (USB_BLOCK_SIZE - 1U);
if (i == 0U) {
count &= ~(USB_BLOCK_SIZE - 1U);
} else {
n = USB_BLOCK_SIZE - i;
if (count >= n) {
count = n;
} else {
count = 0U;
}
}
}
if (count != 0U) {
TransferSize = count;
TransferBusy = 1U;
SWO_QueueTransfer(&TraceBuf[index], count);
}
}
}
}
}
#endif /* (SWO_STREAM != 0) */
#endif /* ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) */

View File

@@ -0,0 +1,286 @@
/*
* Copyright (c) 2013-2017 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. December 2017
* $Revision: V2.0.0
*
* Project: CMSIS-DAP Source
* Title: SW_DP.c CMSIS-DAP SW DP I/O
*
*---------------------------------------------------------------------------*/
#include "DAP_config.h"
#include "DAP.h"
// SW Macros
#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR
#define SW_CLOCK_CYCLE() \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
PIN_SWCLK_SET(); \
PIN_DELAY()
#define SW_WRITE_BIT(bit) \
PIN_SWDIO_OUT(bit); \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
PIN_SWCLK_SET(); \
PIN_DELAY()
#define SW_READ_BIT(bit) \
PIN_SWCLK_CLR(); \
PIN_DELAY(); \
bit = PIN_SWDIO_IN(); \
PIN_SWCLK_SET(); \
PIN_DELAY()
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
// Generate SWJ Sequence
// count: sequence bit count
// data: pointer to sequence bit data
// return: none
#if ((DAP_SWD != 0) || (DAP_JTAG != 0))
void SWJ_Sequence (uint32_t count, const uint8_t *data) {
uint32_t val;
uint32_t n;
val = 0U;
n = 0U;
while (count--) {
if (n == 0U) {
val = *data++;
n = 8U;
}
if (val & 1U) {
PIN_SWDIO_TMS_SET();
} else {
PIN_SWDIO_TMS_CLR();
}
SW_CLOCK_CYCLE();
val >>= 1;
n--;
}
}
#endif
// Generate SWD Sequence
// info: sequence information
// swdo: pointer to SWDIO generated data
// swdi: pointer to SWDIO captured data
// return: none
#if (DAP_SWD != 0)
void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
uint32_t val;
uint32_t bit;
uint32_t n, k;
n = info & SWD_SEQUENCE_CLK;
if (n == 0U) {
n = 64U;
}
if (info & SWD_SEQUENCE_DIN) {
while (n) {
val = 0U;
for (k = 8U; k && n; k--, n--) {
SW_READ_BIT(bit);
val >>= 1;
val |= bit << 7;
}
val >>= k;
*swdi++ = (uint8_t)val;
}
} else {
while (n) {
val = *swdo++;
for (k = 8U; k && n; k--, n--) {
SW_WRITE_BIT(val);
val >>= 1;
}
}
}
}
#endif
#if (DAP_SWD != 0)
// SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
#define SWD_TransferFunction(speed) /**/ \
static uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \
uint32_t ack; \
uint32_t bit; \
uint32_t val; \
uint32_t parity; \
\
uint32_t n; \
\
/* Packet Request */ \
parity = 0U; \
SW_WRITE_BIT(1U); /* Start Bit */ \
bit = request >> 0; \
SW_WRITE_BIT(bit); /* APnDP Bit */ \
parity += bit; \
bit = request >> 1; \
SW_WRITE_BIT(bit); /* RnW Bit */ \
parity += bit; \
bit = request >> 2; \
SW_WRITE_BIT(bit); /* A2 Bit */ \
parity += bit; \
bit = request >> 3; \
SW_WRITE_BIT(bit); /* A3 Bit */ \
parity += bit; \
SW_WRITE_BIT(parity); /* Parity Bit */ \
SW_WRITE_BIT(0U); /* Stop Bit */ \
SW_WRITE_BIT(1U); /* Park Bit */ \
\
/* Turnaround */ \
PIN_SWDIO_OUT_DISABLE(); \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
\
/* Acknowledge response */ \
SW_READ_BIT(bit); \
ack = bit << 0; \
SW_READ_BIT(bit); \
ack |= bit << 1; \
SW_READ_BIT(bit); \
ack |= bit << 2; \
\
if (ack == DAP_TRANSFER_OK) { /* OK response */ \
/* Data transfer */ \
if (request & DAP_TRANSFER_RnW) { \
/* Read data */ \
val = 0U; \
parity = 0U; \
for (n = 32U; n; n--) { \
SW_READ_BIT(bit); /* Read RDATA[0:31] */ \
parity += bit; \
val >>= 1; \
val |= bit << 31; \
} \
SW_READ_BIT(bit); /* Read Parity */ \
if ((parity ^ bit) & 1U) { \
ack = DAP_TRANSFER_ERROR; \
} \
if (data) { *data = val; } \
/* Turnaround */ \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
PIN_SWDIO_OUT_ENABLE(); \
} else { \
/* Turnaround */ \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
PIN_SWDIO_OUT_ENABLE(); \
/* Write data */ \
val = *data; \
parity = 0U; \
for (n = 32U; n; n--) { \
SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \
parity += val; \
val >>= 1; \
} \
SW_WRITE_BIT(parity); /* Write Parity Bit */ \
} \
/* Capture Timestamp */ \
if (request & DAP_TRANSFER_TIMESTAMP) { \
DAP_Data.timestamp = TIMESTAMP_GET(); \
} \
/* Idle cycles */ \
n = DAP_Data.transfer.idle_cycles; \
if (n) { \
PIN_SWDIO_OUT(0U); \
for (; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
} \
PIN_SWDIO_OUT(1U); \
return ((uint8_t)ack); \
} \
\
if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \
/* WAIT or FAULT response */ \
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) { \
for (n = 32U+1U; n; n--) { \
SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \
} \
} \
/* Turnaround */ \
for (n = DAP_Data.swd_conf.turnaround; n; n--) { \
SW_CLOCK_CYCLE(); \
} \
PIN_SWDIO_OUT_ENABLE(); \
if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) { \
PIN_SWDIO_OUT(0U); \
for (n = 32U+1U; n; n--) { \
SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \
} \
} \
PIN_SWDIO_OUT(1U); \
return ((uint8_t)ack); \
} \
\
/* Protocol error */ \
for (n = DAP_Data.swd_conf.turnaround + 32U + 1U; n; n--) { \
SW_CLOCK_CYCLE(); /* Back off data phase */ \
} \
PIN_SWDIO_OUT_ENABLE(); \
PIN_SWDIO_OUT(1U); \
return ((uint8_t)ack); \
}
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_FAST()
SWD_TransferFunction(Fast)
#undef PIN_DELAY
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
SWD_TransferFunction(Slow)
// SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
uint8_t SWD_Transfer(uint32_t request, uint32_t *data) {
if (DAP_Data.fast_clock) {
return SWD_TransferFast(request, data);
} else {
return SWD_TransferSlow(request, data);
}
}
#endif /* (DAP_SWD != 0) */

View File

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