arm_jtag_t -> struct arm_jtag
[openocd.git] / src / target / arm9tdmi.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2008 by Hongtao Zheng *
9 * hontor@126.com *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "arm9tdmi.h"
31 #include "target_type.h"
32
33
34 /*
35 * NOTE: this holds code that's used with multiple ARM9 processors:
36 * - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores
37 * - ARM9E-S (ARMv5TE) ... in ARM946, ARM966, and ARM968 cores
38 * - ARM9EJS (ARMv5TEJ) ... in ARM926 core
39 *
40 * In short, the file name is a misnomer ... it is NOT specific to
41 * that first generation ARM9 processor, or cores using it.
42 */
43
44 #if 0
45 #define _DEBUG_INSTRUCTION_EXECUTION_
46 #endif
47
48 static const arm9tdmi_vector_t arm9tdmi_vectors[] =
49 {
50 {"reset", ARM9TDMI_RESET_VECTOR},
51 {"undef", ARM9TDMI_UNDEF_VECTOR},
52 {"swi", ARM9TDMI_SWI_VECTOR},
53 {"pabt", ARM9TDMI_PABT_VECTOR},
54 {"dabt", ARM9TDMI_DABT_VECTOR},
55 {"irq", ARM9TDMI_IRQ_VECTOR},
56 {"fiq", ARM9TDMI_FIQ_VECTOR},
57 {0, 0},
58 };
59
60 int arm9tdmi_examine_debug_reason(target_t *target)
61 {
62 int retval = ERROR_OK;
63 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
64
65 /* only check the debug reason if we don't know it already */
66 if ((target->debug_reason != DBG_REASON_DBGRQ)
67 && (target->debug_reason != DBG_REASON_SINGLESTEP))
68 {
69 struct scan_field fields[3];
70 uint8_t databus[4];
71 uint8_t instructionbus[4];
72 uint8_t debug_reason;
73
74 jtag_set_end_state(TAP_DRPAUSE);
75
76 fields[0].tap = arm7_9->jtag_info.tap;
77 fields[0].num_bits = 32;
78 fields[0].out_value = NULL;
79 fields[0].in_value = databus;
80
81 fields[1].tap = arm7_9->jtag_info.tap;
82 fields[1].num_bits = 3;
83 fields[1].out_value = NULL;
84 fields[1].in_value = &debug_reason;
85
86 fields[2].tap = arm7_9->jtag_info.tap;
87 fields[2].num_bits = 32;
88 fields[2].out_value = NULL;
89 fields[2].in_value = instructionbus;
90
91 if ((retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1)) != ERROR_OK)
92 {
93 return retval;
94 }
95 arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
96
97 jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_DRPAUSE));
98 if ((retval = jtag_execute_queue()) != ERROR_OK)
99 {
100 return retval;
101 }
102
103 fields[0].in_value = NULL;
104 fields[0].out_value = databus;
105 fields[1].in_value = NULL;
106 fields[1].out_value = &debug_reason;
107 fields[2].in_value = NULL;
108 fields[2].out_value = instructionbus;
109
110 jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_DRPAUSE));
111
112 if (debug_reason & 0x4)
113 if (debug_reason & 0x2)
114 target->debug_reason = DBG_REASON_WPTANDBKPT;
115 else
116 target->debug_reason = DBG_REASON_WATCHPOINT;
117 else
118 target->debug_reason = DBG_REASON_BREAKPOINT;
119 }
120
121 return ERROR_OK;
122 }
123
124 /* put an instruction in the ARM9TDMI pipeline or write the data bus,
125 * and optionally read data
126 */
127 int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr,
128 uint32_t out, uint32_t *in, int sysspeed)
129 {
130 int retval = ERROR_OK;
131 struct scan_field fields[3];
132 uint8_t out_buf[4];
133 uint8_t instr_buf[4];
134 uint8_t sysspeed_buf = 0x0;
135
136 /* prepare buffer */
137 buf_set_u32(out_buf, 0, 32, out);
138
139 buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
140
141 if (sysspeed)
142 buf_set_u32(&sysspeed_buf, 2, 1, 1);
143
144 jtag_set_end_state(TAP_DRPAUSE);
145 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
146 {
147 return retval;
148 }
149
150 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
151
152 fields[0].tap = jtag_info->tap;
153 fields[0].num_bits = 32;
154 fields[0].out_value = out_buf;
155 fields[0].in_value = NULL;
156
157 fields[1].tap = jtag_info->tap;
158 fields[1].num_bits = 3;
159 fields[1].out_value = &sysspeed_buf;
160 fields[1].in_value = NULL;
161
162 fields[2].tap = jtag_info->tap;
163 fields[2].num_bits = 32;
164 fields[2].out_value = instr_buf;
165 fields[2].in_value = NULL;
166
167 if (in)
168 {
169 fields[0].in_value = (uint8_t *)in;
170 jtag_add_dr_scan(3, fields, jtag_get_end_state());
171
172 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
173 }
174 else
175 {
176 jtag_add_dr_scan(3, fields, jtag_get_end_state());
177 }
178
179 jtag_add_runtest(0, jtag_get_end_state());
180
181 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
182 {
183 if ((retval = jtag_execute_queue()) != ERROR_OK)
184 {
185 return retval;
186 }
187
188 if (in)
189 {
190 LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
191 }
192 else
193 LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
194 }
195 #endif
196
197 return ERROR_OK;
198 }
199
200 /* just read data (instruction and data-out = don't care) */
201 int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
202 {
203 int retval = ERROR_OK;;
204 struct scan_field fields[3];
205
206 jtag_set_end_state(TAP_DRPAUSE);
207 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
208 {
209 return retval;
210 }
211
212 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
213
214 fields[0].tap = jtag_info->tap;
215 fields[0].num_bits = 32;
216 fields[0].out_value = NULL;
217 fields[0].in_value = (uint8_t *)in;
218
219 fields[1].tap = jtag_info->tap;
220 fields[1].num_bits = 3;
221 fields[1].out_value = NULL;
222 fields[1].in_value = NULL;
223
224 fields[2].tap = jtag_info->tap;
225 fields[2].num_bits = 32;
226 fields[2].out_value = NULL;
227 fields[2].in_value = NULL;
228
229 jtag_add_dr_scan(3, fields, jtag_get_end_state());
230
231 jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
232
233 jtag_add_runtest(0, jtag_get_end_state());
234
235 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
236 {
237 if ((retval = jtag_execute_queue()) != ERROR_OK)
238 {
239 return retval;
240 }
241
242 if (in)
243 {
244 LOG_DEBUG("in: 0x%8.8x", *in);
245 }
246 else
247 {
248 LOG_ERROR("BUG: called with in == NULL");
249 }
250 }
251 #endif
252
253 return ERROR_OK;
254 }
255
256 extern void arm_endianness(uint8_t *tmp, void *in, int size, int be, int flip);
257
258 static int arm9endianness(jtag_callback_data_t arg,
259 jtag_callback_data_t size, jtag_callback_data_t be,
260 jtag_callback_data_t captured)
261 {
262 uint8_t *in = (uint8_t *)arg;
263
264 arm_endianness((uint8_t *)captured, in, (int)size, (int)be, 0);
265 return ERROR_OK;
266 }
267
268 /* clock the target, and read the databus
269 * the *in pointer points to a buffer where elements of 'size' bytes
270 * are stored in big (be == 1) or little (be == 0) endianness
271 */
272 int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
273 void *in, int size, int be)
274 {
275 int retval = ERROR_OK;
276 struct scan_field fields[3];
277
278 jtag_set_end_state(TAP_DRPAUSE);
279 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
280 {
281 return retval;
282 }
283
284 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
285
286 fields[0].tap = jtag_info->tap;
287 fields[0].num_bits = 32;
288 fields[0].out_value = NULL;
289 jtag_alloc_in_value32(&fields[0]);
290
291 fields[1].tap = jtag_info->tap;
292 fields[1].num_bits = 3;
293 fields[1].out_value = NULL;
294 fields[1].in_value = NULL;
295
296 fields[2].tap = jtag_info->tap;
297 fields[2].num_bits = 32;
298 fields[2].out_value = NULL;
299 fields[2].in_value = NULL;
300
301 jtag_add_dr_scan(3, fields, jtag_get_end_state());
302
303 jtag_add_callback4(arm9endianness, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)fields[0].in_value);
304
305 jtag_add_runtest(0, jtag_get_end_state());
306
307 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
308 {
309 if ((retval = jtag_execute_queue()) != ERROR_OK)
310 {
311 return retval;
312 }
313
314 if (in)
315 {
316 LOG_DEBUG("in: 0x%8.8x", *(uint32_t*)in);
317 }
318 else
319 {
320 LOG_ERROR("BUG: called with in == NULL");
321 }
322 }
323 #endif
324
325 return ERROR_OK;
326 }
327
328 static void arm9tdmi_change_to_arm(target_t *target,
329 uint32_t *r0, uint32_t *pc)
330 {
331 int retval = ERROR_OK;
332 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
333 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
334
335 /* save r0 before using it and put system in ARM state
336 * to allow common handling of ARM and THUMB debugging */
337
338 /* fetch STR r0, [r0] */
339 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
340 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
341 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
342 /* STR r0, [r0] in Memory */
343 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
344
345 /* MOV r0, r15 fetched, STR in Decode */
346 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
347 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
348 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
349 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
350 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
351 /* nothing fetched, STR r0, [r0] in Memory */
352 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
353
354 /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
355 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
356 /* LDR in Decode */
357 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
358 /* LDR in Execute */
359 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
360 /* LDR in Memory (to account for interlock) */
361 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
362
363 /* fetch BX */
364 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
365 /* NOP fetched, BX in Decode, MOV in Execute */
366 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
367 /* NOP fetched, BX in Execute (1) */
368 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
369
370 if ((retval = jtag_execute_queue()) != ERROR_OK)
371 {
372 return;
373 }
374
375 /* fix program counter:
376 * MOV r0, r15 was the 5th instruction (+8)
377 * reading PC in Thumb state gives address of instruction + 4
378 */
379 *pc -= 0xc;
380 }
381
382 void arm9tdmi_read_core_regs(target_t *target,
383 uint32_t mask, uint32_t* core_regs[16])
384 {
385 int i;
386 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
387 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
388
389 /* STMIA r0-15, [r0] at debug speed
390 * register values will start to appear on 4th DCLK
391 */
392 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
393
394 /* fetch NOP, STM in DECODE stage */
395 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
396 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
397 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
398
399 for (i = 0; i <= 15; i++)
400 {
401 if (mask & (1 << i))
402 /* nothing fetched, STM in MEMORY (i'th cycle) */
403 arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
404 }
405 }
406
407 static void arm9tdmi_read_core_regs_target_buffer(target_t *target,
408 uint32_t mask, void* buffer, int size)
409 {
410 int i;
411 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
412 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
413 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
414 uint32_t *buf_u32 = buffer;
415 uint16_t *buf_u16 = buffer;
416 uint8_t *buf_u8 = buffer;
417
418 /* STMIA r0-15, [r0] at debug speed
419 * register values will start to appear on 4th DCLK
420 */
421 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
422
423 /* fetch NOP, STM in DECODE stage */
424 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
425 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
426 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
427
428 for (i = 0; i <= 15; i++)
429 {
430 if (mask & (1 << i))
431 /* nothing fetched, STM in MEMORY (i'th cycle) */
432 switch (size)
433 {
434 case 4:
435 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
436 break;
437 case 2:
438 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
439 break;
440 case 1:
441 arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
442 break;
443 }
444 }
445 }
446
447 static void arm9tdmi_read_xpsr(target_t *target, uint32_t *xpsr, int spsr)
448 {
449 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
450 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
451
452 /* MRS r0, cpsr */
453 arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
454 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
455 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
456 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
457 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
458
459 /* STR r0, [r15] */
460 arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
461 /* fetch NOP, STR in DECODE stage */
462 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
463 /* fetch NOP, STR in EXECUTE stage (1st cycle) */
464 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
465 /* nothing fetched, STR in MEMORY */
466 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
467 }
468
469 static void arm9tdmi_write_xpsr(target_t *target, uint32_t xpsr, int spsr)
470 {
471 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
472 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
473
474 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
475
476 /* MSR1 fetched */
477 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
478 /* MSR2 fetched, MSR1 in DECODE */
479 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
480 /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
481 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
482 /* nothing fetched, MSR1 in EXECUTE (2) */
483 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
484 /* nothing fetched, MSR1 in EXECUTE (3) */
485 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
486 /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
487 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
488 /* nothing fetched, MSR2 in EXECUTE (2) */
489 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
490 /* nothing fetched, MSR2 in EXECUTE (3) */
491 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
492 /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
493 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
494 /* nothing fetched, MSR3 in EXECUTE (2) */
495 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
496 /* nothing fetched, MSR3 in EXECUTE (3) */
497 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
498 /* NOP fetched, MSR4 in EXECUTE (1) */
499 /* last MSR writes flags, which takes only one cycle */
500 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
501 }
502
503 static void arm9tdmi_write_xpsr_im8(target_t *target,
504 uint8_t xpsr_im, int rot, int spsr)
505 {
506 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
507 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
508
509 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
510
511 /* MSR fetched */
512 arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
513 /* NOP fetched, MSR in DECODE */
514 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
515 /* NOP fetched, MSR in EXECUTE (1) */
516 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
517
518 /* rot == 4 writes flags, which takes only one cycle */
519 if (rot != 4)
520 {
521 /* nothing fetched, MSR in EXECUTE (2) */
522 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
523 /* nothing fetched, MSR in EXECUTE (3) */
524 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
525 }
526 }
527
528 void arm9tdmi_write_core_regs(target_t *target,
529 uint32_t mask, uint32_t core_regs[16])
530 {
531 int i;
532 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
533 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
534
535 /* LDMIA r0-15, [r0] at debug speed
536 * register values will start to appear on 4th DCLK
537 */
538 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
539
540 /* fetch NOP, LDM in DECODE stage */
541 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
542 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
543 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
544
545 for (i = 0; i <= 15; i++)
546 {
547 if (mask & (1 << i))
548 /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
549 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
550 }
551 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
552 }
553
554 void arm9tdmi_load_word_regs(target_t *target, uint32_t mask)
555 {
556 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
557 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
558
559 /* put system-speed load-multiple into the pipeline */
560 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
561 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
562 }
563
564 void arm9tdmi_load_hword_reg(target_t *target, int num)
565 {
566 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
567 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
568
569 /* put system-speed load half-word into the pipeline */
570 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
571 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
572 }
573
574 void arm9tdmi_load_byte_reg(target_t *target, int num)
575 {
576 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
577 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
578
579 /* put system-speed load byte into the pipeline */
580 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
581 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
582 }
583
584 void arm9tdmi_store_word_regs(target_t *target, uint32_t mask)
585 {
586 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
587 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
588
589 /* put system-speed store-multiple into the pipeline */
590 arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
591 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
592 }
593
594 void arm9tdmi_store_hword_reg(target_t *target, int num)
595 {
596 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
597 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
598
599 /* put system-speed store half-word into the pipeline */
600 arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
601 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
602 }
603
604 void arm9tdmi_store_byte_reg(target_t *target, int num)
605 {
606 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
607 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
608
609 /* put system-speed store byte into the pipeline */
610 arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
611 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
612 }
613
614 static void arm9tdmi_write_pc(target_t *target, uint32_t pc)
615 {
616 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
617 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
618
619 /* LDMIA r0-15, [r0] at debug speed
620 * register values will start to appear on 4th DCLK
621 */
622 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
623
624 /* fetch NOP, LDM in DECODE stage */
625 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
626 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
627 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
628 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
629 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
630 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
631 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
632 /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
633 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
634 /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
635 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
636 }
637
638 void arm9tdmi_branch_resume(target_t *target)
639 {
640 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
641 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
642
643 arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
644 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
645 }
646
647 static void arm9tdmi_branch_resume_thumb(target_t *target)
648 {
649 LOG_DEBUG("-");
650
651 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
652 struct armv4_5_common_s *armv4_5 = &arm7_9->armv4_5_common;
653 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
654 reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
655
656 /* LDMIA r0-15, [r0] at debug speed
657 * register values will start to appear on 4th DCLK
658 */
659 arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
660
661 /* fetch NOP, LDM in DECODE stage */
662 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
663 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
664 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
665 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
666 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
667 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
668 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
669
670 /* Branch and eXchange */
671 arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
672
673 embeddedice_read_reg(dbg_stat);
674
675 /* fetch NOP, BX in DECODE stage */
676 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
677
678 embeddedice_read_reg(dbg_stat);
679
680 /* fetch NOP, BX in EXECUTE stage (1st cycle) */
681 arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
682
683 /* target is now in Thumb state */
684 embeddedice_read_reg(dbg_stat);
685
686 /* load r0 value, MOV_IM in Decode*/
687 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
688 /* fetch NOP, LDR in Decode, MOV_IM in Execute */
689 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
690 /* fetch NOP, LDR in Execute */
691 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
692 /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
693 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
694 /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
695 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
696
697 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
698 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
699
700 embeddedice_read_reg(dbg_stat);
701
702 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
703 arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
704 }
705
706 void arm9tdmi_enable_single_step(target_t *target, uint32_t next_pc)
707 {
708 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
709
710 if (arm7_9->has_single_step)
711 {
712 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
713 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
714 }
715 else
716 {
717 arm7_9_enable_eice_step(target, next_pc);
718 }
719 }
720
721 void arm9tdmi_disable_single_step(target_t *target)
722 {
723 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
724
725 if (arm7_9->has_single_step)
726 {
727 buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
728 embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
729 }
730 else
731 {
732 arm7_9_disable_eice_step(target);
733 }
734 }
735
736 static void arm9tdmi_build_reg_cache(target_t *target)
737 {
738 reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
739 struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
740
741 (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
742 armv4_5->core_cache = (*cache_p);
743 }
744
745 int arm9tdmi_examine(struct target_s *target)
746 {
747 int retval;
748 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
749
750 if (!target_was_examined(target))
751 {
752 reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
753 reg_cache_t *t;
754 /* one extra register (vector catch) */
755 t = embeddedice_build_reg_cache(target, arm7_9);
756 if (t == NULL)
757 return ERROR_FAIL;
758 (*cache_p) = t;
759 arm7_9->eice_cache = (*cache_p);
760
761 if (arm7_9->armv4_5_common.etm)
762 {
763 struct arm_jtag *jtag_info = &arm7_9->jtag_info;
764 (*cache_p)->next = etm_build_reg_cache(target,
765 jtag_info, arm7_9->armv4_5_common.etm);
766 arm7_9->armv4_5_common.etm->reg_cache = (*cache_p)->next;
767 }
768 target_set_examined(target);
769 }
770 if ((retval = embeddedice_setup(target)) != ERROR_OK)
771 return retval;
772 if ((retval = arm7_9_setup(target)) != ERROR_OK)
773 return retval;
774 if (arm7_9->armv4_5_common.etm)
775 {
776 if ((retval = etm_setup(target)) != ERROR_OK)
777 return retval;
778 }
779 return ERROR_OK;
780 }
781
782 int arm9tdmi_init_target(struct command_context_s *cmd_ctx,
783 struct target_s *target)
784 {
785 arm9tdmi_build_reg_cache(target);
786 return ERROR_OK;
787 }
788
789 int arm9tdmi_init_arch_info(target_t *target, struct arm9tdmi_common *arm9tdmi, struct jtag_tap *tap)
790 {
791 armv4_5_common_t *armv4_5;
792 struct arm7_9_common *arm7_9;
793
794 arm7_9 = &arm9tdmi->arm7_9_common;
795 armv4_5 = &arm7_9->armv4_5_common;
796
797 /* prepare JTAG information for the new target */
798 arm7_9->jtag_info.tap = tap;
799 arm7_9->jtag_info.scann_size = 5;
800
801 /* register arch-specific functions */
802 arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
803 arm7_9->change_to_arm = arm9tdmi_change_to_arm;
804 arm7_9->read_core_regs = arm9tdmi_read_core_regs;
805 arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
806 arm7_9->read_xpsr = arm9tdmi_read_xpsr;
807
808 arm7_9->write_xpsr = arm9tdmi_write_xpsr;
809 arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
810 arm7_9->write_core_regs = arm9tdmi_write_core_regs;
811
812 arm7_9->load_word_regs = arm9tdmi_load_word_regs;
813 arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
814 arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
815
816 arm7_9->store_word_regs = arm9tdmi_store_word_regs;
817 arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
818 arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
819
820 arm7_9->write_pc = arm9tdmi_write_pc;
821 arm7_9->branch_resume = arm9tdmi_branch_resume;
822 arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
823
824 arm7_9->enable_single_step = arm9tdmi_enable_single_step;
825 arm7_9->disable_single_step = arm9tdmi_disable_single_step;
826
827 arm7_9->post_debug_entry = NULL;
828
829 arm7_9->pre_restore_context = NULL;
830 arm7_9->post_restore_context = NULL;
831
832 /* initialize arch-specific breakpoint handling */
833 arm7_9->arm_bkpt = 0xdeeedeee;
834 arm7_9->thumb_bkpt = 0xdeee;
835
836 arm7_9->dbgreq_adjust_pc = 3;
837
838 arm7_9_init_arch_info(target, arm7_9);
839
840 /* override use of DBGRQ, this is safe on ARM9TDMI */
841 arm7_9->use_dbgrq = 1;
842
843 /* all ARM9s have the vector catch register */
844 arm7_9->has_vector_catch = 1;
845
846 return ERROR_OK;
847 }
848
849 static int arm9tdmi_target_create(struct target_s *target, Jim_Interp *interp)
850 {
851 struct arm9tdmi_common *arm9tdmi = calloc(1,sizeof(struct arm9tdmi_common));
852
853 arm9tdmi_init_arch_info(target, arm9tdmi, target->tap);
854 arm9tdmi->arm7_9_common.armv4_5_common.is_armv4 = true;
855
856 return ERROR_OK;
857 }
858
859 COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command)
860 {
861 target_t *target = get_current_target(cmd_ctx);
862 struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
863 reg_t *vector_catch;
864 uint32_t vector_catch_value;
865
866 /* it's uncommon, but some ARM7 chips can support this */
867 if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC
868 || !arm7_9->has_vector_catch) {
869 command_print(cmd_ctx, "target doesn't have EmbeddedICE "
870 "with vector_catch");
871 return ERROR_TARGET_INVALID;
872 }
873
874 vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
875
876 /* read the vector catch register if necessary */
877 if (!vector_catch->valid)
878 embeddedice_read_reg(vector_catch);
879
880 /* get the current setting */
881 vector_catch_value = buf_get_u32(vector_catch->value, 0, 8);
882
883 if (argc > 0)
884 {
885 vector_catch_value = 0x0;
886 if (strcmp(args[0], "all") == 0)
887 {
888 vector_catch_value = 0xdf;
889 }
890 else if (strcmp(args[0], "none") == 0)
891 {
892 /* do nothing */
893 }
894 else
895 {
896 for (unsigned i = 0; i < argc; i++)
897 {
898 /* go through list of vectors */
899 unsigned j;
900 for (j = 0; arm9tdmi_vectors[j].name; j++)
901 {
902 if (strcmp(args[i], arm9tdmi_vectors[j].name) == 0)
903 {
904 vector_catch_value |= arm9tdmi_vectors[j].value;
905 break;
906 }
907 }
908
909 /* complain if vector wasn't found */
910 if (!arm9tdmi_vectors[j].name)
911 {
912 command_print(cmd_ctx, "vector '%s' not found, leaving current setting unchanged", args[i]);
913
914 /* reread current setting */
915 vector_catch_value = buf_get_u32(
916 vector_catch->value,
917 0, 8);
918
919 break;
920 }
921 }
922 }
923
924 /* store new settings */
925 buf_set_u32(vector_catch->value, 0, 8, vector_catch_value);
926 embeddedice_store_reg(vector_catch);
927 }
928
929 /* output current settings */
930 for (unsigned i = 0; arm9tdmi_vectors[i].name; i++) {
931 command_print(cmd_ctx, "%s: %s", arm9tdmi_vectors[i].name,
932 (vector_catch_value & arm9tdmi_vectors[i].value)
933 ? "catch" : "don't catch");
934 }
935
936 return ERROR_OK;
937 }
938
939 int arm9tdmi_register_commands(struct command_context_s *cmd_ctx)
940 {
941 int retval;
942 command_t *arm9tdmi_cmd;
943
944 retval = arm7_9_register_commands(cmd_ctx);
945 arm9tdmi_cmd = register_command(cmd_ctx, NULL, "arm9",
946 NULL, COMMAND_ANY,
947 "arm9 specific commands");
948 register_command(cmd_ctx, arm9tdmi_cmd, "vector_catch",
949 handle_arm9tdmi_catch_vectors_command, COMMAND_EXEC,
950 "arm9 vector_catch [all|none|reset|undef|swi|pabt|dabt|irq|fiq] ...");
951
952 return retval;
953 }
954
955 /** Holds methods for ARM9TDMI targets. */
956 target_type_t arm9tdmi_target =
957 {
958 .name = "arm9tdmi",
959
960 .poll = arm7_9_poll,
961 .arch_state = armv4_5_arch_state,
962
963 .target_request_data = arm7_9_target_request_data,
964
965 .halt = arm7_9_halt,
966 .resume = arm7_9_resume,
967 .step = arm7_9_step,
968
969 .assert_reset = arm7_9_assert_reset,
970 .deassert_reset = arm7_9_deassert_reset,
971 .soft_reset_halt = arm7_9_soft_reset_halt,
972
973 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
974
975 .read_memory = arm7_9_read_memory,
976 .write_memory = arm7_9_write_memory,
977 .bulk_write_memory = arm7_9_bulk_write_memory,
978 .checksum_memory = arm7_9_checksum_memory,
979 .blank_check_memory = arm7_9_blank_check_memory,
980
981 .run_algorithm = armv4_5_run_algorithm,
982
983 .add_breakpoint = arm7_9_add_breakpoint,
984 .remove_breakpoint = arm7_9_remove_breakpoint,
985 .add_watchpoint = arm7_9_add_watchpoint,
986 .remove_watchpoint = arm7_9_remove_watchpoint,
987
988 .register_commands = arm9tdmi_register_commands,
989 .target_create = arm9tdmi_target_create,
990 .init_target = arm9tdmi_init_target,
991 .examine = arm9tdmi_examine,
992 };

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)