| 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) */
|
|---|