target: improve robustness of reset command
[openocd.git] / src / target / feroceon.c
1 /***************************************************************************
2 * Copyright (C) 2008-2009 by Marvell Semiconductors, Inc. *
3 * Written by Nicolas Pitre <nico@marvell.com> *
4 * *
5 * Copyright (C) 2008 by Hongtao Zheng *
6 * hontor@126.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
23
24 /*
25 * Marvell Feroceon/Dragonite support.
26 *
27 * The Feroceon core, as found in the Orion and Kirkwood SoCs amongst others,
28 * mimics the ARM926 ICE interface with the following differences:
29 *
30 * - the MOE (method of entry) reporting is not implemented
31 *
32 * - breakpoint/watchpoint comparator #1 is seemingly not implemented
33 *
34 * - due to a different pipeline implementation, some injected debug
35 * instruction sequences have to be somewhat different
36 *
37 * Other issues:
38 *
39 * - asserting DBGRQ doesn't work if target is looping on the undef vector
40 *
41 * - the EICE version signature in the COMMS_CTL reg is next to the flow bits
42 * not at the top, and rather meaningless due to existing discrepencies
43 *
44 * - the DCC channel is half duplex (only one FIFO for both directions) with
45 * seemingly no proper flow control.
46 *
47 * The Dragonite core is the non-mmu version based on the ARM966 model, and
48 * it shares the above issues as well.
49 */
50
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #include "arm926ejs.h"
56 #include "arm966e.h"
57 #include "target_type.h"
58 #include "register.h"
59 #include "arm_opcodes.h"
60
61 static int feroceon_assert_reset(struct target *target)
62 {
63 struct arm *arm = target->arch_info;
64 struct arm7_9_common *arm7_9 = arm->arch_info;
65 int ud = arm7_9->use_dbgrq;
66
67 /* TODO: apply hw reset signal in not examined state */
68 if (!(target_was_examined(target))) {
69 LOG_WARNING("Reset is not asserted because the target is not examined.");
70 LOG_WARNING("Use a reset button or power cycle the target.");
71 return ERROR_TARGET_NOT_EXAMINED;
72 }
73
74 arm7_9->use_dbgrq = 0;
75 if (target->reset_halt)
76 arm7_9_halt(target);
77 arm7_9->use_dbgrq = ud;
78 return arm7_9_assert_reset(target);
79 }
80
81 static int feroceon_dummy_clock_out(struct arm_jtag *jtag_info, uint32_t instr)
82 {
83 struct scan_field fields[3];
84 uint8_t out_buf[4];
85 uint8_t instr_buf[4];
86 uint8_t sysspeed_buf = 0x0;
87 int retval;
88
89 /* prepare buffer */
90 buf_set_u32(out_buf, 0, 32, 0);
91
92 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
93
94 retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
95 if (retval != ERROR_OK)
96 return retval;
97
98 retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
99 if (retval != ERROR_OK)
100 return retval;
101
102 fields[0].num_bits = 32;
103 fields[0].out_value = out_buf;
104 fields[0].in_value = NULL;
105
106 fields[1].num_bits = 3;
107 fields[1].out_value = &sysspeed_buf;
108 fields[1].in_value = NULL;
109
110 fields[2].num_bits = 32;
111 fields[2].out_value = instr_buf;
112 fields[2].in_value = NULL;
113
114 jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
115
116 /* no jtag_add_runtest(0, TAP_DRPAUSE) here */
117
118 return ERROR_OK;
119 }
120
121 static void feroceon_change_to_arm(struct target *target, uint32_t *r0,
122 uint32_t *pc)
123 {
124 struct arm *arm = target->arch_info;
125 struct arm7_9_common *arm7_9 = arm->arch_info;
126 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
127
128 /*
129 * save r0 before using it and put system in ARM state
130 * to allow common handling of ARM and THUMB debugging
131 */
132
133 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
134 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
135 feroceon_dummy_clock_out(jtag_info, ARMV4_5_T_NOP);
136
137 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
138 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
139 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
140 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
141 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
142 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
143
144 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
145 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
146 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
147 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
148 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
149 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
150 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
151
152 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(15), 0, NULL, 0);
153 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
154 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
155 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
156 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
157
158 jtag_execute_queue();
159
160 /*
161 * fix program counter:
162 * MOV R0, PC was the 7th instruction (+12)
163 * reading PC in Thumb state gives address of instruction + 4
164 */
165 *pc -= (12 + 4);
166 }
167
168 static void feroceon_read_core_regs(struct target *target,
169 uint32_t mask, uint32_t *core_regs[16])
170 {
171 int i;
172 struct arm *arm = target->arch_info;
173 struct arm7_9_common *arm7_9 = arm->arch_info;
174 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
175
176 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
177 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
178 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
179
180 for (i = 0; i <= 15; i++)
181 if (mask & (1 << i))
182 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
183
184 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
185 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
186 }
187
188 static void feroceon_read_core_regs_target_buffer(struct target *target,
189 uint32_t mask, void *buffer, int size)
190 {
191 int i;
192 struct arm *arm = target->arch_info;
193 struct arm7_9_common *arm7_9 = arm->arch_info;
194 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
195 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
196 uint32_t *buf_u32 = buffer;
197 uint16_t *buf_u16 = buffer;
198 uint8_t *buf_u8 = buffer;
199
200 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
201 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
202 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
203
204 for (i = 0; i <= 15; i++) {
205 if (mask & (1 << i)) {
206 switch (size) {
207 case 4:
208 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
209 break;
210 case 2:
211 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
212 break;
213 case 1:
214 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
215 break;
216 }
217 }
218 }
219
220 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
221 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
222 }
223
224 static void feroceon_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
225 {
226 struct arm *arm = target->arch_info;
227 struct arm7_9_common *arm7_9 = arm->arch_info;
228 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
229
230 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
231 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
232 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
233 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
234 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
235 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
236 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
237
238 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
239 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
240 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
241 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
242
243 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
244 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
245 }
246
247 static void feroceon_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
248 {
249 struct arm *arm = target->arch_info;
250 struct arm7_9_common *arm7_9 = arm->arch_info;
251 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
252
253 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
254
255 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
256 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
257 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
258 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
259 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
260 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
261 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
262
263 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
264 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
265 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
266 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
267 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
268 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
269 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
270
271 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
272 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
273 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
274 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
275 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
276 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
277 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
278
279 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
280 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
281 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
282 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
283 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
284 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
285 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
286 }
287
288 static void feroceon_write_xpsr_im8(struct target *target,
289 uint8_t xpsr_im, int rot, int spsr)
290 {
291 struct arm *arm = target->arch_info;
292 struct arm7_9_common *arm7_9 = arm->arch_info;
293 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
294
295 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
296
297 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
298 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
299 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
300 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
301 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
302 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
303 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
304 }
305
306 static void feroceon_write_core_regs(struct target *target,
307 uint32_t mask, uint32_t core_regs[16])
308 {
309 int i;
310 struct arm *arm = target->arch_info;
311 struct arm7_9_common *arm7_9 = arm->arch_info;
312 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
313
314 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
315 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
316 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
317
318 for (i = 0; i <= 15; i++)
319 if (mask & (1 << i))
320 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
321
322 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
323 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
324 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
325 }
326
327 static void feroceon_branch_resume(struct target *target)
328 {
329 struct arm *arm = target->arch_info;
330 struct arm7_9_common *arm7_9 = arm->arch_info;
331 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
332
333 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
334 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
335 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
336 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffff9, 0), 0, NULL, 0);
337 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
338
339 arm7_9->need_bypass_before_restart = 1;
340 }
341
342 static void feroceon_branch_resume_thumb(struct target *target)
343 {
344 LOG_DEBUG("-");
345
346 struct arm *arm = target->arch_info;
347 struct arm7_9_common *arm7_9 = arm->arch_info;
348 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
349 uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
350 uint32_t pc = buf_get_u32(arm->pc->value, 0, 32);
351
352 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
353 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
354 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
355 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
356
357 arm9tdmi_clock_out(jtag_info, 0xE28F0001, 0, NULL, 0); /* add r0,pc,#1 */
358 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
359 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
360 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
361
362 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDMIA(0, 0x1), 0, NULL, 0);
363 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
364 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
365
366 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, r0, NULL, 0);
367 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
368 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
369
370 pc = (pc & 2) >> 1;
371 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7e9 + pc), 0, NULL, 0);
372 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 1);
373
374 arm7_9->need_bypass_before_restart = 1;
375 }
376
377 static int feroceon_read_cp15(struct target *target, uint32_t op1,
378 uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
379 {
380 struct arm *arm = target->arch_info;
381 struct arm7_9_common *arm7_9 = arm->arch_info;
382 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
383 int err;
384
385 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRC(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
386 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
387 err = arm7_9_execute_sys_speed(target);
388 if (err != ERROR_OK)
389 return err;
390
391 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, 1, 0, 0), 0, NULL, 0);
392 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
393 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
394 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, value, 0);
395 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
396 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
397 return jtag_execute_queue();
398 }
399
400 static int feroceon_write_cp15(struct target *target, uint32_t op1,
401 uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
402 {
403 struct arm *arm = target->arch_info;
404 struct arm7_9_common *arm7_9 = arm->arch_info;
405 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
406
407 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 1, 0, 0), 0, NULL, 0);
408 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
409 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
410 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, value, NULL, 0);
411 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
412 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
413 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
414
415 arm9tdmi_clock_out(jtag_info, ARMV4_5_MCR(15, op1, 0, CRn, CRm, op2), 0, NULL, 0);
416 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
417 return arm7_9_execute_sys_speed(target);
418 }
419
420 static void feroceon_set_dbgrq(struct target *target)
421 {
422 struct arm *arm = target->arch_info;
423 struct arm7_9_common *arm7_9 = arm->arch_info;
424 struct reg *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
425
426 buf_set_u32(dbg_ctrl->value, 0, 8, 2);
427 embeddedice_store_reg(dbg_ctrl);
428 }
429
430 static void feroceon_enable_single_step(struct target *target, uint32_t next_pc)
431 {
432 struct arm *arm = target->arch_info;
433 struct arm7_9_common *arm7_9 = arm->arch_info;
434
435 /* set a breakpoint there */
436 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], next_pc);
437 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0);
438 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
439 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
440 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
441 }
442
443 static void feroceon_disable_single_step(struct target *target)
444 {
445 struct arm *arm = target->arch_info;
446 struct arm7_9_common *arm7_9 = arm->arch_info;
447
448 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
449 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
450 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
451 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
452 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
453 }
454
455 static int feroceon_examine_debug_reason(struct target *target)
456 {
457 /* the MOE is not implemented */
458 if (target->debug_reason != DBG_REASON_SINGLESTEP)
459 target->debug_reason = DBG_REASON_DBGRQ;
460
461 return ERROR_OK;
462 }
463
464 static int feroceon_bulk_write_memory(struct target *target,
465 uint32_t address, uint32_t count, const uint8_t *buffer)
466 {
467 int retval;
468 struct arm *arm = target->arch_info;
469 struct arm7_9_common *arm7_9 = arm->arch_info;
470 enum arm_state core_state = arm->core_state;
471 uint32_t x, flip, shift, save[7];
472 uint32_t i;
473
474 /*
475 * We can't use the dcc flow control bits, so let's transfer data
476 * with 31 bits and flip the MSB each time a new data word is sent.
477 */
478 static uint32_t dcc_code[] = {
479 0xee115e10, /* 3: mrc p14, 0, r5, c1, c0, 0 */
480 0xe3a0301e, /* 1: mov r3, #30 */
481 0xe3a04002, /* mov r4, #2 */
482 0xee111e10, /* 2: mrc p14, 0, r1, c1, c0, 0 */
483 0xe1310005, /* teq r1, r5 */
484 0x0afffffc, /* beq 1b */
485 0xe1a05001, /* mov r5, r1 */
486 0xe1a01081, /* mov r1, r1, lsl #1 */
487 0xee112e10, /* 3: mrc p14, 0, r2, c1, c0, 0 */
488 0xe1320005, /* teq r2, r5 */
489 0x0afffffc, /* beq 3b */
490 0xe1a05002, /* mov r5, r2 */
491 0xe3c22102, /* bic r2, r2, #0x80000000 */
492 0xe1811332, /* orr r1, r1, r2, lsr r3 */
493 0xe2533001, /* subs r3, r3, #1 */
494 0xe4801004, /* str r1, [r0], #4 */
495 0xe1a01412, /* mov r1, r2, lsl r4 */
496 0xe2844001, /* add r4, r4, #1 */
497 0x4affffed, /* bmi 1b */
498 0xeafffff3, /* b 3b */
499 };
500
501 uint32_t dcc_size = sizeof(dcc_code);
502
503 if (address % 4 != 0)
504 return ERROR_TARGET_UNALIGNED_ACCESS;
505
506 if (!arm7_9->dcc_downloads)
507 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
508
509 /* regrab previously allocated working_area, or allocate a new one */
510 if (!arm7_9->dcc_working_area) {
511 uint8_t dcc_code_buf[dcc_size];
512
513 /* make sure we have a working area */
514 if (target_alloc_working_area(target, dcc_size, &arm7_9->dcc_working_area) != ERROR_OK) {
515 LOG_INFO("no working area available, falling back to memory writes");
516 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
517 }
518
519 /* copy target instructions to target endianness */
520 target_buffer_set_u32_array(target, dcc_code_buf, ARRAY_SIZE(dcc_code), dcc_code);
521
522 /* write DCC code to working area, using the non-optimized
523 * memory write to avoid ending up here again */
524 retval = arm7_9_write_memory_no_opt(target,
525 arm7_9->dcc_working_area->address, 4, dcc_size/4, dcc_code_buf);
526 if (retval != ERROR_OK)
527 return retval;
528 }
529
530 /* backup clobbered processor state */
531 for (i = 0; i <= 5; i++)
532 save[i] = buf_get_u32(arm->core_cache->reg_list[i].value, 0, 32);
533 save[i] = buf_get_u32(arm->pc->value, 0, 32);
534
535 /* set up target address in r0 */
536 buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, address);
537 arm->core_cache->reg_list[0].valid = 1;
538 arm->core_cache->reg_list[0].dirty = 1;
539 arm->core_state = ARM_STATE_ARM;
540
541 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], 0);
542 arm7_9_resume(target, 0, arm7_9->dcc_working_area->address, 1, 1);
543
544 /* send data over */
545 x = 0;
546 flip = 0;
547 shift = 1;
548 for (i = 0; i < count; i++) {
549 uint32_t y = target_buffer_get_u32(target, buffer);
550 uint32_t z = (x >> 1) | (y >> shift) | (flip ^= 0x80000000);
551 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
552 x = y << (32 - shift);
553 if (++shift >= 32 || i + 1 >= count) {
554 z = (x >> 1) | (flip ^= 0x80000000);
555 embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_COMMS_DATA], z);
556 x = 0;
557 shift = 1;
558 }
559 buffer += 4;
560 }
561
562 retval = target_halt(target);
563 if (retval == ERROR_OK)
564 retval = target_wait_state(target, TARGET_HALTED, 500);
565 if (retval == ERROR_OK) {
566 uint32_t endaddress =
567 buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32);
568 if (endaddress != address + count*4) {
569 LOG_ERROR("DCC write failed,"
570 " expected end address 0x%08" PRIx32
571 " got 0x%0" PRIx32 "",
572 address + count*4, endaddress);
573 retval = ERROR_FAIL;
574 }
575 }
576
577 /* restore target state */
578 for (i = 0; i <= 5; i++) {
579 buf_set_u32(arm->core_cache->reg_list[i].value, 0, 32, save[i]);
580 arm->core_cache->reg_list[i].valid = 1;
581 arm->core_cache->reg_list[i].dirty = 1;
582 }
583 buf_set_u32(arm->pc->value, 0, 32, save[i]);
584 arm->pc->valid = 1;
585 arm->pc->dirty = 1;
586 arm->core_state = core_state;
587
588 return retval;
589 }
590
591 static int feroceon_init_target(struct command_context *cmd_ctx,
592 struct target *target)
593 {
594 arm9tdmi_init_target(cmd_ctx, target);
595 return ERROR_OK;
596 }
597
598 static void feroceon_common_setup(struct target *target)
599 {
600 struct arm *arm = target->arch_info;
601 struct arm7_9_common *arm7_9 = arm->arch_info;
602
603 /* override some insn sequence functions */
604 arm7_9->change_to_arm = feroceon_change_to_arm;
605 arm7_9->read_core_regs = feroceon_read_core_regs;
606 arm7_9->read_core_regs_target_buffer = feroceon_read_core_regs_target_buffer;
607 arm7_9->read_xpsr = feroceon_read_xpsr;
608 arm7_9->write_xpsr = feroceon_write_xpsr;
609 arm7_9->write_xpsr_im8 = feroceon_write_xpsr_im8;
610 arm7_9->write_core_regs = feroceon_write_core_regs;
611 arm7_9->branch_resume = feroceon_branch_resume;
612 arm7_9->branch_resume_thumb = feroceon_branch_resume_thumb;
613
614 /* must be implemented with only one comparator */
615 arm7_9->enable_single_step = feroceon_enable_single_step;
616 arm7_9->disable_single_step = feroceon_disable_single_step;
617
618 arm7_9->bulk_write_memory = feroceon_bulk_write_memory;
619
620 /* MOE is not implemented */
621 arm7_9->examine_debug_reason = feroceon_examine_debug_reason;
622
623 /* Note: asserting DBGRQ might not win over the undef exception.
624 If that happens then just use "arm7_9 dbgrq disable". */
625 arm7_9->use_dbgrq = 1;
626 arm7_9->set_special_dbgrq = feroceon_set_dbgrq;
627
628 /* only one working comparator */
629 arm7_9->wp_available_max = 1;
630 arm7_9->wp1_used_default = -1;
631 }
632
633 static int feroceon_target_create(struct target *target, Jim_Interp *interp)
634 {
635 struct arm926ejs_common *arm926ejs = calloc(1, sizeof(struct arm926ejs_common));
636
637 arm926ejs_init_arch_info(target, arm926ejs, target->tap);
638 feroceon_common_setup(target);
639
640 struct arm *arm = target->arch_info;
641 struct arm7_9_common *arm7_9 = arm->arch_info;
642 arm7_9->write_memory = arm926ejs_write_memory;
643
644 /* the standard ARM926 methods don't always work (don't ask...) */
645 arm926ejs->read_cp15 = feroceon_read_cp15;
646 arm926ejs->write_cp15 = feroceon_write_cp15;
647
648 return ERROR_OK;
649 }
650
651 static int dragonite_target_create(struct target *target, Jim_Interp *interp)
652 {
653 struct arm966e_common *arm966e = calloc(1, sizeof(struct arm966e_common));
654
655 arm966e_init_arch_info(target, arm966e, target->tap);
656 feroceon_common_setup(target);
657
658 struct arm *arm = target->arch_info;
659 struct arm7_9_common *arm7_9 = arm->arch_info;
660 arm7_9->write_memory = arm7_9_write_memory;
661
662 return ERROR_OK;
663 }
664
665 static int feroceon_examine(struct target *target)
666 {
667 struct arm *arm;
668 struct arm7_9_common *arm7_9;
669 int retval;
670
671 retval = arm7_9_examine(target);
672 if (retval != ERROR_OK)
673 return retval;
674
675 arm = target->arch_info;
676 arm7_9 = arm->arch_info;
677
678 /* the COMMS_CTRL bits are all contiguous */
679 if (buf_get_u32(arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL].value, 2, 4) != 6)
680 LOG_ERROR("unexpected Feroceon EICE version signature");
681
682 arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].size = 6;
683 arm7_9->eice_cache->reg_list[EICE_DBG_STAT].size = 5;
684 arm7_9->has_monitor_mode = 1;
685
686 /* vector catch reg is not initialized on reset */
687 embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0);
688
689 /* clear monitor mode, enable comparators */
690 embeddedice_read_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
691 jtag_execute_queue();
692 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
693 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 5, 1, 0);
694 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
695
696 return ERROR_OK;
697 }
698
699 struct target_type feroceon_target = {
700 .name = "feroceon",
701
702 .poll = arm7_9_poll,
703 .arch_state = arm926ejs_arch_state,
704
705 .target_request_data = arm7_9_target_request_data,
706
707 .halt = arm7_9_halt,
708 .resume = arm7_9_resume,
709 .step = arm7_9_step,
710
711 .assert_reset = feroceon_assert_reset,
712 .deassert_reset = arm7_9_deassert_reset,
713 .soft_reset_halt = arm926ejs_soft_reset_halt,
714
715 .get_gdb_reg_list = arm_get_gdb_reg_list,
716
717 .read_memory = arm7_9_read_memory,
718 .write_memory = arm7_9_write_memory_opt,
719
720 .checksum_memory = arm_checksum_memory,
721 .blank_check_memory = arm_blank_check_memory,
722
723 .run_algorithm = armv4_5_run_algorithm,
724
725 .add_breakpoint = arm7_9_add_breakpoint,
726 .remove_breakpoint = arm7_9_remove_breakpoint,
727 .add_watchpoint = arm7_9_add_watchpoint,
728 .remove_watchpoint = arm7_9_remove_watchpoint,
729
730 .commands = arm926ejs_command_handlers,
731 .target_create = feroceon_target_create,
732 .init_target = feroceon_init_target,
733 .examine = feroceon_examine,
734 };
735
736 struct target_type dragonite_target = {
737 .name = "dragonite",
738
739 .poll = arm7_9_poll,
740 .arch_state = arm_arch_state,
741
742 .target_request_data = arm7_9_target_request_data,
743
744 .halt = arm7_9_halt,
745 .resume = arm7_9_resume,
746 .step = arm7_9_step,
747
748 .assert_reset = feroceon_assert_reset,
749 .deassert_reset = arm7_9_deassert_reset,
750 .soft_reset_halt = arm7_9_soft_reset_halt,
751
752 .get_gdb_reg_list = arm_get_gdb_reg_list,
753
754 .read_memory = arm7_9_read_memory,
755 .write_memory = arm7_9_write_memory_opt,
756
757 .checksum_memory = arm_checksum_memory,
758 .blank_check_memory = arm_blank_check_memory,
759
760 .run_algorithm = armv4_5_run_algorithm,
761
762 .add_breakpoint = arm7_9_add_breakpoint,
763 .remove_breakpoint = arm7_9_remove_breakpoint,
764 .add_watchpoint = arm7_9_add_watchpoint,
765 .remove_watchpoint = arm7_9_remove_watchpoint,
766
767 .commands = arm966e_command_handlers,
768 .target_create = dragonite_target_create,
769 .init_target = feroceon_init_target,
770 .examine = feroceon_examine,
771 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)