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

531 lines
13 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
*
*---------------------------------------------------------------------------*/
/**
* @file SW_DP.c
* @author windowsair
* @brief Adaptation of GPIO and SPI
* @change:
* 2021-2-10 Support GPIO and SPI for SWD sequence / SWJ sequence / SWD transfer
* Note: SWD sequence not yet tested
* @version 0.1
* @date 2021-2-10
*
* @copyright Copyright (c) 2021
*
*/
#include <stdio.h>
#include "components/DAP/config/DAP_config.h"
#include "components/DAP/include/DAP.h"
#include "components/DAP/include/spi_op.h"
#include "components/DAP/include/spi_switch.h"
#include "components/DAP/include/dap_utility.h"
// Debug
#define PRINT_SWD_PROTOCOL 0
// SW Macros
#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET
#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR
// Space for time in the original version,
// and time for space in our implementation
#define SW_CLOCK_CYCLE() \
PIN_SWCLK_CLR(); \
if (need_delay) { PIN_DELAY(); } \
PIN_SWCLK_SET(); \
if (need_delay) { PIN_DELAY(); }
#define SW_WRITE_BIT(bit) \
PIN_SWDIO_OUT(bit); \
PIN_SWCLK_CLR(); \
if (need_delay) { PIN_DELAY(); } \
PIN_SWCLK_SET(); \
if (need_delay) { PIN_DELAY(); }
#define SW_READ_BIT(bit) \
PIN_SWCLK_CLR(); \
if (need_delay) { PIN_DELAY(); } \
bit = PIN_SWDIO_IN(); \
PIN_SWCLK_SET(); \
if (need_delay) { PIN_DELAY(); }
uint8_t SWD_TransferSpeed = kTransfer_GPIO_normal;
void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay);
void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data);
void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi);
void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi);
// 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)
// {
// os_printf("[ERROR] wrong SWJ Swquence length:%d\r\n", (int)count);
// return;
// }
if(SWD_TransferSpeed == kTransfer_SPI) {
SWJ_Sequence_SPI(count, data);
} else {
SWJ_Sequence_GPIO(count, data, 1);
}
}
void SWJ_Sequence_GPIO (uint32_t count, const uint8_t *data, uint8_t need_delay) {
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--;
}
}
void SWJ_Sequence_SPI (uint32_t count, const uint8_t *data) {
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) {
if (SWD_TransferSpeed == kTransfer_SPI) {
SWD_Sequence_SPI(info, swdo, swdi);
} else {
SWD_Sequence_GPIO(info, swdo, swdi);
}
}
void SWD_Sequence_GPIO (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
const uint8_t need_delay = 1;
uint32_t val;
uint32_t bit;
uint32_t n, k;
n = info & SWD_SEQUENCE_CLK;
if (n == 0U) {
n = 64U;
}
// n = 1 ~ 64
// LSB
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;
}
}
}
}
void SWD_Sequence_SPI (uint32_t info, const uint8_t *swdo, uint8_t *swdi) {
uint32_t n;
n = info & SWD_SEQUENCE_CLK;
if (n == 0U) {
n = 64U;
}
// n = 1 ~ 64
if (info & SWD_SEQUENCE_DIN) {
DAP_SPI_ReadBits(n, swdi);
} else {
DAP_SPI_WriteBits(n, swdo);
}
}
#endif
#if (DAP_SWD != 0)
// SWD Transfer I/O
// request: A[3:2] RnW APnDP
// data: DATA[31:0]
// return: ACK[2:0]
static uint8_t SWD_Transfer_SPI (uint32_t request, uint32_t *data) {
//// FIXME: overrun detection
// SPI transfer mode does not require operations such as PIN_DELAY
uint8_t ack;
// uint32_t bit;
uint32_t val;
uint8_t parity;
uint8_t computedParity;
uint32_t n;
const uint8_t constantBits = 0b10000001U; /* Start Bit & Stop Bit & Park Bit is fixed. */
uint8_t requestByte; /* LSB */
DAP_SPI_Enable();
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:
os_printf("IDCODE\r\n");
break;
case 0xA9U:
os_printf("W CTRL/STAT\r\n");
break;
case 0xBDU:
os_printf("RDBUFF\r\n");
break;
case 0x8DU:
os_printf("R CTRL/STAT\r\n");
break;
case 0x81U:
os_printf("W ABORT\r\n");
break;
case 0xB1U:
os_printf("W SELECT\r\n");
break;
case 0xBBU:
os_printf("W APc\r\n");
break;
case 0x9FU:
os_printf("R APc\r\n");
break;
case 0x8BU:
os_printf("W AP4\r\n");
break;
case 0xA3U:
os_printf("W AP0\r\n");
break;
case 0X87U:
os_printf("R AP0\r\n");
break;
case 0xB7U:
os_printf("R AP8\r\n");
break;
default:
//W AP8
os_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)) {
////FIXME: esp32 // DAP_SPI_Fast_Cycle();
DAP_SPI_Generate_Cycle(1);
#if (PRINT_SWD_PROTOCOL == 1)
os_printf("WAIT\r\n");
#endif
// 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();
#if (PRINT_SWD_PROTOCOL == 1)
os_printf("Protocol Error: Read\r\n");
#endif
}
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)
os_printf("WAIT\r\n");
#endif
}
else {
/* Protocol error */
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
DAP_SPI_Enable();
DAP_SPI_Protocol_Error_Write();
DAP_SPI_Disable();
PIN_SWDIO_TMS_SET();
#if (PRINT_SWD_PROTOCOL == 1)
os_printf("Protocol Error: Write\r\n");
#endif
}
return ((uint8_t)ack);
}
return DAP_TRANSFER_ERROR;
}
static uint8_t SWD_Transfer_GPIO (uint32_t request, uint32_t *data, uint8_t need_delay) {
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);
}
// 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) {
switch (SWD_TransferSpeed) {
case kTransfer_SPI:
return SWD_Transfer_SPI(request, data);
case kTransfer_GPIO_fast:
return SWD_Transfer_GPIO(request, data, 0);
case kTransfer_GPIO_normal:
return SWD_Transfer_GPIO(request, data, 1);
default:
return SWD_Transfer_GPIO(request, data, 1);
}
}
#endif /* (DAP_SWD != 0) */