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