mirror of https://github.com/m24h/DAPLINK_C6T6
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
7.0 KiB
269 lines
7.0 KiB
/****************************************************************************** |
|
* @file SW_DP.c |
|
* @brief CMSIS-DAP SW DP I/O |
|
* @version V1.00 |
|
* @date 31. May 2012 |
|
* |
|
* @note |
|
* Copyright (C) 2012 ARM Limited. All rights reserved. |
|
* |
|
* @par |
|
* ARM Limited (ARM) is supplying this software for use with Cortex-M |
|
* processor based microcontrollers. |
|
* |
|
* @par |
|
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED |
|
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF |
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. |
|
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR |
|
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. |
|
* |
|
******************************************************************************/ |
|
|
|
#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, uint8_t *data) |
|
{ |
|
uint8_t val; |
|
uint8_t n = 0; |
|
|
|
DEBUG("DATA:"); |
|
while (count != 0) |
|
{ |
|
count--; |
|
if (n == 0) |
|
{ |
|
val = *data++; |
|
DEBUG(" %02X", val); |
|
n = 8; |
|
} |
|
if (val & 1) |
|
{ |
|
PIN_SWDIO_TMS_SET(); |
|
} |
|
else |
|
{ |
|
PIN_SWDIO_TMS_CLR(); |
|
} |
|
SW_CLOCK_CYCLE(); |
|
val >>= 1; |
|
n--; |
|
} |
|
DEBUG("\n"); |
|
} |
|
#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) /**/ \ |
|
uint8_t SWD_Transfer##speed (uint8_t request, uint32_t *data) \ |
|
{ \ |
|
uint8_t ack; \ |
|
uint8_t bit; \ |
|
uint32_t val; \ |
|
uint8_t parity; \ |
|
uint8_t n; \ |
|
\ |
|
/* Packet Request */ \ |
|
parity = 0; \ |
|
SW_WRITE_BIT(1); /* 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(0); /* Stop Bit */ \ |
|
SW_WRITE_BIT(1); /* Park Bit */ \ |
|
\ |
|
/* Turnaround */ \ |
|
PIN_SWDIO_OUT_DISABLE(); \ |
|
for (n = DAP_Data.swd_conf.turnaround; n != 0; 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 = 0; \ |
|
parity = 0; \ |
|
for (n = 32; 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) & 1) \ |
|
{ \ |
|
ack = DAP_TRANSFER_ERROR; \ |
|
} \ |
|
if (data) *data = val; \ |
|
/* Turnaround */ \ |
|
for (n = DAP_Data.swd_conf.turnaround; n != 0; n--) \ |
|
{ \ |
|
SW_CLOCK_CYCLE(); \ |
|
} \ |
|
\ |
|
PIN_SWDIO_OUT_ENABLE(); \ |
|
} \ |
|
else \ |
|
{ \ |
|
/* Turnaround */ \ |
|
for (n = DAP_Data.swd_conf.turnaround; n != 0; n--) \ |
|
{ \ |
|
SW_CLOCK_CYCLE(); \ |
|
} \ |
|
\ |
|
PIN_SWDIO_OUT_ENABLE(); \ |
|
/* Write data */ \ |
|
val = *data; \ |
|
parity = 0; \ |
|
for (n = 32; n; n--) { \ |
|
SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \ |
|
parity += val; \ |
|
val >>= 1; \ |
|
} \ |
|
SW_WRITE_BIT(parity); /* Write Parity Bit */ \ |
|
} \ |
|
/* Idle cycles */ \ |
|
n = DAP_Data.transfer.idle_cycles; \ |
|
if (n != 0) \ |
|
{ \ |
|
PIN_SWDIO_OUT(0); \ |
|
for (; n != 0; n--) \ |
|
{ \ |
|
SW_CLOCK_CYCLE(); \ |
|
} \ |
|
} \ |
|
PIN_SWDIO_OUT(1); \ |
|
return (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) != 0) \ |
|
{ \ |
|
for (n = 32+1; n; n--) \ |
|
{ \ |
|
SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \ |
|
} \ |
|
} \ |
|
/* Turnaround */ \ |
|
for (n = DAP_Data.swd_conf.turnaround; n != 0; n--) \ |
|
{ \ |
|
SW_CLOCK_CYCLE(); \ |
|
} \ |
|
\ |
|
PIN_SWDIO_OUT_ENABLE(); \ |
|
if (DAP_Data.swd_conf.data_phase && (request & DAP_TRANSFER_RnW) == 0) \ |
|
{ \ |
|
PIN_SWDIO_OUT(0); \ |
|
for (n = 32 + 1; n != 0; n--) \ |
|
{ \ |
|
SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \ |
|
} \ |
|
} \ |
|
PIN_SWDIO_OUT(1); \ |
|
return (ack); \ |
|
} \ |
|
\ |
|
/* Protocol error */ \ |
|
for (n = DAP_Data.swd_conf.turnaround + 32 + 1; n != 0; n--) \ |
|
{ \ |
|
SW_CLOCK_CYCLE(); /* Back off data phase */ \ |
|
} \ |
|
\ |
|
PIN_SWDIO_OUT(1); \ |
|
return (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(uint8_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) */
|
|
|