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.
360 lines
16 KiB
360 lines
16 KiB
/****************************************************************************** |
|
* @file JTAG_DP.c |
|
* @brief CMSIS-DAP JTAG 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" |
|
|
|
|
|
// 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, 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 == 0) n = 64; |
|
|
|
if (info & JTAG_SEQUENCE_TMS) { |
|
PIN_TMS_SET(); |
|
} else { |
|
PIN_TMS_CLR(); |
|
} |
|
|
|
while (n) { |
|
i_val = *tdi++; |
|
o_val = 0; |
|
for (k = 8; 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++ = o_val; |
|
} |
|
} |
|
} |
|
|
|
|
|
// JTAG Set IR |
|
// ir: IR value |
|
// return: none |
|
#define JTAG_IR_Function(speed) /**/ \ |
|
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(1); \ |
|
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] - 1; 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(1); \ |
|
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(1); \ |
|
} |
|
|
|
|
|
// JTAG Transfer I/O |
|
// request: A[3:2] RnW APnDP |
|
// data: DATA[31:0] |
|
// return: ACK[2:0] |
|
#define JTAG_TransferFunction(speed) /**/ \ |
|
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 = 0; \ |
|
for (n = 31; 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 - 1; \ |
|
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 = 31; n; n--) { \ |
|
JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \ |
|
val >>= 1; \ |
|
} \ |
|
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; \ |
|
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(1); \ |
|
\ |
|
/* Idle cycles */ \ |
|
n = DAP_Data.transfer.idle_cycles; \ |
|
while (n--) { \ |
|
JTAG_CYCLE_TCK(); /* Idle */ \ |
|
} \ |
|
\ |
|
return (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 = 0; |
|
for (n = 31; 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(0); |
|
JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */ |
|
JTAG_CYCLE_TCK(); /* Set A2=0 */ |
|
JTAG_CYCLE_TCK(); /* Set A3=0 */ |
|
|
|
for (n = 31; n; n--) { |
|
JTAG_CYCLE_TDI(data); /* Set D0..D30 */ |
|
data >>= 1; |
|
} |
|
n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; |
|
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(1); |
|
} |
|
|
|
|
|
// 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(uint8_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) */
|
|
|