SW_DP.c
1 /* 2 * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Licensed under the Apache License, Version 2.0 (the License); you may 7 * not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * ---------------------------------------------------------------------- 19 * 20 * $Date: 1. December 2017 21 * $Revision: V2.0.0 22 * 23 * Project: CMSIS-DAP Source 24 * Title: SW_DP.c CMSIS-DAP SW DP I/O 25 * 26 *---------------------------------------------------------------------------*/ 27 28 #include "DAP_config.h" 29 #include "DAP.h" 30 31 32 // SW Macros 33 34 #define PIN_SWCLK_SET PIN_SWCLK_TCK_SET 35 #define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR 36 37 #define SW_CLOCK_CYCLE() \ 38 PIN_SWCLK_CLR(); \ 39 PIN_DELAY(); \ 40 PIN_SWCLK_SET(); \ 41 PIN_DELAY() 42 43 #define SW_WRITE_BIT(bit) \ 44 PIN_SWDIO_OUT(bit); \ 45 PIN_SWCLK_CLR(); \ 46 PIN_DELAY(); \ 47 PIN_SWCLK_SET(); \ 48 PIN_DELAY() 49 50 #define SW_READ_BIT(bit) \ 51 PIN_SWCLK_CLR(); \ 52 PIN_DELAY(); \ 53 bit = PIN_SWDIO_IN(); \ 54 PIN_SWCLK_SET(); \ 55 PIN_DELAY() 56 57 #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 58 59 60 // Generate SWJ Sequence 61 // count: sequence bit count 62 // data: pointer to sequence bit data 63 // return: none 64 #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 65 void SWJ_Sequence (uint32_t count, const uint8_t *data) { 66 uint32_t val; 67 uint32_t n; 68 69 val = 0U; 70 n = 0U; 71 while (count--) { 72 if (n == 0U) { 73 val = *data++; 74 n = 8U; 75 } 76 if (val & 1U) { 77 PIN_SWDIO_TMS_SET(); 78 } else { 79 PIN_SWDIO_TMS_CLR(); 80 } 81 SW_CLOCK_CYCLE(); 82 val >>= 1; 83 n--; 84 } 85 } 86 #endif 87 88 89 // Generate SWD Sequence 90 // info: sequence information 91 // swdo: pointer to SWDIO generated data 92 // swdi: pointer to SWDIO captured data 93 // return: none 94 #if (DAP_SWD != 0) 95 void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { 96 uint32_t val; 97 uint32_t bit; 98 uint32_t n, k; 99 100 n = info & SWD_SEQUENCE_CLK; 101 if (n == 0U) { 102 n = 64U; 103 } 104 105 if (info & SWD_SEQUENCE_DIN) { 106 while (n) { 107 val = 0U; 108 for (k = 8U; k && n; k--, n--) { 109 SW_READ_BIT(bit); 110 val >>= 1; 111 val |= bit << 7; 112 } 113 val >>= k; 114 *swdi++ = (uint8_t)val; 115 } 116 } else { 117 while (n) { 118 val = *swdo++; 119 for (k = 8U; k && n; k--, n--) { 120 SW_WRITE_BIT(val); 121 val >>= 1; 122 } 123 } 124 } 125 } 126 #endif 127 128 129 #if (DAP_SWD != 0) 130 131 132 // SWD Transfer I/O 133 // request: A[3:2] RnW APnDP 134 // data: DATA[31:0] 135 // return: ACK[2:0] 136 #define SWD_TransferFunction(speed) /**/ \ 137 static uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \ 138 uint32_t ack; \ 139 uint32_t bit; \ 140 uint32_t val; \ 141 uint32_t parity; \ 142 \ 143 uint32_t n; \ 144 \ 145 /* Packet Request */ \ 146 parity = 0U; \ 147 SW_WRITE_BIT(1U); /* Start Bit */ \ 148 bit = request >> 0; \ 149 SW_WRITE_BIT(bit); /* APnDP Bit */ \ 150 parity += bit; \ 151 bit = request >> 1; \ 152 SW_WRITE_BIT(bit); /* RnW Bit */ \ 153 parity += bit; \ 154 bit = request >> 2; \ 155 SW_WRITE_BIT(bit); /* A2 Bit */ \ 156 parity += bit; \ 157 bit = request >> 3; \ 158 SW_WRITE_BIT(bit); /* A3 Bit */ \ 159 parity += bit; \ 160 SW_WRITE_BIT(parity); /* Parity Bit */ \ 161 SW_WRITE_BIT(0U); /* Stop Bit */ \ 162 SW_WRITE_BIT(1U); /* Park Bit */ \ 163 \ 164 /* Turnaround */ \ 165 PIN_SWDIO_OUT_DISABLE(); \ 166 for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 167 SW_CLOCK_CYCLE(); \ 168 } \ 169 \ 170 /* Acknowledge response */ \ 171 SW_READ_BIT(bit); \ 172 ack = bit << 0; \ 173 SW_READ_BIT(bit); \ 174 ack |= bit << 1; \ 175 SW_READ_BIT(bit); \ 176 ack |= bit << 2; \ 177 \ 178 if (ack == DAP_TRANSFER_OK) { /* OK response */ \ 179 /* Data transfer */ \ 180 if (request & DAP_TRANSFER_RnW) { \ 181 /* Read data */ \ 182 val = 0U; \ 183 parity = 0U; \ 184 for (n = 32U; n; n--) { \ 185 SW_READ_BIT(bit); /* Read RDATA[0:31] */ \ 186 parity += bit; \ 187 val >>= 1; \ 188 val |= bit << 31; \ 189 } \ 190 SW_READ_BIT(bit); /* Read Parity */ \ 191 if ((parity ^ bit) & 1U) { \ 192 ack = DAP_TRANSFER_ERROR; \ 193 } \ 194 if (data) { *data = val; } \ 195 /* Turnaround */ \ 196 for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 197 SW_CLOCK_CYCLE(); \ 198 } \ 199 PIN_SWDIO_OUT_ENABLE(); \ 200 } else { \ 201 /* Turnaround */ \ 202 for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 203 SW_CLOCK_CYCLE(); \ 204 } \ 205 PIN_SWDIO_OUT_ENABLE(); \ 206 /* Write data */ \ 207 val = *data; \ 208 parity = 0U; \ 209 for (n = 32U; n; n--) { \ 210 SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \ 211 parity += val; \ 212 val >>= 1; \ 213 } \ 214 SW_WRITE_BIT(parity); /* Write Parity Bit */ \ 215 } \ 216 /* Capture Timestamp */ \ 217 if (request & DAP_TRANSFER_TIMESTAMP) { \ 218 DAP_Data.timestamp = TIMESTAMP_GET(); \ 219 } \ 220 /* Idle cycles */ \ 221 n = DAP_Data.transfer.idle_cycles; \ 222 if (n) { \ 223 PIN_SWDIO_OUT(0U); \ 224 for (; n; n--) { \ 225 SW_CLOCK_CYCLE(); \ 226 } \ 227 } \ 228 PIN_SWDIO_OUT(1U); \ 229 return ((uint8_t)ack); \ 230 } \ 231 \ 232 if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \ 233 /* WAIT or FAULT response */ \ 234 if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) { \ 235 for (n = 32U+1U; n; n--) { \ 236 SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \ 237 } \ 238 } \ 239 /* Turnaround */ \ 240 for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 241 SW_CLOCK_CYCLE(); \ 242 } \ 243 PIN_SWDIO_OUT_ENABLE(); \ 244 if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) { \ 245 PIN_SWDIO_OUT(0U); \ 246 for (n = 32U+1U; n; n--) { \ 247 SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \ 248 } \ 249 } \ 250 PIN_SWDIO_OUT(1U); \ 251 return ((uint8_t)ack); \ 252 } \ 253 \ 254 /* Protocol error */ \ 255 for (n = DAP_Data.swd_conf.turnaround + 32U + 1U; n; n--) { \ 256 SW_CLOCK_CYCLE(); /* Back off data phase */ \ 257 } \ 258 PIN_SWDIO_OUT_ENABLE(); \ 259 PIN_SWDIO_OUT(1U); \ 260 return ((uint8_t)ack); \ 261 } 262 263 264 #undef PIN_DELAY 265 #define PIN_DELAY() PIN_DELAY_FAST() 266 SWD_TransferFunction(Fast) 267 268 #undef PIN_DELAY 269 #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 270 SWD_TransferFunction(Slow) 271 272 273 // SWD Transfer I/O 274 // request: A[3:2] RnW APnDP 275 // data: DATA[31:0] 276 // return: ACK[2:0] 277 uint8_t SWD_Transfer(uint32_t request, uint32_t *data) { 278 if (DAP_Data.fast_clock) { 279 return SWD_TransferFast(request, data); 280 } else { 281 return SWD_TransferSlow(request, data); 282 } 283 } 284 285 286 #endif /* (DAP_SWD != 0) */