287 lines
14 KiB
C
287 lines
14 KiB
C
|
/*
|
||
|
* 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) */
|