27a8337fcfc79c3b647b5a5cd9220883aa7ee2a3
[openocd.git] / src / target / arm7tdmi.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) 2007,2008 Øyvind Harboe *
9 * oyvind.harboe@zylin.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 "arm7tdmi.h"
31 #include "target_type.h"
32
33
34 /*
35 * For information about ARM7TDMI, see ARM DDI 0210C (r4p1)
36 * or ARM DDI 0029G (r3). "Debug In Depth", Appendix B,
37 * covers JTAG support.
38 */
39
40 #if 0
41 #define _DEBUG_INSTRUCTION_EXECUTION_
42 #endif
43
44 static int arm7tdmi_examine_debug_reason(target_t *target)
45 {
46 int retval = ERROR_OK;
47 /* get pointers to arch-specific information */
48 armv4_5_common_t *armv4_5 = target->arch_info;
49 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
50
51 /* only check the debug reason if we don't know it already */
52 if ((target->debug_reason != DBG_REASON_DBGRQ)
53 && (target->debug_reason != DBG_REASON_SINGLESTEP))
54 {
55 scan_field_t fields[2];
56 uint8_t databus[4];
57 uint8_t breakpoint;
58
59 jtag_set_end_state(TAP_DRPAUSE);
60
61 fields[0].tap = arm7_9->jtag_info.tap;
62 fields[0].num_bits = 1;
63 fields[0].out_value = NULL;
64 fields[0].in_value = &breakpoint;
65
66 fields[1].tap = arm7_9->jtag_info.tap;
67 fields[1].num_bits = 32;
68 fields[1].out_value = NULL;
69 fields[1].in_value = databus;
70
71 if ((retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1)) != ERROR_OK)
72 {
73 return retval;
74 }
75 arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
76
77 jtag_add_dr_scan(2, fields, jtag_set_end_state(TAP_DRPAUSE));
78 if ((retval = jtag_execute_queue()) != ERROR_OK)
79 {
80 return retval;
81 }
82
83 fields[0].in_value = NULL;
84 fields[0].out_value = &breakpoint;
85 fields[1].in_value = NULL;
86 fields[1].out_value = databus;
87
88 jtag_add_dr_scan(2, fields, jtag_set_end_state(TAP_DRPAUSE));
89
90 if (breakpoint & 1)
91 target->debug_reason = DBG_REASON_WATCHPOINT;
92 else
93 target->debug_reason = DBG_REASON_BREAKPOINT;
94 }
95
96 return ERROR_OK;
97 }
98
99 static const int arm7tdmi_num_bits[] = {1, 32};
100
101 static __inline int arm7tdmi_clock_out_inner(arm_jtag_t *jtag_info, uint32_t out, int breakpoint)
102 {
103 uint32_t values[2]={breakpoint, flip_u32(out, 32)};
104
105 jtag_add_dr_out(jtag_info->tap,
106 2,
107 arm7tdmi_num_bits,
108 values,
109 jtag_get_end_state());
110
111 jtag_add_runtest(0, jtag_get_end_state());
112
113 return ERROR_OK;
114 }
115
116 /* put an instruction in the ARM7TDMI pipeline or write the data bus,
117 * and optionally read data
118 *
119 * FIXME remove the unused "deprecated" parameter
120 */
121 static __inline int arm7tdmi_clock_out(arm_jtag_t *jtag_info,
122 uint32_t out, uint32_t *deprecated, int breakpoint)
123 {
124 jtag_set_end_state(TAP_DRPAUSE);
125 arm_jtag_scann(jtag_info, 0x1);
126 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
127
128 return arm7tdmi_clock_out_inner(jtag_info, out, breakpoint);
129 }
130
131 /* clock the target, reading the databus */
132 static int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, uint32_t *in)
133 {
134 int retval = ERROR_OK;
135 scan_field_t fields[2];
136
137 jtag_set_end_state(TAP_DRPAUSE);
138 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
139 {
140 return retval;
141 }
142 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
143
144 fields[0].tap = jtag_info->tap;
145 fields[0].num_bits = 1;
146 fields[0].out_value = NULL;
147 fields[0].in_value = NULL;
148
149 fields[1].tap = jtag_info->tap;
150 fields[1].num_bits = 32;
151 fields[1].out_value = NULL;
152 fields[1].in_value = (uint8_t *)in;
153
154 jtag_add_dr_scan(2, fields, jtag_get_end_state());
155
156 jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
157
158 jtag_add_runtest(0, jtag_get_end_state());
159
160 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
161 if ((retval = jtag_execute_queue()) != ERROR_OK)
162 return retval;
163
164 if (in)
165 LOG_DEBUG("in: 0x%8.8x", *in);
166 else
167 LOG_ERROR("BUG: called with in == NULL");
168 #endif
169
170 return ERROR_OK;
171 }
172
173 void arm_endianness(uint8_t *tmp, void *in, int size, int be, int flip)
174 {
175 uint32_t readback = le_to_h_u32(tmp);
176 if (flip)
177 readback = flip_u32(readback, 32);
178 switch (size)
179 {
180 case 4:
181 if (be)
182 {
183 h_u32_to_be(((uint8_t*)in), readback);
184 } else
185 {
186 h_u32_to_le(((uint8_t*)in), readback);
187 }
188 break;
189 case 2:
190 if (be)
191 {
192 h_u16_to_be(((uint8_t*)in), readback & 0xffff);
193 } else
194 {
195 h_u16_to_le(((uint8_t*)in), readback & 0xffff);
196 }
197 break;
198 case 1:
199 *((uint8_t *)in)= readback & 0xff;
200 break;
201 }
202 }
203
204 static int arm7endianness(jtag_callback_data_t arg,
205 jtag_callback_data_t size, jtag_callback_data_t be,
206 jtag_callback_data_t captured)
207 {
208 uint8_t *in = (uint8_t *)arg;
209
210 arm_endianness((uint8_t *)captured, in, (int)size, (int)be, 1);
211 return ERROR_OK;
212 }
213
214 /* clock the target, and read the databus
215 * the *in pointer points to a buffer where elements of 'size' bytes
216 * are stored in big (be == 1) or little (be == 0) endianness
217 */
218 static int arm7tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info,
219 void *in, int size, int be)
220 {
221 int retval = ERROR_OK;
222 scan_field_t fields[2];
223
224 jtag_set_end_state(TAP_DRPAUSE);
225 if ((retval = arm_jtag_scann(jtag_info, 0x1)) != ERROR_OK)
226 {
227 return retval;
228 }
229 arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
230
231 fields[0].tap = jtag_info->tap;
232 fields[0].num_bits = 1;
233 fields[0].out_value = NULL;
234 fields[0].in_value = NULL;
235
236 fields[1].tap = jtag_info->tap;
237 fields[1].num_bits = 32;
238 fields[1].out_value = NULL;
239 jtag_alloc_in_value32(&fields[1]);
240
241 jtag_add_dr_scan(2, fields, jtag_get_end_state());
242
243 jtag_add_callback4(arm7endianness, (jtag_callback_data_t)in, (jtag_callback_data_t)size, (jtag_callback_data_t)be, (jtag_callback_data_t)fields[1].in_value);
244
245 jtag_add_runtest(0, jtag_get_end_state());
246
247 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
248 {
249 if ((retval = jtag_execute_queue()) != ERROR_OK)
250 {
251 return retval;
252 }
253
254 if (in)
255 {
256 LOG_DEBUG("in: 0x%8.8x", *(uint32_t*)in);
257 }
258 else
259 {
260 LOG_ERROR("BUG: called with in == NULL");
261 }
262 }
263 #endif
264
265 return ERROR_OK;
266 }
267
268 static void arm7tdmi_change_to_arm(target_t *target,
269 uint32_t *r0, uint32_t *pc)
270 {
271 /* get pointers to arch-specific information */
272 armv4_5_common_t *armv4_5 = target->arch_info;
273 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
274 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
275
276 /* save r0 before using it and put system in ARM state
277 * to allow common handling of ARM and THUMB debugging */
278
279 /* fetch STR r0, [r0] */
280 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
281 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
282 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
283 /* nothing fetched, STR r0, [r0] in Execute (2) */
284 arm7tdmi_clock_data_in(jtag_info, r0);
285
286 /* MOV r0, r15 fetched, STR in Decode */
287 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0);
288 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
289 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
290 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
291 /* nothing fetched, STR r0, [r0] in Execute (2) */
292 arm7tdmi_clock_data_in(jtag_info, pc);
293
294 /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
295 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
296 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
297 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
298 /* nothing fetched, data for LDR r0, [PC, #0] */
299 arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);
300 /* nothing fetched, data from previous cycle is written to register */
301 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
302
303 /* fetch BX */
304 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);
305 /* NOP fetched, BX in Decode, MOV in Execute */
306 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
307 /* NOP fetched, BX in Execute (1) */
308 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
309
310 jtag_execute_queue();
311
312 /* fix program counter:
313 * MOV r0, r15 was the 4th instruction (+6)
314 * reading PC in Thumb state gives address of instruction + 4
315 */
316 *pc -= 0xa;
317 }
318
319
320 /* FIX!!! is this a potential performance bottleneck w.r.t. requiring too many
321 * roundtrips when jtag_execute_queue() has a large overhead(e.g. for USB)s?
322 *
323 * The solution is to arrange for a large out/in scan in this loop and
324 * and convert data afterwards.
325 */
326 static void arm7tdmi_read_core_regs(target_t *target,
327 uint32_t mask, uint32_t* core_regs[16])
328 {
329 int i;
330 /* get pointers to arch-specific information */
331 armv4_5_common_t *armv4_5 = target->arch_info;
332 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
333 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
334
335 /* STMIA r0-15, [r0] at debug speed
336 * register values will start to appear on 4th DCLK
337 */
338 arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
339
340 /* fetch NOP, STM in DECODE stage */
341 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
342 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
343 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
344
345 for (i = 0; i <= 15; i++)
346 {
347 if (mask & (1 << i))
348 /* nothing fetched, STM still in EXECUTE (1 + i cycle) */
349 arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
350 }
351 }
352
353 static void arm7tdmi_read_core_regs_target_buffer(target_t *target,
354 uint32_t mask, void* buffer, int size)
355 {
356 int i;
357 /* get pointers to arch-specific information */
358 armv4_5_common_t *armv4_5 = target->arch_info;
359 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
360 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
361 int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
362 uint32_t *buf_u32 = buffer;
363 uint16_t *buf_u16 = buffer;
364 uint8_t *buf_u8 = buffer;
365
366 /* STMIA r0-15, [r0] at debug speed
367 * register values will start to appear on 4th DCLK
368 */
369 arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
370
371 /* fetch NOP, STM in DECODE stage */
372 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
373 /* fetch NOP, STM in EXECUTE stage (1st cycle) */
374 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
375
376 for (i = 0; i <= 15; i++)
377 {
378 /* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */
379 if (mask & (1 << i))
380 {
381 switch (size)
382 {
383 case 4:
384 arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
385 break;
386 case 2:
387 arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
388 break;
389 case 1:
390 arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
391 break;
392 }
393 }
394 }
395 }
396
397 static void arm7tdmi_read_xpsr(target_t *target, uint32_t *xpsr, int spsr)
398 {
399 /* get pointers to arch-specific information */
400 armv4_5_common_t *armv4_5 = target->arch_info;
401 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
402 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
403
404 /* MRS r0, cpsr */
405 arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0);
406
407 /* STR r0, [r15] */
408 arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0);
409 /* fetch NOP, STR in DECODE stage */
410 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
411 /* fetch NOP, STR in EXECUTE stage (1st cycle) */
412 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
413 /* nothing fetched, STR still in EXECUTE (2nd cycle) */
414 arm7tdmi_clock_data_in(jtag_info, xpsr);
415 }
416
417 static void arm7tdmi_write_xpsr(target_t *target, uint32_t xpsr, int spsr)
418 {
419 /* get pointers to arch-specific information */
420 armv4_5_common_t *armv4_5 = target->arch_info;
421 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
422 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
423
424 LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
425
426 /* MSR1 fetched */
427 arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0);
428 /* MSR2 fetched, MSR1 in DECODE */
429 arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0);
430 /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
431 arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0);
432 /* nothing fetched, MSR1 in EXECUTE (2) */
433 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
434 /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
435 arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0);
436 /* nothing fetched, MSR2 in EXECUTE (2) */
437 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
438 /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
439 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
440 /* nothing fetched, MSR3 in EXECUTE (2) */
441 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
442 /* NOP fetched, MSR4 in EXECUTE (1) */
443 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
444 /* nothing fetched, MSR4 in EXECUTE (2) */
445 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
446 }
447
448 static void arm7tdmi_write_xpsr_im8(target_t *target,
449 uint8_t xpsr_im, int rot, int spsr)
450 {
451 /* get pointers to arch-specific information */
452 armv4_5_common_t *armv4_5 = target->arch_info;
453 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
454 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
455
456 LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
457
458 /* MSR fetched */
459 arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0);
460 /* NOP fetched, MSR in DECODE */
461 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
462 /* NOP fetched, MSR in EXECUTE (1) */
463 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
464 /* nothing fetched, MSR in EXECUTE (2) */
465 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
466 }
467
468 static void arm7tdmi_write_core_regs(target_t *target,
469 uint32_t mask, uint32_t core_regs[16])
470 {
471 int i;
472 /* get pointers to arch-specific information */
473 armv4_5_common_t *armv4_5 = target->arch_info;
474 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
475 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
476
477 /* LDMIA r0-15, [r0] at debug speed
478 * register values will start to appear on 4th DCLK
479 */
480 arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0);
481
482 /* fetch NOP, LDM in DECODE stage */
483 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
484 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
485 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
486
487 for (i = 0; i <= 15; i++)
488 {
489 if (mask & (1 << i))
490 /* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
491 arm7tdmi_clock_out_inner(jtag_info, core_regs[i], 0);
492 }
493 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
494 }
495
496 static void arm7tdmi_load_word_regs(target_t *target, uint32_t mask)
497 {
498 /* get pointers to arch-specific information */
499 armv4_5_common_t *armv4_5 = target->arch_info;
500 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
501 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
502
503 /* put system-speed load-multiple into the pipeline */
504 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
505 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
506 arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0);
507 }
508
509 static void arm7tdmi_load_hword_reg(target_t *target, int num)
510 {
511 /* get pointers to arch-specific information */
512 armv4_5_common_t *armv4_5 = target->arch_info;
513 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
514 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
515
516 /* put system-speed load half-word into the pipeline */
517 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
518 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
519 arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0);
520 }
521
522 static void arm7tdmi_load_byte_reg(target_t *target, int num)
523 {
524 /* get pointers to arch-specific information */
525 armv4_5_common_t *armv4_5 = target->arch_info;
526 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
527 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
528
529 /* put system-speed load byte into the pipeline */
530 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
531 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
532 arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0);
533 }
534
535 static void arm7tdmi_store_word_regs(target_t *target, uint32_t mask)
536 {
537 /* get pointers to arch-specific information */
538 armv4_5_common_t *armv4_5 = target->arch_info;
539 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
540 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
541
542 /* put system-speed store-multiple into the pipeline */
543 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
544 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
545 arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0);
546 }
547
548 static void arm7tdmi_store_hword_reg(target_t *target, int num)
549 {
550 /* get pointers to arch-specific information */
551 armv4_5_common_t *armv4_5 = target->arch_info;
552 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
553 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
554
555 /* put system-speed store half-word into the pipeline */
556 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
557 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
558 arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0);
559 }
560
561 static void arm7tdmi_store_byte_reg(target_t *target, int num)
562 {
563 /* get pointers to arch-specific information */
564 armv4_5_common_t *armv4_5 = target->arch_info;
565 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
566 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
567
568 /* put system-speed store byte into the pipeline */
569 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
570 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
571 arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0);
572 }
573
574 static void arm7tdmi_write_pc(target_t *target, uint32_t pc)
575 {
576 /* get pointers to arch-specific information */
577 armv4_5_common_t *armv4_5 = target->arch_info;
578 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
579 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
580
581 /* LDMIA r0-15, [r0] at debug speed
582 * register values will start to appear on 4th DCLK
583 */
584 arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0);
585 /* fetch NOP, LDM in DECODE stage */
586 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
587 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
588 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
589 /* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */
590 arm7tdmi_clock_out_inner(jtag_info, pc, 0);
591 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */
592 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
593 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */
594 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
595 /* fetch NOP, LDM in EXECUTE stage (4th cycle) */
596 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
597 /* fetch NOP, LDM in EXECUTE stage (5th cycle) */
598 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0);
599 }
600
601 static void arm7tdmi_branch_resume(target_t *target)
602 {
603 /* get pointers to arch-specific information */
604 armv4_5_common_t *armv4_5 = target->arch_info;
605 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
606 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
607
608 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
609 arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_B(0xfffffa, 0), 0);
610 }
611
612 static void arm7tdmi_branch_resume_thumb(target_t *target)
613 {
614 LOG_DEBUG("-");
615
616 /* get pointers to arch-specific information */
617 armv4_5_common_t *armv4_5 = target->arch_info;
618 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
619 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
620 reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
621
622 /* LDMIA r0, [r0] at debug speed
623 * register values will start to appear on 4th DCLK
624 */
625 arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0);
626
627 /* fetch NOP, LDM in DECODE stage */
628 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
629 /* fetch NOP, LDM in EXECUTE stage (1st cycle) */
630 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
631 /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
632 arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
633 /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
634 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
635
636 /* Branch and eXchange */
637 arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0);
638
639 embeddedice_read_reg(dbg_stat);
640
641 /* fetch NOP, BX in DECODE stage */
642 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
643
644 /* target is now in Thumb state */
645 embeddedice_read_reg(dbg_stat);
646
647 /* fetch NOP, BX in EXECUTE stage (1st cycle) */
648 arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
649
650 /* target is now in Thumb state */
651 embeddedice_read_reg(dbg_stat);
652
653 /* load r0 value */
654 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
655 /* fetch NOP, LDR in Decode */
656 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
657 /* fetch NOP, LDR in Execute */
658 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
659 /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
660 arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
661 /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
662 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
663
664 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
665 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
666
667 embeddedice_read_reg(dbg_stat);
668
669 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);
670 arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);
671 }
672
673 static void arm7tdmi_build_reg_cache(target_t *target)
674 {
675 reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
676 /* get pointers to arch-specific information */
677 armv4_5_common_t *armv4_5 = target->arch_info;
678
679 (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
680 armv4_5->core_cache = (*cache_p);
681 }
682
683 int arm7tdmi_examine(struct target_s *target)
684 {
685 int retval;
686 armv4_5_common_t *armv4_5 = target->arch_info;
687 arm7_9_common_t *arm7_9 = armv4_5->arch_info;
688 if (!target_was_examined(target))
689 {
690 /* get pointers to arch-specific information */
691 reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
692 reg_cache_t *t = embeddedice_build_reg_cache(target, arm7_9);
693 if (t == NULL)
694 return ERROR_FAIL;
695
696 (*cache_p) = t;
697 arm7_9->eice_cache = (*cache_p);
698
699 if (arm7_9->etm_ctx)
700 {
701 arm_jtag_t *jtag_info = &arm7_9->jtag_info;
702 (*cache_p)->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
703 arm7_9->etm_ctx->reg_cache = (*cache_p)->next;
704 }
705 target_set_examined(target);
706 }
707 if ((retval = embeddedice_setup(target)) != ERROR_OK)
708 return retval;
709 if ((retval = arm7_9_setup(target)) != ERROR_OK)
710 return retval;
711 if (arm7_9->etm_ctx)
712 {
713 if ((retval = etm_setup(target)) != ERROR_OK)
714 return retval;
715 }
716 return ERROR_OK;
717 }
718
719 int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
720 {
721 arm7tdmi_build_reg_cache(target);
722
723 return ERROR_OK;
724 }
725
726 int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, jtag_tap_t *tap)
727 {
728 armv4_5_common_t *armv4_5;
729 arm7_9_common_t *arm7_9;
730
731 arm7_9 = &arm7tdmi->arm7_9_common;
732 armv4_5 = &arm7_9->armv4_5_common;
733
734 /* prepare JTAG information for the new target */
735 arm7_9->jtag_info.tap = tap;
736 arm7_9->jtag_info.scann_size = 4;
737
738 /* register arch-specific functions */
739 arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;
740 arm7_9->change_to_arm = arm7tdmi_change_to_arm;
741 arm7_9->read_core_regs = arm7tdmi_read_core_regs;
742 arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;
743 arm7_9->read_xpsr = arm7tdmi_read_xpsr;
744
745 arm7_9->write_xpsr = arm7tdmi_write_xpsr;
746 arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8;
747 arm7_9->write_core_regs = arm7tdmi_write_core_regs;
748
749 arm7_9->load_word_regs = arm7tdmi_load_word_regs;
750 arm7_9->load_hword_reg = arm7tdmi_load_hword_reg;
751 arm7_9->load_byte_reg = arm7tdmi_load_byte_reg;
752
753 arm7_9->store_word_regs = arm7tdmi_store_word_regs;
754 arm7_9->store_hword_reg = arm7tdmi_store_hword_reg;
755 arm7_9->store_byte_reg = arm7tdmi_store_byte_reg;
756
757 arm7_9->write_pc = arm7tdmi_write_pc;
758 arm7_9->branch_resume = arm7tdmi_branch_resume;
759 arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb;
760
761 arm7_9->enable_single_step = arm7_9_enable_eice_step;
762 arm7_9->disable_single_step = arm7_9_disable_eice_step;
763
764 arm7_9->post_debug_entry = NULL;
765
766 arm7_9->pre_restore_context = NULL;
767 arm7_9->post_restore_context = NULL;
768
769 /* initialize arch-specific breakpoint handling */
770 arm7_9->arm_bkpt = 0xdeeedeee;
771 arm7_9->thumb_bkpt = 0xdeee;
772
773 arm7_9->dbgreq_adjust_pc = 2;
774 arm7_9->arch_info = arm7tdmi;
775
776 arm7tdmi->arch_info = NULL;
777 arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC;
778
779 arm7_9_init_arch_info(target, arm7_9);
780
781 return ERROR_OK;
782 }
783
784 static int arm7tdmi_target_create(struct target_s *target, Jim_Interp *interp)
785 {
786 arm7tdmi_common_t *arm7tdmi;
787
788 arm7tdmi = calloc(1,sizeof(arm7tdmi_common_t));
789 arm7tdmi_init_arch_info(target, arm7tdmi, target->tap);
790 arm7tdmi->arm7_9_common.armv4_5_common.is_armv4 = true;
791
792 return ERROR_OK;
793 }
794
795 /** Holds methods for ARM7TDMI targets. */
796 target_type_t arm7tdmi_target =
797 {
798 .name = "arm7tdmi",
799
800 .poll = arm7_9_poll,
801 .arch_state = armv4_5_arch_state,
802
803 .target_request_data = arm7_9_target_request_data,
804
805 .halt = arm7_9_halt,
806 .resume = arm7_9_resume,
807 .step = arm7_9_step,
808
809 .assert_reset = arm7_9_assert_reset,
810 .deassert_reset = arm7_9_deassert_reset,
811 .soft_reset_halt = arm7_9_soft_reset_halt,
812
813 .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
814
815 .read_memory = arm7_9_read_memory,
816 .write_memory = arm7_9_write_memory,
817 .bulk_write_memory = arm7_9_bulk_write_memory,
818 .checksum_memory = arm7_9_checksum_memory,
819 .blank_check_memory = arm7_9_blank_check_memory,
820
821 .run_algorithm = armv4_5_run_algorithm,
822
823 .add_breakpoint = arm7_9_add_breakpoint,
824 .remove_breakpoint = arm7_9_remove_breakpoint,
825 .add_watchpoint = arm7_9_add_watchpoint,
826 .remove_watchpoint = arm7_9_remove_watchpoint,
827
828 .register_commands = arm7_9_register_commands,
829 .target_create = arm7tdmi_target_create,
830 .init_target = arm7tdmi_init_target,
831 .examine = arm7tdmi_examine,
832 };

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)