initial commit
[armstart-ibdap] / src / SW_DP.c
1 /******************************************************************************\r
2  * @file     SW_DP.c\r
3  * @brief    CMSIS-DAP SW DP I/O\r
4  * @version  V1.00\r
5  * @date     31. May 2012\r
6  *\r
7  * @note\r
8  * Copyright (C) 2012 ARM Limited. All rights reserved.\r
9  *\r
10  * @par\r
11  * ARM Limited (ARM) is supplying this software for use with Cortex-M\r
12  * processor based microcontrollers.\r
13  *\r
14  * @par\r
15  * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED\r
16  * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF\r
17  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.\r
18  * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR\r
19  * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.\r
20  *\r
21  ******************************************************************************/\r
22 \r
23 #include "DAP_config.h"\r
24 #include "DAP.h"\r
25 \r
26 \r
27 // SW Macros\r
28 \r
29 #define PIN_SWCLK_SET PIN_SWCLK_TCK_SET\r
30 #define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR\r
31 \r
32 #define SW_CLOCK_CYCLE()                \\r
33   PIN_SWCLK_CLR();                      \\r
34   PIN_DELAY();                          \\r
35   PIN_SWCLK_SET();                      \\r
36   PIN_DELAY()\r
37 \r
38 #define SW_WRITE_BIT(bit)               \\r
39   PIN_SWDIO_OUT(bit);                   \\r
40   PIN_SWCLK_CLR();                      \\r
41   PIN_DELAY();                          \\r
42   PIN_SWCLK_SET();                      \\r
43   PIN_DELAY()\r
44 \r
45 #define SW_READ_BIT(bit)                \\r
46   PIN_SWCLK_CLR();                      \\r
47   PIN_DELAY();                          \\r
48   bit = PIN_SWDIO_IN();                 \\r
49   PIN_SWCLK_SET();                      \\r
50   PIN_DELAY()\r
51 \r
52 #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)\r
53 \r
54 \r
55 // Generate SWJ Sequence\r
56 //   count:  sequence bit count\r
57 //   data:   pointer to sequence bit data\r
58 //   return: none\r
59 #if ((DAP_SWD != 0) || (DAP_JTAG != 0))\r
60 void SWJ_Sequence (uint32_t count, uint8_t *data) {\r
61   uint32_t val;\r
62   uint32_t n;\r
63 \r
64   val = 0;\r
65   n = 0;\r
66   while (count--) {\r
67     if (n == 0) {\r
68       val = *data++;\r
69       n = 8;\r
70     }\r
71     if (val & 1) {\r
72       PIN_SWDIO_TMS_SET();\r
73     } else {\r
74       PIN_SWDIO_TMS_CLR();\r
75     }\r
76     SW_CLOCK_CYCLE();\r
77     val >>= 1;\r
78     n--;\r
79   }\r
80 }\r
81 #endif\r
82 \r
83 \r
84 #if (DAP_SWD != 0)\r
85 \r
86 \r
87 // SWD Transfer I/O\r
88 //   request: A[3:2] RnW APnDP\r
89 //   data:    DATA[31:0]\r
90 //   return:  ACK[2:0]\r
91 #define SWD_TransferFunction(speed)     /**/                                    \\r
92 uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) {                \\r
93   uint32_t ack;                                                                 \\r
94   uint32_t bit;                                                                 \\r
95   uint32_t val;                                                                 \\r
96   uint32_t parity;                                                              \\r
97                                                                                 \\r
98   uint32_t n;                                                                   \\r
99                                                                                 \\r
100   /* Packet Request */                                                          \\r
101   parity = 0;                                                                   \\r
102   SW_WRITE_BIT(1);                      /* Start Bit */                         \\r
103   bit = request >> 0;                                                           \\r
104   SW_WRITE_BIT(bit);                    /* APnDP Bit */                         \\r
105   parity += bit;                                                                \\r
106   bit = request >> 1;                                                           \\r
107   SW_WRITE_BIT(bit);                    /* RnW Bit */                           \\r
108   parity += bit;                                                                \\r
109   bit = request >> 2;                                                           \\r
110   SW_WRITE_BIT(bit);                    /* A2 Bit */                            \\r
111   parity += bit;                                                                \\r
112   bit = request >> 3;                                                           \\r
113   SW_WRITE_BIT(bit);                    /* A3 Bit */                            \\r
114   parity += bit;                                                                \\r
115   SW_WRITE_BIT(parity);                 /* Parity Bit */                        \\r
116   SW_WRITE_BIT(0);                      /* Stop Bit */                          \\r
117   SW_WRITE_BIT(1);                      /* Park Bit */                          \\r
118                                                                                 \\r
119   /* Turnaround */                                                              \\r
120   PIN_SWDIO_OUT_DISABLE();                                                      \\r
121   for (n = DAP_Data.swd_conf.turnaround; n; n--) {                              \\r
122     SW_CLOCK_CYCLE();                                                           \\r
123   }                                                                             \\r
124                                                                                 \\r
125   /* Acknowledge response */                                                    \\r
126   SW_READ_BIT(bit);                                                             \\r
127   ack  = bit << 0;                                                              \\r
128   SW_READ_BIT(bit);                                                             \\r
129   ack |= bit << 1;                                                              \\r
130   SW_READ_BIT(bit);                                                             \\r
131   ack |= bit << 2;                                                              \\r
132                                                                                 \\r
133   if (ack == DAP_TRANSFER_OK) {         /* OK response */                       \\r
134     /* Data transfer */                                                         \\r
135     if (request & DAP_TRANSFER_RnW) {                                           \\r
136       /* Read data */                                                           \\r
137       val = 0;                                                                  \\r
138       parity = 0;                                                               \\r
139       for (n = 32; n; n--) {                                                    \\r
140         SW_READ_BIT(bit);               /* Read RDATA[0:31] */                  \\r
141         parity += bit;                                                          \\r
142         val >>= 1;                                                              \\r
143         val  |= bit << 31;                                                      \\r
144       }                                                                         \\r
145       SW_READ_BIT(bit);                 /* Read Parity */                       \\r
146       if ((parity ^ bit) & 1) {                                                 \\r
147         ack = DAP_TRANSFER_ERROR;                                               \\r
148       }                                                                         \\r
149       if (data) *data = val;                                                    \\r
150       /* Turnaround */                                                          \\r
151       for (n = DAP_Data.swd_conf.turnaround; n; n--) {                          \\r
152         SW_CLOCK_CYCLE();                                                       \\r
153       }                                                                         \\r
154       PIN_SWDIO_OUT_ENABLE();                                                   \\r
155     } else {                                                                    \\r
156       /* Turnaround */                                                          \\r
157       for (n = DAP_Data.swd_conf.turnaround; n; n--) {                          \\r
158         SW_CLOCK_CYCLE();                                                       \\r
159       }                                                                         \\r
160       PIN_SWDIO_OUT_ENABLE();                                                   \\r
161       /* Write data */                                                          \\r
162       val = *data;                                                              \\r
163       parity = 0;                                                               \\r
164       for (n = 32; n; n--) {                                                    \\r
165         SW_WRITE_BIT(val);              /* Write WDATA[0:31] */                 \\r
166         parity += val;                                                          \\r
167         val >>= 1;                                                              \\r
168       }                                                                         \\r
169       SW_WRITE_BIT(parity);             /* Write Parity Bit */                  \\r
170     }                                                                           \\r
171     /* Idle cycles */                                                           \\r
172     n = DAP_Data.transfer.idle_cycles;                                          \\r
173     if (n) {                                                                    \\r
174       PIN_SWDIO_OUT(0);                                                         \\r
175       for (; n; n--) {                                                          \\r
176         SW_CLOCK_CYCLE();                                                       \\r
177       }                                                                         \\r
178     }                                                                           \\r
179     PIN_SWDIO_OUT(1);                                                           \\r
180     return (ack);                                                               \\r
181   }                                                                             \\r
182                                                                                 \\r
183   if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {              \\r
184     /* WAIT or FAULT response */                                                \\r
185     if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0)) {  \\r
186       for (n = 32+1; n; n--) {                                                  \\r
187         SW_CLOCK_CYCLE();               /* Dummy Read RDATA[0:31] + Parity */   \\r
188       }                                                                         \\r
189     }                                                                           \\r
190     /* Turnaround */                                                            \\r
191     for (n = DAP_Data.swd_conf.turnaround; n; n--) {                            \\r
192       SW_CLOCK_CYCLE();                                                         \\r
193     }                                                                           \\r
194     PIN_SWDIO_OUT_ENABLE();                                                     \\r
195     if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0)) {  \\r
196       PIN_SWDIO_OUT(0);                                                         \\r
197       for (n = 32+1; n; n--) {                                                  \\r
198         SW_CLOCK_CYCLE();               /* Dummy Write WDATA[0:31] + Parity */  \\r
199       }                                                                         \\r
200     }                                                                           \\r
201     PIN_SWDIO_OUT(1);                                                           \\r
202     return (ack);                                                               \\r
203   }                                                                             \\r
204                                                                                 \\r
205   /* Protocol error */                                                          \\r
206   for (n = DAP_Data.swd_conf.turnaround + 32 + 1; n; n--) {                     \\r
207     SW_CLOCK_CYCLE();                   /* Back off data phase */               \\r
208   }                                                                             \\r
209   PIN_SWDIO_OUT(1);                                                             \\r
210   return (ack);                                                                 \\r
211 }\r
212 \r
213 \r
214 #undef  PIN_DELAY\r
215 #define PIN_DELAY() PIN_DELAY_FAST()\r
216 SWD_TransferFunction(Fast);\r
217 \r
218 #undef  PIN_DELAY\r
219 #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay)\r
220 SWD_TransferFunction(Slow);\r
221 \r
222 \r
223 // SWD Transfer I/O\r
224 //   request: A[3:2] RnW APnDP\r
225 //   data:    DATA[31:0]\r
226 //   return:  ACK[2:0]\r
227 uint8_t  SWD_Transfer(uint32_t request, uint32_t *data) {\r
228   if (DAP_Data.fast_clock) {\r
229     return SWD_TransferFast(request, data);\r
230   } else {\r
231     return SWD_TransferSlow(request, data);\r
232   }\r
233 }\r
234 \r
235 \r
236 #endif  /* (DAP_SWD != 0) */\r