/ Drivers / CMSIS / DAP / Firmware / Source / JTAG_DP.c
JTAG_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:        JTAG_DP.c CMSIS-DAP JTAG DP I/O
 25   *
 26   *---------------------------------------------------------------------------*/
 27  
 28  #include "DAP_config.h"
 29  #include "DAP.h"
 30  
 31  
 32  // JTAG Macros
 33  
 34  #define PIN_TCK_SET PIN_SWCLK_TCK_SET
 35  #define PIN_TCK_CLR PIN_SWCLK_TCK_CLR
 36  #define PIN_TMS_SET PIN_SWDIO_TMS_SET
 37  #define PIN_TMS_CLR PIN_SWDIO_TMS_CLR
 38  
 39  #define JTAG_CYCLE_TCK()                \
 40    PIN_TCK_CLR();                        \
 41    PIN_DELAY();                          \
 42    PIN_TCK_SET();                        \
 43    PIN_DELAY()
 44  
 45  #define JTAG_CYCLE_TDI(tdi)             \
 46    PIN_TDI_OUT(tdi);                     \
 47    PIN_TCK_CLR();                        \
 48    PIN_DELAY();                          \
 49    PIN_TCK_SET();                        \
 50    PIN_DELAY()
 51  
 52  #define JTAG_CYCLE_TDO(tdo)             \
 53    PIN_TCK_CLR();                        \
 54    PIN_DELAY();                          \
 55    tdo = PIN_TDO_IN();                   \
 56    PIN_TCK_SET();                        \
 57    PIN_DELAY()
 58  
 59  #define JTAG_CYCLE_TDIO(tdi,tdo)        \
 60    PIN_TDI_OUT(tdi);                     \
 61    PIN_TCK_CLR();                        \
 62    PIN_DELAY();                          \
 63    tdo = PIN_TDO_IN();                   \
 64    PIN_TCK_SET();                        \
 65    PIN_DELAY()
 66  
 67  #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
 68  
 69  
 70  #if (DAP_JTAG != 0)
 71  
 72  
 73  // Generate JTAG Sequence
 74  //   info:   sequence information
 75  //   tdi:    pointer to TDI generated data
 76  //   tdo:    pointer to TDO captured data
 77  //   return: none
 78  void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo) {
 79    uint32_t i_val;
 80    uint32_t o_val;
 81    uint32_t bit;
 82    uint32_t n, k;
 83  
 84    n = info & JTAG_SEQUENCE_TCK;
 85    if (n == 0U) {
 86      n = 64U;
 87    }
 88  
 89    if (info & JTAG_SEQUENCE_TMS) {
 90      PIN_TMS_SET();
 91    } else {
 92      PIN_TMS_CLR();
 93    }
 94  
 95    while (n) {
 96      i_val = *tdi++;
 97      o_val = 0U;
 98      for (k = 8U; k && n; k--, n--) {
 99        JTAG_CYCLE_TDIO(i_val, bit);
100        i_val >>= 1;
101        o_val >>= 1;
102        o_val  |= bit << 7;
103      }
104      o_val >>= k;
105      if (info & JTAG_SEQUENCE_TDO) {
106        *tdo++ = (uint8_t)o_val;
107      }
108    }
109  }
110  
111  
112  // JTAG Set IR
113  //   ir:     IR value
114  //   return: none
115  #define JTAG_IR_Function(speed) /**/                                            \
116  static void JTAG_IR_##speed (uint32_t ir) {                                     \
117    uint32_t n;                                                                   \
118                                                                                  \
119    PIN_TMS_SET();                                                                \
120    JTAG_CYCLE_TCK();                         /* Select-DR-Scan */                \
121    JTAG_CYCLE_TCK();                         /* Select-IR-Scan */                \
122    PIN_TMS_CLR();                                                                \
123    JTAG_CYCLE_TCK();                         /* Capture-IR */                    \
124    JTAG_CYCLE_TCK();                         /* Shift-IR */                      \
125                                                                                  \
126    PIN_TDI_OUT(1U);                                                              \
127    for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) {      \
128      JTAG_CYCLE_TCK();                       /* Bypass before data */            \
129    }                                                                             \
130    for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1U; n; n--) { \
131      JTAG_CYCLE_TDI(ir);                     /* Set IR bits (except last) */     \
132      ir >>= 1;                                                                   \
133    }                                                                             \
134    n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index];                      \
135    if (n) {                                                                      \
136      JTAG_CYCLE_TDI(ir);                     /* Set last IR bit */               \
137      PIN_TDI_OUT(1U);                                                            \
138      for (--n; n; n--) {                                                         \
139        JTAG_CYCLE_TCK();                     /* Bypass after data */             \
140      }                                                                           \
141      PIN_TMS_SET();                                                              \
142      JTAG_CYCLE_TCK();                       /* Bypass & Exit1-IR */             \
143    } else {                                                                      \
144      PIN_TMS_SET();                                                              \
145      JTAG_CYCLE_TDI(ir);                     /* Set last IR bit & Exit1-IR */    \
146    }                                                                             \
147                                                                                  \
148    JTAG_CYCLE_TCK();                         /* Update-IR */                     \
149    PIN_TMS_CLR();                                                                \
150    JTAG_CYCLE_TCK();                         /* Idle */                          \
151    PIN_TDI_OUT(1U);                                                              \
152  }
153  
154  
155  // JTAG Transfer I/O
156  //   request: A[3:2] RnW APnDP
157  //   data:    DATA[31:0]
158  //   return:  ACK[2:0]
159  #define JTAG_TransferFunction(speed)        /**/                                \
160  static uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) {        \
161    uint32_t ack;                                                                 \
162    uint32_t bit;                                                                 \
163    uint32_t val;                                                                 \
164    uint32_t n;                                                                   \
165                                                                                  \
166    PIN_TMS_SET();                                                                \
167    JTAG_CYCLE_TCK();                         /* Select-DR-Scan */                \
168    PIN_TMS_CLR();                                                                \
169    JTAG_CYCLE_TCK();                         /* Capture-DR */                    \
170    JTAG_CYCLE_TCK();                         /* Shift-DR */                      \
171                                                                                  \
172    for (n = DAP_Data.jtag_dev.index; n; n--) {                                   \
173      JTAG_CYCLE_TCK();                       /* Bypass before data */            \
174    }                                                                             \
175                                                                                  \
176    JTAG_CYCLE_TDIO(request >> 1, bit);       /* Set RnW, Get ACK.0 */            \
177    ack  = bit << 1;                                                              \
178    JTAG_CYCLE_TDIO(request >> 2, bit);       /* Set A2,  Get ACK.1 */            \
179    ack |= bit << 0;                                                              \
180    JTAG_CYCLE_TDIO(request >> 3, bit);       /* Set A3,  Get ACK.2 */            \
181    ack |= bit << 2;                                                              \
182                                                                                  \
183    if (ack != DAP_TRANSFER_OK) {                                                 \
184      /* Exit on error */                                                         \
185      PIN_TMS_SET();                                                              \
186      JTAG_CYCLE_TCK();                       /* Exit1-DR */                      \
187      goto exit;                                                                  \
188    }                                                                             \
189                                                                                  \
190    if (request & DAP_TRANSFER_RnW) {                                             \
191      /* Read Transfer */                                                         \
192      val = 0U;                                                                   \
193      for (n = 31U; n; n--) {                                                     \
194        JTAG_CYCLE_TDO(bit);                  /* Get D0..D30 */                   \
195        val  |= bit << 31;                                                        \
196        val >>= 1;                                                                \
197      }                                                                           \
198      n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U;                 \
199      if (n) {                                                                    \
200        JTAG_CYCLE_TDO(bit);                  /* Get D31 */                       \
201        for (--n; n; n--) {                                                       \
202          JTAG_CYCLE_TCK();                   /* Bypass after data */             \
203        }                                                                         \
204        PIN_TMS_SET();                                                            \
205        JTAG_CYCLE_TCK();                     /* Bypass & Exit1-DR */             \
206      } else {                                                                    \
207        PIN_TMS_SET();                                                            \
208        JTAG_CYCLE_TDO(bit);                  /* Get D31 & Exit1-DR */            \
209      }                                                                           \
210      val |= bit << 31;                                                           \
211      if (data) { *data = val; }                                                  \
212    } else {                                                                      \
213      /* Write Transfer */                                                        \
214      val = *data;                                                                \
215      for (n = 31U; n; n--) {                                                     \
216        JTAG_CYCLE_TDI(val);                  /* Set D0..D30 */                   \
217        val >>= 1;                                                                \
218      }                                                                           \
219      n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U;                 \
220      if (n) {                                                                    \
221        JTAG_CYCLE_TDI(val);                  /* Set D31 */                       \
222        for (--n; n; n--) {                                                       \
223          JTAG_CYCLE_TCK();                   /* Bypass after data */             \
224        }                                                                         \
225        PIN_TMS_SET();                                                            \
226        JTAG_CYCLE_TCK();                     /* Bypass & Exit1-DR */             \
227      } else {                                                                    \
228        PIN_TMS_SET();                                                            \
229        JTAG_CYCLE_TDI(val);                  /* Set D31 & Exit1-DR */            \
230      }                                                                           \
231    }                                                                             \
232                                                                                  \
233  exit:                                                                           \
234    JTAG_CYCLE_TCK();                         /* Update-DR */                     \
235    PIN_TMS_CLR();                                                                \
236    JTAG_CYCLE_TCK();                         /* Idle */                          \
237    PIN_TDI_OUT(1U);                                                              \
238                                                                                  \
239    /* Capture Timestamp */                                                       \
240    if (request & DAP_TRANSFER_TIMESTAMP) {                                       \
241      DAP_Data.timestamp = TIMESTAMP_GET();                                       \
242    }                                                                             \
243                                                                                  \
244    /* Idle cycles */                                                             \
245    n = DAP_Data.transfer.idle_cycles;                                            \
246    while (n--) {                                                                 \
247      JTAG_CYCLE_TCK();                       /* Idle */                          \
248    }                                                                             \
249                                                                                  \
250    return ((uint8_t)ack);                                                        \
251  }
252  
253  
254  #undef  PIN_DELAY
255  #define PIN_DELAY() PIN_DELAY_FAST()
256  JTAG_IR_Function(Fast)
257  JTAG_TransferFunction(Fast)
258  
259  #undef  PIN_DELAY
260  #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)
261  JTAG_IR_Function(Slow)
262  JTAG_TransferFunction(Slow)
263  
264  
265  // JTAG Read IDCODE register
266  //   return: value read
267  uint32_t JTAG_ReadIDCode (void) {
268    uint32_t bit;
269    uint32_t val;
270    uint32_t n;
271  
272    PIN_TMS_SET();
273    JTAG_CYCLE_TCK();                         /* Select-DR-Scan */
274    PIN_TMS_CLR();
275    JTAG_CYCLE_TCK();                         /* Capture-DR */
276    JTAG_CYCLE_TCK();                         /* Shift-DR */
277  
278    for (n = DAP_Data.jtag_dev.index; n; n--) {
279      JTAG_CYCLE_TCK();                       /* Bypass before data */
280    }
281  
282    val = 0U;
283    for (n = 31U; n; n--) {
284      JTAG_CYCLE_TDO(bit);                    /* Get D0..D30 */
285      val  |= bit << 31;
286      val >>= 1;
287    }
288    PIN_TMS_SET();
289    JTAG_CYCLE_TDO(bit);                      /* Get D31 & Exit1-DR */
290    val |= bit << 31;
291  
292    JTAG_CYCLE_TCK();                         /* Update-DR */
293    PIN_TMS_CLR();
294    JTAG_CYCLE_TCK();                         /* Idle */
295  
296    return (val);
297  }
298  
299  
300  // JTAG Write ABORT register
301  //   data:   value to write
302  //   return: none
303  void JTAG_WriteAbort (uint32_t data) {
304    uint32_t n;
305  
306    PIN_TMS_SET();
307    JTAG_CYCLE_TCK();                         /* Select-DR-Scan */
308    PIN_TMS_CLR();
309    JTAG_CYCLE_TCK();                         /* Capture-DR */
310    JTAG_CYCLE_TCK();                         /* Shift-DR */
311  
312    for (n = DAP_Data.jtag_dev.index; n; n--) {
313      JTAG_CYCLE_TCK();                       /* Bypass before data */
314    }
315  
316    PIN_TDI_OUT(0U);
317    JTAG_CYCLE_TCK();                         /* Set RnW=0 (Write) */
318    JTAG_CYCLE_TCK();                         /* Set A2=0 */
319    JTAG_CYCLE_TCK();                         /* Set A3=0 */
320  
321    for (n = 31U; n; n--) {
322      JTAG_CYCLE_TDI(data);                   /* Set D0..D30 */
323      data >>= 1;
324    }
325    n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1U;
326    if (n) {
327      JTAG_CYCLE_TDI(data);                   /* Set D31 */
328      for (--n; n; n--) {
329        JTAG_CYCLE_TCK();                     /* Bypass after data */
330      }
331      PIN_TMS_SET();
332      JTAG_CYCLE_TCK();                       /* Bypass & Exit1-DR */
333    } else {
334      PIN_TMS_SET();
335      JTAG_CYCLE_TDI(data);                   /* Set D31 & Exit1-DR */
336    }
337  
338    JTAG_CYCLE_TCK();                         /* Update-DR */
339    PIN_TMS_CLR();
340    JTAG_CYCLE_TCK();                         /* Idle */
341    PIN_TDI_OUT(1U);
342  }
343  
344  
345  // JTAG Set IR
346  //   ir:     IR value
347  //   return: none
348  void JTAG_IR (uint32_t ir) {
349    if (DAP_Data.fast_clock) {
350      JTAG_IR_Fast(ir);
351    } else {
352      JTAG_IR_Slow(ir);
353    }
354  }
355  
356  
357  // JTAG Transfer I/O
358  //   request: A[3:2] RnW APnDP
359  //   data:    DATA[31:0]
360  //   return:  ACK[2:0]
361  uint8_t  JTAG_Transfer(uint32_t request, uint32_t *data) {
362    if (DAP_Data.fast_clock) {
363      return JTAG_TransferFast(request, data);
364    } else {
365      return JTAG_TransferSlow(request, data);
366    }
367  }
368  
369  
370  #endif  /* (DAP_JTAG != 0) */