/ Drivers / CMSIS / DAP / Firmware / Source / SW_DP.c
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) */