0
0
Fork 0
wireless-proxy-esp32/components/DAP/source/SW_DP.c

327 lines
8.3 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"
#include "spi_op.h"
#include "spi_switch.h"
#include "dap_utility.h"
// Debug
#define PRINT_SWD_PROTOCOL 0
// 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)
#define PIN_DELAY() PIN_DELAY_FAST()
// 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) {
if (count != 8 && count != 16 && count!= 51)
{
printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count);
return;
}
DAP_SPI_Enable();
DAP_SPI_WriteBits(count, data);
}
#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]
//// TODO: low speed
#define SWD_TransferFunction(speed) /* Speed may be useless, because all use this function */ \
static uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \
SWD_Transfer_Common(request,data); \
return 1; \
}
static uint8_t SWD_Transfer_Common (uint32_t request, uint32_t *data) {
uint8_t ack;
// uint32_t bit;
uint32_t val;
uint8_t parity;
uint8_t computedParity;
uint32_t n;
int retryCount = 0;
const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */
uint8_t requestByte; /* LSB */
DAP_SPI_Enable();
do {
requestByte = constantBits | (((uint8_t)(request & 0xFU)) << 1U) | (ParityEvenUint8(request & 0xFU) << 5U);
/* For 4bit, Parity can be equivalent to 8bit with all 0 high bits */
#if (PRINT_SWD_PROTOCOL == 1)
switch (requestByte)
{
case 0xA5U:
printf("IDCODE\r\n");
break;
case 0xA9U:
printf("W CTRL/STAT\r\n");
break;
case 0xBDU:
printf("RDBUFF\r\n");
break;
case 0x8DU:
printf("R CTRL/STAT\r\n");
break;
case 0x81U:
printf("W ABORT\r\n");
break;
case 0xB1U:
printf("W SELECT\r\n");
break;
case 0xBBU:
printf("W APc\r\n");
break;
case 0x9FU:
printf("R APc\r\n");
break;
case 0x8BU:
printf("W AP4\r\n");
break;
case 0xA3U:
printf("W AP0\r\n");
break;
case 0X87U:
printf("R AP0\r\n");
break;
case 0xB7U:
printf("R AP8\r\n");
break;
default:
//W AP8
printf("Unknown:%08x\r\n", requestByte);
break;
}
#endif
if (request & DAP_TRANSFER_RnW) {
/* Read data */
DAP_SPI_Send_Header(requestByte, &ack, 0); // 0 Trn After ACK
if (ack == DAP_TRANSFER_OK) {
DAP_SPI_Read_Data(&val, &parity);
computedParity = ParityEvenUint32(val);
if ((computedParity ^ parity) & 1U) {
ack = DAP_TRANSFER_ERROR;
}
if (data) { *data = val; }
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
DAP_Data.timestamp = TIMESTAMP_GET();
}
}
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
DAP_SPI_Generate_Cycle(1);
#if (PRINT_SWD_PROTOCOL == 1)
printf("WAIT\r\n");
#endif
continue;
// return DAP_TRANSFER_WAIT;
}
else {
/* Protocol error */
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
DAP_SPI_Enable();
DAP_SPI_Protocol_Error_Read();
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
printf("Protocol Error: Read\r\n");
}
return ((uint8_t)ack);
}
else {
/* Write data */
parity = ParityEvenUint32(*data);
DAP_SPI_Send_Header(requestByte, &ack, 1); // 1 Trn After ACK
if (ack == DAP_TRANSFER_OK) {
DAP_SPI_Write_Data(*data, parity);
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
DAP_Data.timestamp = TIMESTAMP_GET();
}
/* Idle cycles */
n = DAP_Data.transfer.idle_cycles;
if (n) { DAP_SPI_Generate_Cycle(n); }
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
return ((uint8_t)ack);
}
else if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
/* already turnaround. */
/* TODO: overrun transfer -> for read */
#if (PRINT_SWD_PROTOCOL == 1)
printf("WAIT\r\n");
#endif
continue;
}
else {
//// FIXME: bug
/* Protocol error */
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
DAP_SPI_Enable();
DAP_SPI_Protocol_Error_Write();
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
printf("Protocol Error: Write\r\n");
}
return ((uint8_t)ack);
}
} while (retryCount++ < 99);
return DAP_TRANSFER_ERROR;
}
#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) */