]> git.gag.com Git - fw/openocd/blob - src/jtag/dummy.c
bfdf0dcccfe37c757b8248f85d5c0ad19f96fb68
[fw/openocd] / src / jtag / dummy.c
1 /***************************************************************************\r
2  *   Copyright (C) 2008 by Ã˜yvind Harboe                                   *\r
3  *   oyvind.harboe@zylin.com                                               *\r
4  *                                                                         *\r
5  *   This program is free software; you can redistribute it and/or modify  *\r
6  *   it under the terms of the GNU General Public License as published by  *\r
7  *   the Free Software Foundation; either version 2 of the License, or     *\r
8  *   (at your option) any later version.                                   *\r
9  *                                                                         *\r
10  *   This program is distributed in the hope that it will be useful,       *\r
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
13  *   GNU General Public License for more details.                          *\r
14  *                                                                         *\r
15  *   You should have received a copy of the GNU General Public License     *\r
16  *   along with this program; if not, write to the                         *\r
17  *   Free Software Foundation, Inc.,                                       *\r
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
19  ***************************************************************************/\r
20 #ifdef HAVE_CONFIG_H\r
21 #include "config.h"\r
22 #endif\r
23 \r
24 #include "replacements.h"\r
25 \r
26 #include "jtag.h"\r
27 #include "bitbang.h"\r
28 \r
29 \r
30 /* my private tap controller state, which tracks state for calling code */\r
31 static tap_state_t dummy_state = TAP_RESET;\r
32 \r
33 static int dummy_clock;         /* edge detector */\r
34 \r
35 static tap_state_t tap_state_transition(tap_state_t cur_state, int tms);\r
36 \r
37 \r
38 int dummy_speed(int speed);\r
39 int dummy_register_commands(struct command_context_s *cmd_ctx);\r
40 int dummy_init(void);\r
41 int dummy_quit(void);\r
42 static int dummy_khz(int khz, int *jtag_speed);\r
43 static int dummy_speed_div(int speed, int *khz);\r
44 \r
45 \r
46 /* The dummy driver is used to easily check the code path\r
47  * where the target is unresponsive.\r
48  */\r
49 jtag_interface_t dummy_interface =\r
50 {\r
51         .name = "dummy",\r
52 \r
53         .execute_queue = bitbang_execute_queue,\r
54 \r
55         .speed = dummy_speed,\r
56         .register_commands = dummy_register_commands,\r
57         .khz = dummy_khz,\r
58         .speed_div = dummy_speed_div,\r
59 \r
60         .init = dummy_init,\r
61         .quit = dummy_quit,\r
62 };\r
63 \r
64 int dummy_read(void);\r
65 void dummy_write(int tck, int tms, int tdi);\r
66 void dummy_reset(int trst, int srst);\r
67 void dummy_led(int on);\r
68 \r
69 bitbang_interface_t dummy_bitbang =\r
70 {\r
71         .read = dummy_read,\r
72         .write = dummy_write,\r
73         .reset = dummy_reset,\r
74         .blink = dummy_led\r
75 };\r
76 \r
77 int dummy_read(void)\r
78 {\r
79         return 1;\r
80 }\r
81 \r
82 \r
83 void dummy_write(int tck, int tms, int tdi)\r
84 {\r
85         /* TAP standard: "state transitions occur on rising edge of clock" */\r
86         if( tck != dummy_clock )\r
87         {\r
88                 if( tck )\r
89                 {\r
90                         int old_state = dummy_state;\r
91                         dummy_state = tap_state_transition( dummy_state, tms );\r
92                         if( old_state != dummy_state )\r
93                                 LOG_DEBUG( "dummy_tap=%s", jtag_state_name(dummy_state) );\r
94                 }\r
95                 dummy_clock = tck;\r
96         }\r
97 }\r
98 \r
99 void dummy_reset(int trst, int srst)\r
100 {\r
101         dummy_clock = 0;\r
102         dummy_state = TAP_RESET;\r
103         LOG_DEBUG( "reset to %s", jtag_state_name(dummy_state) );\r
104 }\r
105 \r
106 static int dummy_khz(int khz, int *jtag_speed)\r
107 {\r
108         if (khz==0)\r
109         {\r
110                 *jtag_speed=0;\r
111         }\r
112         else\r
113         {\r
114                 *jtag_speed=64000/khz;\r
115         }\r
116         return ERROR_OK;\r
117 }\r
118 \r
119 static int dummy_speed_div(int speed, int *khz)\r
120 {\r
121         if (speed==0)\r
122         {\r
123                 *khz = 0;\r
124         }\r
125         else\r
126         {\r
127                 *khz=64000/speed;\r
128         }\r
129 \r
130         return ERROR_OK;\r
131 }\r
132 \r
133 int dummy_speed(int speed)\r
134 {\r
135         return ERROR_OK;\r
136 }\r
137 \r
138 int dummy_register_commands(struct command_context_s *cmd_ctx)\r
139 {\r
140         return ERROR_OK;\r
141 }\r
142 \r
143 int dummy_init(void)\r
144 {\r
145         bitbang_interface = &dummy_bitbang;\r
146 \r
147         return ERROR_OK;\r
148 }\r
149 \r
150 int dummy_quit(void)\r
151 {\r
152         return ERROR_OK;\r
153 }\r
154 \r
155 void dummy_led(int on)\r
156 {\r
157 }\r
158 \r
159 \r
160 /**\r
161  * Function tap_state_transition\r
162  * takes a current TAP state and returns the next state according to the tms value.\r
163  *\r
164  * Even though there is code to duplicate this elsewhere, we do it here a little\r
165  * differently just to get a second opinion, i.e. a verification, on state tracking\r
166  * in that other logic. Plus array lookups without index checking are no favorite thing.\r
167  * This is educational for developers new to TAP controllers.\r
168  */\r
169 static tap_state_t tap_state_transition(tap_state_t cur_state, int tms)\r
170 {\r
171         tap_state_t new_state;\r
172 \r
173         if (tms)\r
174         {\r
175                 switch (cur_state)\r
176                 {\r
177                 case TAP_RESET:\r
178                         new_state = cur_state;\r
179                         break;\r
180                 case TAP_IDLE:\r
181                 case TAP_DRUPDATE:\r
182                 case TAP_IRUPDATE:\r
183                         new_state = TAP_DRSELECT;\r
184                         break;\r
185                 case TAP_DRSELECT:\r
186                         new_state = TAP_IRSELECT;\r
187                         break;\r
188                 case TAP_DRCAPTURE:\r
189                 case TAP_DRSHIFT:\r
190                         new_state = TAP_DREXIT1;\r
191                         break;\r
192                 case TAP_DREXIT1:\r
193                 case TAP_DREXIT2:\r
194                         new_state = TAP_DRUPDATE;\r
195                         break;\r
196                 case TAP_DRPAUSE:\r
197                         new_state = TAP_DREXIT2;\r
198                         break;\r
199                 case TAP_IRSELECT:\r
200                         new_state = TAP_RESET;\r
201                         break;\r
202                 case TAP_IRCAPTURE:\r
203                 case TAP_IRSHIFT:\r
204                         new_state = TAP_IREXIT1;\r
205                         break;\r
206                 case TAP_IREXIT1:\r
207                 case TAP_IREXIT2:\r
208                         new_state = TAP_IRUPDATE;\r
209                         break;\r
210                 case TAP_IRPAUSE:\r
211                         new_state = TAP_IREXIT2;\r
212                         break;\r
213                 default:\r
214                         LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );\r
215                         exit(1);\r
216                         break;\r
217                 }\r
218         }\r
219         else\r
220         {\r
221                 switch (cur_state)\r
222                 {\r
223                 case TAP_RESET:\r
224                 case TAP_IDLE:\r
225                 case TAP_DRUPDATE:\r
226                 case TAP_IRUPDATE:\r
227                         new_state = TAP_IDLE;\r
228                         break;\r
229                 case TAP_DRSELECT:\r
230                         new_state = TAP_DRCAPTURE;\r
231                         break;\r
232                 case TAP_DRCAPTURE:\r
233                 case TAP_DRSHIFT:\r
234                 case TAP_DREXIT2:\r
235                         new_state = TAP_DRSHIFT;\r
236                         break;\r
237                 case TAP_DREXIT1:\r
238                 case TAP_DRPAUSE:\r
239                         new_state = TAP_DRPAUSE;\r
240                         break;\r
241                 case TAP_IRSELECT:\r
242                         new_state = TAP_IRCAPTURE;\r
243                         break;\r
244                 case TAP_IRCAPTURE:\r
245                 case TAP_IRSHIFT:\r
246                 case TAP_IREXIT2:\r
247                         new_state = TAP_IRSHIFT;\r
248                         break;\r
249                 case TAP_IREXIT1:\r
250                 case TAP_IRPAUSE:\r
251                         new_state = TAP_IRPAUSE;\r
252                         break;\r
253                 default:\r
254                         LOG_ERROR( "fatal: invalid argument cur_state=%d", cur_state );\r
255                         exit(1);\r
256                         break;\r
257                 }\r
258         }\r
259 \r
260         return new_state;\r
261 }\r