ARM: keep a handle to the PC
[openocd.git] / src / target / cortex_a8.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2006 by Magnus Lundin *
6 * lundin@mlu.mine.nu *
7 * *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
11 * Copyright (C) 2009 by Dirk Behme *
12 * dirk.behme@gmail.com - copy from cortex_m3 *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28 * *
29 * Cortex-A8(tm) TRM, ARM DDI 0344H *
30 * *
31 ***************************************************************************/
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include "breakpoints.h"
37 #include "cortex_a8.h"
38 #include "register.h"
39 #include "target_request.h"
40 #include "target_type.h"
41 #include "arm_opcodes.h"
42
43 static int cortex_a8_poll(struct target *target);
44 static int cortex_a8_debug_entry(struct target *target);
45 static int cortex_a8_restore_context(struct target *target, bool bpwp);
46 static int cortex_a8_set_breakpoint(struct target *target,
47 struct breakpoint *breakpoint, uint8_t matchmode);
48 static int cortex_a8_unset_breakpoint(struct target *target,
49 struct breakpoint *breakpoint);
50 static int cortex_a8_dap_read_coreregister_u32(struct target *target,
51 uint32_t *value, int regnum);
52 static int cortex_a8_dap_write_coreregister_u32(struct target *target,
53 uint32_t value, int regnum);
54 /*
55 * FIXME do topology discovery using the ROM; don't
56 * assume this is an OMAP3.
57 */
58 #define swjdp_memoryap 0
59 #define swjdp_debugap 1
60 #define OMAP3530_DEBUG_BASE 0x54011000
61
62 /*
63 * Cortex-A8 Basic debug access, very low level assumes state is saved
64 */
65 static int cortex_a8_init_debug_access(struct target *target)
66 {
67 struct armv7a_common *armv7a = target_to_armv7a(target);
68 struct swjdp_common *swjdp = &armv7a->swjdp_info;
69
70 int retval;
71 uint32_t dummy;
72
73 LOG_DEBUG(" ");
74
75 /* Unlocking the debug registers for modification */
76 /* The debugport might be uninitialised so try twice */
77 retval = mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
78 if (retval != ERROR_OK)
79 mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
80 /* Clear Sticky Power Down status Bit in PRSR to enable access to
81 the registers in the Core Power Domain */
82 retval = mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_PRSR, &dummy);
83 /* Enabling of instruction execution in debug mode is done in debug_entry code */
84
85 /* Resync breakpoint registers */
86
87 /* Since this is likley called from init or reset, update targtet state information*/
88 cortex_a8_poll(target);
89
90 return retval;
91 }
92
93 /* To reduce needless round-trips, pass in a pointer to the current
94 * DSCR value. Initialize it to zero if you just need to know the
95 * value on return from this function; or DSCR_INSTR_COMP if you
96 * happen to know that no instruction is pending.
97 */
98 static int cortex_a8_exec_opcode(struct target *target,
99 uint32_t opcode, uint32_t *dscr_p)
100 {
101 uint32_t dscr;
102 int retval;
103 struct armv7a_common *armv7a = target_to_armv7a(target);
104 struct swjdp_common *swjdp = &armv7a->swjdp_info;
105
106 dscr = dscr_p ? *dscr_p : 0;
107
108 LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
109
110 /* Wait for InstrCompl bit to be set */
111 while ((dscr & DSCR_INSTR_COMP) == 0)
112 {
113 retval = mem_ap_read_atomic_u32(swjdp,
114 armv7a->debug_base + CPUDBG_DSCR, &dscr);
115 if (retval != ERROR_OK)
116 {
117 LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
118 return retval;
119 }
120 }
121
122 mem_ap_write_u32(swjdp, armv7a->debug_base + CPUDBG_ITR, opcode);
123
124 do
125 {
126 retval = mem_ap_read_atomic_u32(swjdp,
127 armv7a->debug_base + CPUDBG_DSCR, &dscr);
128 if (retval != ERROR_OK)
129 {
130 LOG_ERROR("Could not read DSCR register");
131 return retval;
132 }
133 }
134 while ((dscr & DSCR_INSTR_COMP) == 0); /* Wait for InstrCompl bit to be set */
135
136 if (dscr_p)
137 *dscr_p = dscr;
138
139 return retval;
140 }
141
142 /**************************************************************************
143 Read core register with very few exec_opcode, fast but needs work_area.
144 This can cause problems with MMU active.
145 **************************************************************************/
146 static int cortex_a8_read_regs_through_mem(struct target *target, uint32_t address,
147 uint32_t * regfile)
148 {
149 int retval = ERROR_OK;
150 struct armv7a_common *armv7a = target_to_armv7a(target);
151 struct swjdp_common *swjdp = &armv7a->swjdp_info;
152
153 cortex_a8_dap_read_coreregister_u32(target, regfile, 0);
154 cortex_a8_dap_write_coreregister_u32(target, address, 0);
155 cortex_a8_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL);
156 dap_ap_select(swjdp, swjdp_memoryap);
157 mem_ap_read_buf_u32(swjdp, (uint8_t *)(&regfile[1]), 4*15, address);
158 dap_ap_select(swjdp, swjdp_debugap);
159
160 return retval;
161 }
162
163 static int cortex_a8_dap_read_coreregister_u32(struct target *target,
164 uint32_t *value, int regnum)
165 {
166 int retval = ERROR_OK;
167 uint8_t reg = regnum&0xFF;
168 uint32_t dscr = 0;
169 struct armv7a_common *armv7a = target_to_armv7a(target);
170 struct swjdp_common *swjdp = &armv7a->swjdp_info;
171
172 if (reg > 17)
173 return retval;
174
175 if (reg < 15)
176 {
177 /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0" 0xEE00nE15 */
178 cortex_a8_exec_opcode(target,
179 ARMV4_5_MCR(14, 0, reg, 0, 5, 0),
180 &dscr);
181 }
182 else if (reg == 15)
183 {
184 /* "MOV r0, r15"; then move r0 to DCCTX */
185 cortex_a8_exec_opcode(target, 0xE1A0000F, &dscr);
186 cortex_a8_exec_opcode(target,
187 ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
188 &dscr);
189 }
190 else
191 {
192 /* "MRS r0, CPSR" or "MRS r0, SPSR"
193 * then move r0 to DCCTX
194 */
195 cortex_a8_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr);
196 cortex_a8_exec_opcode(target,
197 ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
198 &dscr);
199 }
200
201 /* Wait for DTRRXfull then read DTRRTX */
202 while ((dscr & DSCR_DTR_TX_FULL) == 0)
203 {
204 retval = mem_ap_read_atomic_u32(swjdp,
205 armv7a->debug_base + CPUDBG_DSCR, &dscr);
206 }
207
208 retval = mem_ap_read_atomic_u32(swjdp,
209 armv7a->debug_base + CPUDBG_DTRTX, value);
210 LOG_DEBUG("read DCC 0x%08" PRIx32, *value);
211
212 return retval;
213 }
214
215 static int cortex_a8_dap_write_coreregister_u32(struct target *target,
216 uint32_t value, int regnum)
217 {
218 int retval = ERROR_OK;
219 uint8_t Rd = regnum&0xFF;
220 uint32_t dscr;
221 struct armv7a_common *armv7a = target_to_armv7a(target);
222 struct swjdp_common *swjdp = &armv7a->swjdp_info;
223
224 LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);
225
226 /* Check that DCCRX is not full */
227 retval = mem_ap_read_atomic_u32(swjdp,
228 armv7a->debug_base + CPUDBG_DSCR, &dscr);
229 if (dscr & DSCR_DTR_RX_FULL)
230 {
231 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
232 /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode 0xEE000E15 */
233 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
234 &dscr);
235 }
236
237 if (Rd > 17)
238 return retval;
239
240 /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */
241 LOG_DEBUG("write DCC 0x%08" PRIx32, value);
242 retval = mem_ap_write_u32(swjdp,
243 armv7a->debug_base + CPUDBG_DTRRX, value);
244
245 if (Rd < 15)
246 {
247 /* DCCRX to Rn, "MCR p14, 0, Rn, c0, c5, 0", 0xEE00nE15 */
248 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0),
249 &dscr);
250 }
251 else if (Rd == 15)
252 {
253 /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
254 * then "mov r15, r0"
255 */
256 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
257 &dscr);
258 cortex_a8_exec_opcode(target, 0xE1A0F000, &dscr);
259 }
260 else
261 {
262 /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
263 * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields)
264 */
265 cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
266 &dscr);
267 cortex_a8_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1),
268 &dscr);
269
270 /* "Prefetch flush" after modifying execution status in CPSR */
271 if (Rd == 16)
272 cortex_a8_exec_opcode(target,
273 ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
274 &dscr);
275 }
276
277 return retval;
278 }
279
280 /* Write to memory mapped registers directly with no cache or mmu handling */
281 static int cortex_a8_dap_write_memap_register_u32(struct target *target, uint32_t address, uint32_t value)
282 {
283 int retval;
284 struct armv7a_common *armv7a = target_to_armv7a(target);
285 struct swjdp_common *swjdp = &armv7a->swjdp_info;
286
287 retval = mem_ap_write_atomic_u32(swjdp, address, value);
288
289 return retval;
290 }
291
292 /*
293 * Cortex-A8 implementation of Debug Programmer's Model
294 *
295 * NOTE the invariant: these routines return with DSCR_INSTR_COMP set,
296 * so there's no need to poll for it before executing an instruction.
297 *
298 * NOTE that in several of these cases the "stall" mode might be useful.
299 * It'd let us queue a few operations together... prepare/finish might
300 * be the places to enable/disable that mode.
301 */
302
303 static inline struct cortex_a8_common *dpm_to_a8(struct arm_dpm *dpm)
304 {
305 return container_of(dpm, struct cortex_a8_common, armv7a_common.dpm);
306 }
307
308 static int cortex_a8_write_dcc(struct cortex_a8_common *a8, uint32_t data)
309 {
310 LOG_DEBUG("write DCC 0x%08" PRIx32, data);
311 return mem_ap_write_u32(&a8->armv7a_common.swjdp_info,
312 a8->armv7a_common.debug_base + CPUDBG_DTRRX, data);
313 }
314
315 static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
316 uint32_t *dscr_p)
317 {
318 struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
319 uint32_t dscr = DSCR_INSTR_COMP;
320 int retval;
321
322 if (dscr_p)
323 dscr = *dscr_p;
324
325 /* Wait for DTRRXfull */
326 while ((dscr & DSCR_DTR_TX_FULL) == 0) {
327 retval = mem_ap_read_atomic_u32(swjdp,
328 a8->armv7a_common.debug_base + CPUDBG_DSCR,
329 &dscr);
330 }
331
332 retval = mem_ap_read_atomic_u32(swjdp,
333 a8->armv7a_common.debug_base + CPUDBG_DTRTX, data);
334 //LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
335
336 if (dscr_p)
337 *dscr_p = dscr;
338
339 return retval;
340 }
341
342 static int cortex_a8_dpm_prepare(struct arm_dpm *dpm)
343 {
344 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
345 struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
346 uint32_t dscr;
347 int retval;
348
349 /* set up invariant: INSTR_COMP is set after ever DPM operation */
350 do {
351 retval = mem_ap_read_atomic_u32(swjdp,
352 a8->armv7a_common.debug_base + CPUDBG_DSCR,
353 &dscr);
354 } while ((dscr & DSCR_INSTR_COMP) == 0);
355
356 /* this "should never happen" ... */
357 if (dscr & DSCR_DTR_RX_FULL) {
358 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
359 /* Clear DCCRX */
360 retval = cortex_a8_exec_opcode(
361 a8->armv7a_common.armv4_5_common.target,
362 ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
363 &dscr);
364 }
365
366 return retval;
367 }
368
369 static int cortex_a8_dpm_finish(struct arm_dpm *dpm)
370 {
371 /* REVISIT what could be done here? */
372 return ERROR_OK;
373 }
374
375 static int cortex_a8_instr_write_data_dcc(struct arm_dpm *dpm,
376 uint32_t opcode, uint32_t data)
377 {
378 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
379 int retval;
380 uint32_t dscr = DSCR_INSTR_COMP;
381
382 retval = cortex_a8_write_dcc(a8, data);
383
384 return cortex_a8_exec_opcode(
385 a8->armv7a_common.armv4_5_common.target,
386 opcode,
387 &dscr);
388 }
389
390 static int cortex_a8_instr_write_data_r0(struct arm_dpm *dpm,
391 uint32_t opcode, uint32_t data)
392 {
393 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
394 uint32_t dscr = DSCR_INSTR_COMP;
395 int retval;
396
397 retval = cortex_a8_write_dcc(a8, data);
398
399 /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
400 retval = cortex_a8_exec_opcode(
401 a8->armv7a_common.armv4_5_common.target,
402 ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
403 &dscr);
404
405 /* then the opcode, taking data from R0 */
406 retval = cortex_a8_exec_opcode(
407 a8->armv7a_common.armv4_5_common.target,
408 opcode,
409 &dscr);
410
411 return retval;
412 }
413
414 static int cortex_a8_instr_cpsr_sync(struct arm_dpm *dpm)
415 {
416 struct target *target = dpm->arm->target;
417 uint32_t dscr = DSCR_INSTR_COMP;
418
419 /* "Prefetch flush" after modifying execution status in CPSR */
420 return cortex_a8_exec_opcode(target,
421 ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
422 &dscr);
423 }
424
425 static int cortex_a8_instr_read_data_dcc(struct arm_dpm *dpm,
426 uint32_t opcode, uint32_t *data)
427 {
428 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
429 int retval;
430 uint32_t dscr = DSCR_INSTR_COMP;
431
432 /* the opcode, writing data to DCC */
433 retval = cortex_a8_exec_opcode(
434 a8->armv7a_common.armv4_5_common.target,
435 opcode,
436 &dscr);
437
438 return cortex_a8_read_dcc(a8, data, &dscr);
439 }
440
441
442 static int cortex_a8_instr_read_data_r0(struct arm_dpm *dpm,
443 uint32_t opcode, uint32_t *data)
444 {
445 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
446 uint32_t dscr = DSCR_INSTR_COMP;
447 int retval;
448
449 /* the opcode, writing data to R0 */
450 retval = cortex_a8_exec_opcode(
451 a8->armv7a_common.armv4_5_common.target,
452 opcode,
453 &dscr);
454
455 /* write R0 to DCC */
456 retval = cortex_a8_exec_opcode(
457 a8->armv7a_common.armv4_5_common.target,
458 ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
459 &dscr);
460
461 return cortex_a8_read_dcc(a8, data, &dscr);
462 }
463
464 static int cortex_a8_bpwp_enable(struct arm_dpm *dpm, unsigned index,
465 uint32_t addr, uint32_t control)
466 {
467 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
468 uint32_t vr = a8->armv7a_common.debug_base;
469 uint32_t cr = a8->armv7a_common.debug_base;
470 int retval;
471
472 switch (index) {
473 case 0 ... 15: /* breakpoints */
474 vr += CPUDBG_BVR_BASE;
475 cr += CPUDBG_BCR_BASE;
476 break;
477 case 16 ... 31: /* watchpoints */
478 vr += CPUDBG_WVR_BASE;
479 cr += CPUDBG_WCR_BASE;
480 index -= 16;
481 break;
482 default:
483 return ERROR_FAIL;
484 }
485 vr += 4 * index;
486 cr += 4 * index;
487
488 LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
489 (unsigned) vr, (unsigned) cr);
490
491 retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
492 vr, addr);
493 if (retval != ERROR_OK)
494 return retval;
495 retval = cortex_a8_dap_write_memap_register_u32(dpm->arm->target,
496 cr, control);
497 return retval;
498 }
499
500 static int cortex_a8_bpwp_disable(struct arm_dpm *dpm, unsigned index)
501 {
502 struct cortex_a8_common *a8 = dpm_to_a8(dpm);
503 uint32_t cr;
504
505 switch (index) {
506 case 0 ... 15:
507 cr = a8->armv7a_common.debug_base + CPUDBG_BCR_BASE;
508 break;
509 case 16 ... 31:
510 cr = a8->armv7a_common.debug_base + CPUDBG_WCR_BASE;
511 index -= 16;
512 break;
513 default:
514 return ERROR_FAIL;
515 }
516 cr += 4 * index;
517
518 LOG_DEBUG("A8: bpwp disable, cr %08x", (unsigned) cr);
519
520 /* clear control register */
521 return cortex_a8_dap_write_memap_register_u32(dpm->arm->target, cr, 0);
522 }
523
524 static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
525 {
526 struct arm_dpm *dpm = &a8->armv7a_common.dpm;
527 int retval;
528
529 dpm->arm = &a8->armv7a_common.armv4_5_common;
530 dpm->didr = didr;
531
532 dpm->prepare = cortex_a8_dpm_prepare;
533 dpm->finish = cortex_a8_dpm_finish;
534
535 dpm->instr_write_data_dcc = cortex_a8_instr_write_data_dcc;
536 dpm->instr_write_data_r0 = cortex_a8_instr_write_data_r0;
537 dpm->instr_cpsr_sync = cortex_a8_instr_cpsr_sync;
538
539 dpm->instr_read_data_dcc = cortex_a8_instr_read_data_dcc;
540 dpm->instr_read_data_r0 = cortex_a8_instr_read_data_r0;
541
542 dpm->bpwp_enable = cortex_a8_bpwp_enable;
543 dpm->bpwp_disable = cortex_a8_bpwp_disable;
544
545 retval = arm_dpm_setup(dpm);
546 if (retval == ERROR_OK)
547 retval = arm_dpm_initialize(dpm);
548
549 return retval;
550 }
551
552
553 /*
554 * Cortex-A8 Run control
555 */
556
557 static int cortex_a8_poll(struct target *target)
558 {
559 int retval = ERROR_OK;
560 uint32_t dscr;
561 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
562 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
563 struct swjdp_common *swjdp = &armv7a->swjdp_info;
564 enum target_state prev_target_state = target->state;
565 uint8_t saved_apsel = dap_ap_get_select(swjdp);
566
567 dap_ap_select(swjdp, swjdp_debugap);
568 retval = mem_ap_read_atomic_u32(swjdp,
569 armv7a->debug_base + CPUDBG_DSCR, &dscr);
570 if (retval != ERROR_OK)
571 {
572 dap_ap_select(swjdp, saved_apsel);
573 return retval;
574 }
575 cortex_a8->cpudbg_dscr = dscr;
576
577 if ((dscr & 0x3) == 0x3)
578 {
579 if (prev_target_state != TARGET_HALTED)
580 {
581 /* We have a halting debug event */
582 LOG_DEBUG("Target halted");
583 target->state = TARGET_HALTED;
584 if ((prev_target_state == TARGET_RUNNING)
585 || (prev_target_state == TARGET_RESET))
586 {
587 retval = cortex_a8_debug_entry(target);
588 if (retval != ERROR_OK)
589 return retval;
590
591 target_call_event_callbacks(target,
592 TARGET_EVENT_HALTED);
593 }
594 if (prev_target_state == TARGET_DEBUG_RUNNING)
595 {
596 LOG_DEBUG(" ");
597
598 retval = cortex_a8_debug_entry(target);
599 if (retval != ERROR_OK)
600 return retval;
601
602 target_call_event_callbacks(target,
603 TARGET_EVENT_DEBUG_HALTED);
604 }
605 }
606 }
607 else if ((dscr & 0x3) == 0x2)
608 {
609 target->state = TARGET_RUNNING;
610 }
611 else
612 {
613 LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr);
614 target->state = TARGET_UNKNOWN;
615 }
616
617 dap_ap_select(swjdp, saved_apsel);
618
619 return retval;
620 }
621
622 static int cortex_a8_halt(struct target *target)
623 {
624 int retval = ERROR_OK;
625 uint32_t dscr;
626 struct armv7a_common *armv7a = target_to_armv7a(target);
627 struct swjdp_common *swjdp = &armv7a->swjdp_info;
628 uint8_t saved_apsel = dap_ap_get_select(swjdp);
629 dap_ap_select(swjdp, swjdp_debugap);
630
631 /*
632 * Tell the core to be halted by writing DRCR with 0x1
633 * and then wait for the core to be halted.
634 */
635 retval = mem_ap_write_atomic_u32(swjdp,
636 armv7a->debug_base + CPUDBG_DRCR, 0x1);
637
638 /*
639 * enter halting debug mode
640 */
641 mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DSCR, &dscr);
642 retval = mem_ap_write_atomic_u32(swjdp,
643 armv7a->debug_base + CPUDBG_DSCR, dscr | DSCR_HALT_DBG_MODE);
644
645 if (retval != ERROR_OK)
646 goto out;
647
648 do {
649 mem_ap_read_atomic_u32(swjdp,
650 armv7a->debug_base + CPUDBG_DSCR, &dscr);
651 } while ((dscr & DSCR_CORE_HALTED) == 0);
652
653 target->debug_reason = DBG_REASON_DBGRQ;
654
655 out:
656 dap_ap_select(swjdp, saved_apsel);
657 return retval;
658 }
659
660 static int cortex_a8_resume(struct target *target, int current,
661 uint32_t address, int handle_breakpoints, int debug_execution)
662 {
663 struct armv7a_common *armv7a = target_to_armv7a(target);
664 struct arm *armv4_5 = &armv7a->armv4_5_common;
665 struct swjdp_common *swjdp = &armv7a->swjdp_info;
666
667 // struct breakpoint *breakpoint = NULL;
668 uint32_t resume_pc, dscr;
669
670 uint8_t saved_apsel = dap_ap_get_select(swjdp);
671 dap_ap_select(swjdp, swjdp_debugap);
672
673 if (!debug_execution)
674 target_free_all_working_areas(target);
675
676 #if 0
677 if (debug_execution)
678 {
679 /* Disable interrupts */
680 /* We disable interrupts in the PRIMASK register instead of
681 * masking with C_MASKINTS,
682 * This is probably the same issue as Cortex-M3 Errata 377493:
683 * C_MASKINTS in parallel with disabled interrupts can cause
684 * local faults to not be taken. */
685 buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
686 armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
687 armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;
688
689 /* Make sure we are in Thumb mode */
690 buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
691 buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24));
692 armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
693 armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
694 }
695 #endif
696
697 /* current = 1: continue on current pc, otherwise continue at <address> */
698 resume_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
699 if (!current)
700 resume_pc = address;
701
702 /* Make sure that the Armv7 gdb thumb fixups does not
703 * kill the return address
704 */
705 switch (armv4_5->core_state)
706 {
707 case ARM_STATE_ARM:
708 resume_pc &= 0xFFFFFFFC;
709 break;
710 case ARM_STATE_THUMB:
711 case ARM_STATE_THUMB_EE:
712 /* When the return address is loaded into PC
713 * bit 0 must be 1 to stay in Thumb state
714 */
715 resume_pc |= 0x1;
716 break;
717 case ARM_STATE_JAZELLE:
718 LOG_ERROR("How do I resume into Jazelle state??");
719 return ERROR_FAIL;
720 }
721 LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
722 buf_set_u32(armv4_5->pc->value, 0, 32, resume_pc);
723 armv4_5->pc->dirty = 1;
724 armv4_5->pc->valid = 1;
725
726 cortex_a8_restore_context(target, handle_breakpoints);
727
728 #if 0
729 /* the front-end may request us not to handle breakpoints */
730 if (handle_breakpoints)
731 {
732 /* Single step past breakpoint at current address */
733 if ((breakpoint = breakpoint_find(target, resume_pc)))
734 {
735 LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
736 cortex_m3_unset_breakpoint(target, breakpoint);
737 cortex_m3_single_step_core(target);
738 cortex_m3_set_breakpoint(target, breakpoint);
739 }
740 }
741
742 #endif
743 /* Restart core and wait for it to be started
744 * NOTE: this clears DSCR_ITR_EN and other bits.
745 *
746 * REVISIT: for single stepping, we probably want to
747 * disable IRQs by default, with optional override...
748 */
749 mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DRCR, 0x2);
750
751 do {
752 mem_ap_read_atomic_u32(swjdp,
753 armv7a->debug_base + CPUDBG_DSCR, &dscr);
754 } while ((dscr & DSCR_CORE_RESTARTED) == 0);
755
756 target->debug_reason = DBG_REASON_NOTHALTED;
757 target->state = TARGET_RUNNING;
758
759 /* registers are now invalid */
760 register_cache_invalidate(armv4_5->core_cache);
761
762 if (!debug_execution)
763 {
764 target->state = TARGET_RUNNING;
765 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
766 LOG_DEBUG("target resumed at 0x%" PRIx32, resume_pc);
767 }
768 else
769 {
770 target->state = TARGET_DEBUG_RUNNING;
771 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
772 LOG_DEBUG("target debug resumed at 0x%" PRIx32, resume_pc);
773 }
774
775 dap_ap_select(swjdp, saved_apsel);
776
777 return ERROR_OK;
778 }
779
780 static int cortex_a8_debug_entry(struct target *target)
781 {
782 int i;
783 uint32_t regfile[16], cpsr, dscr;
784 int retval = ERROR_OK;
785 struct working_area *regfile_working_area = NULL;
786 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
787 struct armv7a_common *armv7a = target_to_armv7a(target);
788 struct arm *armv4_5 = &armv7a->armv4_5_common;
789 struct swjdp_common *swjdp = &armv7a->swjdp_info;
790 struct reg *reg;
791
792 LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a8->cpudbg_dscr);
793
794 /* REVISIT surely we should not re-read DSCR !! */
795 mem_ap_read_atomic_u32(swjdp,
796 armv7a->debug_base + CPUDBG_DSCR, &dscr);
797
798 /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any
799 * imprecise data aborts get discarded by issuing a Data
800 * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4).
801 */
802
803 /* Enable the ITR execution once we are in debug mode */
804 dscr |= DSCR_ITR_EN;
805 retval = mem_ap_write_atomic_u32(swjdp,
806 armv7a->debug_base + CPUDBG_DSCR, dscr);
807
808 /* Examine debug reason */
809 arm_dpm_report_dscr(&armv7a->dpm, cortex_a8->cpudbg_dscr);
810
811 /* save address of instruction that triggered the watchpoint? */
812 if (target->debug_reason == DBG_REASON_WATCHPOINT) {
813 uint32_t wfar;
814
815 retval = mem_ap_read_atomic_u32(swjdp,
816 armv7a->debug_base + CPUDBG_WFAR,
817 &wfar);
818 arm_dpm_report_wfar(&armv7a->dpm, wfar);
819 }
820
821 /* REVISIT fast_reg_read is never set ... */
822
823 /* Examine target state and mode */
824 if (cortex_a8->fast_reg_read)
825 target_alloc_working_area(target, 64, &regfile_working_area);
826
827 /* First load register acessible through core debug port*/
828 if (!regfile_working_area)
829 {
830 retval = arm_dpm_read_current_registers(&armv7a->dpm);
831 }
832 else
833 {
834 dap_ap_select(swjdp, swjdp_memoryap);
835 cortex_a8_read_regs_through_mem(target,
836 regfile_working_area->address, regfile);
837 dap_ap_select(swjdp, swjdp_memoryap);
838 target_free_working_area(target, regfile_working_area);
839
840 /* read Current PSR */
841 cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
842 dap_ap_select(swjdp, swjdp_debugap);
843 LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
844
845 arm_set_cpsr(armv4_5, cpsr);
846
847 /* update cache */
848 for (i = 0; i <= ARM_PC; i++)
849 {
850 reg = arm_reg_current(armv4_5, i);
851
852 buf_set_u32(reg->value, 0, 32, regfile[i]);
853 reg->valid = 1;
854 reg->dirty = 0;
855 }
856
857 /* Fixup PC Resume Address */
858 if (cpsr & (1 << 5))
859 {
860 // T bit set for Thumb or ThumbEE state
861 regfile[ARM_PC] -= 4;
862 }
863 else
864 {
865 // ARM state
866 regfile[ARM_PC] -= 8;
867 }
868
869 reg = armv4_5->pc;
870 buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
871 reg->dirty = reg->valid;
872 }
873
874 #if 0
875 /* TODO, Move this */
876 uint32_t cp15_control_register, cp15_cacr, cp15_nacr;
877 cortex_a8_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
878 LOG_DEBUG("cp15_control_register = 0x%08x", cp15_control_register);
879
880 cortex_a8_read_cp(target, &cp15_cacr, 15, 0, 1, 0, 2);
881 LOG_DEBUG("cp15 Coprocessor Access Control Register = 0x%08x", cp15_cacr);
882
883 cortex_a8_read_cp(target, &cp15_nacr, 15, 0, 1, 1, 2);
884 LOG_DEBUG("cp15 Nonsecure Access Control Register = 0x%08x", cp15_nacr);
885 #endif
886
887 /* Are we in an exception handler */
888 // armv4_5->exception_number = 0;
889 if (armv7a->post_debug_entry)
890 armv7a->post_debug_entry(target);
891
892 return retval;
893 }
894
895 static void cortex_a8_post_debug_entry(struct target *target)
896 {
897 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
898 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
899 int retval;
900
901 /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
902 retval = armv7a->armv4_5_common.mrc(target, 15,
903 0, 0, /* op1, op2 */
904 1, 0, /* CRn, CRm */
905 &cortex_a8->cp15_control_reg);
906 LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a8->cp15_control_reg);
907
908 if (armv7a->armv4_5_mmu.armv4_5_cache.ctype == -1)
909 {
910 uint32_t cache_type_reg;
911
912 /* MRC p15,0,<Rt>,c0,c0,1 ; Read CP15 Cache Type Register */
913 retval = armv7a->armv4_5_common.mrc(target, 15,
914 0, 1, /* op1, op2 */
915 0, 0, /* CRn, CRm */
916 &cache_type_reg);
917 LOG_DEBUG("cp15 cache type: %8.8x", (unsigned) cache_type_reg);
918
919 /* FIXME the armv4_4 cache info DOES NOT APPLY to Cortex-A8 */
920 armv4_5_identify_cache(cache_type_reg,
921 &armv7a->armv4_5_mmu.armv4_5_cache);
922 }
923
924 armv7a->armv4_5_mmu.mmu_enabled =
925 (cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0;
926 armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
927 (cortex_a8->cp15_control_reg & 0x4U) ? 1 : 0;
928 armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
929 (cortex_a8->cp15_control_reg & 0x1000U) ? 1 : 0;
930
931
932 }
933
934 static int cortex_a8_step(struct target *target, int current, uint32_t address,
935 int handle_breakpoints)
936 {
937 struct armv7a_common *armv7a = target_to_armv7a(target);
938 struct arm *armv4_5 = &armv7a->armv4_5_common;
939 struct breakpoint *breakpoint = NULL;
940 struct breakpoint stepbreakpoint;
941 struct reg *r;
942
943 int timeout = 100;
944
945 if (target->state != TARGET_HALTED)
946 {
947 LOG_WARNING("target not halted");
948 return ERROR_TARGET_NOT_HALTED;
949 }
950
951 /* current = 1: continue on current pc, otherwise continue at <address> */
952 r = armv4_5->pc;
953 if (!current)
954 {
955 buf_set_u32(r->value, 0, 32, address);
956 }
957 else
958 {
959 address = buf_get_u32(r->value, 0, 32);
960 }
961
962 /* The front-end may request us not to handle breakpoints.
963 * But since Cortex-A8 uses breakpoint for single step,
964 * we MUST handle breakpoints.
965 */
966 handle_breakpoints = 1;
967 if (handle_breakpoints) {
968 breakpoint = breakpoint_find(target, address);
969 if (breakpoint)
970 cortex_a8_unset_breakpoint(target, breakpoint);
971 }
972
973 /* Setup single step breakpoint */
974 stepbreakpoint.address = address;
975 stepbreakpoint.length = (armv4_5->core_state == ARM_STATE_THUMB)
976 ? 2 : 4;
977 stepbreakpoint.type = BKPT_HARD;
978 stepbreakpoint.set = 0;
979
980 /* Break on IVA mismatch */
981 cortex_a8_set_breakpoint(target, &stepbreakpoint, 0x04);
982
983 target->debug_reason = DBG_REASON_SINGLESTEP;
984
985 cortex_a8_resume(target, 1, address, 0, 0);
986
987 while (target->state != TARGET_HALTED)
988 {
989 cortex_a8_poll(target);
990 if (--timeout == 0)
991 {
992 LOG_WARNING("timeout waiting for target halt");
993 break;
994 }
995 }
996
997 cortex_a8_unset_breakpoint(target, &stepbreakpoint);
998 if (timeout > 0)
999 target->debug_reason = DBG_REASON_BREAKPOINT;
1000
1001 if (breakpoint)
1002 cortex_a8_set_breakpoint(target, breakpoint, 0);
1003
1004 if (target->state != TARGET_HALTED)
1005 LOG_DEBUG("target stepped");
1006
1007 return ERROR_OK;
1008 }
1009
1010 static int cortex_a8_restore_context(struct target *target, bool bpwp)
1011 {
1012 struct armv7a_common *armv7a = target_to_armv7a(target);
1013
1014 LOG_DEBUG(" ");
1015
1016 if (armv7a->pre_restore_context)
1017 armv7a->pre_restore_context(target);
1018
1019 arm_dpm_write_dirty_registers(&armv7a->dpm, bpwp);
1020
1021 if (armv7a->post_restore_context)
1022 armv7a->post_restore_context(target);
1023
1024 return ERROR_OK;
1025 }
1026
1027
1028 /*
1029 * Cortex-A8 Breakpoint and watchpoint fuctions
1030 */
1031
1032 /* Setup hardware Breakpoint Register Pair */
1033 static int cortex_a8_set_breakpoint(struct target *target,
1034 struct breakpoint *breakpoint, uint8_t matchmode)
1035 {
1036 int retval;
1037 int brp_i=0;
1038 uint32_t control;
1039 uint8_t byte_addr_select = 0x0F;
1040 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1041 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1042 struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
1043
1044 if (breakpoint->set)
1045 {
1046 LOG_WARNING("breakpoint already set");
1047 return ERROR_OK;
1048 }
1049
1050 if (breakpoint->type == BKPT_HARD)
1051 {
1052 while (brp_list[brp_i].used && (brp_i < cortex_a8->brp_num))
1053 brp_i++ ;
1054 if (brp_i >= cortex_a8->brp_num)
1055 {
1056 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1057 return ERROR_FAIL;
1058 }
1059 breakpoint->set = brp_i + 1;
1060 if (breakpoint->length == 2)
1061 {
1062 byte_addr_select = (3 << (breakpoint->address & 0x02));
1063 }
1064 control = ((matchmode & 0x7) << 20)
1065 | (byte_addr_select << 5)
1066 | (3 << 1) | 1;
1067 brp_list[brp_i].used = 1;
1068 brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
1069 brp_list[brp_i].control = control;
1070 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1071 + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
1072 brp_list[brp_i].value);
1073 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1074 + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
1075 brp_list[brp_i].control);
1076 LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
1077 brp_list[brp_i].control,
1078 brp_list[brp_i].value);
1079 }
1080 else if (breakpoint->type == BKPT_SOFT)
1081 {
1082 uint8_t code[4];
1083 if (breakpoint->length == 2)
1084 {
1085 buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
1086 }
1087 else
1088 {
1089 buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
1090 }
1091 retval = target->type->read_memory(target,
1092 breakpoint->address & 0xFFFFFFFE,
1093 breakpoint->length, 1,
1094 breakpoint->orig_instr);
1095 if (retval != ERROR_OK)
1096 return retval;
1097 retval = target->type->write_memory(target,
1098 breakpoint->address & 0xFFFFFFFE,
1099 breakpoint->length, 1, code);
1100 if (retval != ERROR_OK)
1101 return retval;
1102 breakpoint->set = 0x11; /* Any nice value but 0 */
1103 }
1104
1105 return ERROR_OK;
1106 }
1107
1108 static int cortex_a8_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
1109 {
1110 int retval;
1111 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1112 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1113 struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
1114
1115 if (!breakpoint->set)
1116 {
1117 LOG_WARNING("breakpoint not set");
1118 return ERROR_OK;
1119 }
1120
1121 if (breakpoint->type == BKPT_HARD)
1122 {
1123 int brp_i = breakpoint->set - 1;
1124 if ((brp_i < 0) || (brp_i >= cortex_a8->brp_num))
1125 {
1126 LOG_DEBUG("Invalid BRP number in breakpoint");
1127 return ERROR_OK;
1128 }
1129 LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
1130 brp_list[brp_i].control, brp_list[brp_i].value);
1131 brp_list[brp_i].used = 0;
1132 brp_list[brp_i].value = 0;
1133 brp_list[brp_i].control = 0;
1134 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1135 + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
1136 brp_list[brp_i].control);
1137 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1138 + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
1139 brp_list[brp_i].value);
1140 }
1141 else
1142 {
1143 /* restore original instruction (kept in target endianness) */
1144 if (breakpoint->length == 4)
1145 {
1146 retval = target->type->write_memory(target,
1147 breakpoint->address & 0xFFFFFFFE,
1148 4, 1, breakpoint->orig_instr);
1149 if (retval != ERROR_OK)
1150 return retval;
1151 }
1152 else
1153 {
1154 retval = target->type->write_memory(target,
1155 breakpoint->address & 0xFFFFFFFE,
1156 2, 1, breakpoint->orig_instr);
1157 if (retval != ERROR_OK)
1158 return retval;
1159 }
1160 }
1161 breakpoint->set = 0;
1162
1163 return ERROR_OK;
1164 }
1165
1166 static int cortex_a8_add_breakpoint(struct target *target,
1167 struct breakpoint *breakpoint)
1168 {
1169 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1170
1171 if ((breakpoint->type == BKPT_HARD) && (cortex_a8->brp_num_available < 1))
1172 {
1173 LOG_INFO("no hardware breakpoint available");
1174 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1175 }
1176
1177 if (breakpoint->type == BKPT_HARD)
1178 cortex_a8->brp_num_available--;
1179 cortex_a8_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
1180
1181 return ERROR_OK;
1182 }
1183
1184 static int cortex_a8_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
1185 {
1186 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1187
1188 #if 0
1189 /* It is perfectly possible to remove brakpoints while the taget is running */
1190 if (target->state != TARGET_HALTED)
1191 {
1192 LOG_WARNING("target not halted");
1193 return ERROR_TARGET_NOT_HALTED;
1194 }
1195 #endif
1196
1197 if (breakpoint->set)
1198 {
1199 cortex_a8_unset_breakpoint(target, breakpoint);
1200 if (breakpoint->type == BKPT_HARD)
1201 cortex_a8->brp_num_available++ ;
1202 }
1203
1204
1205 return ERROR_OK;
1206 }
1207
1208
1209
1210 /*
1211 * Cortex-A8 Reset fuctions
1212 */
1213
1214 static int cortex_a8_assert_reset(struct target *target)
1215 {
1216 struct armv7a_common *armv7a = target_to_armv7a(target);
1217
1218 LOG_DEBUG(" ");
1219
1220 /* FIXME when halt is requested, make it work somehow... */
1221
1222 /* Issue some kind of warm reset. */
1223 if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
1224 target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
1225 } else if (jtag_get_reset_config() & RESET_HAS_SRST) {
1226 /* REVISIT handle "pulls" cases, if there's
1227 * hardware that needs them to work.
1228 */
1229 jtag_add_reset(0, 1);
1230 } else {
1231 LOG_ERROR("%s: how to reset?", target_name(target));
1232 return ERROR_FAIL;
1233 }
1234
1235 /* registers are now invalid */
1236 register_cache_invalidate(armv7a->armv4_5_common.core_cache);
1237
1238 target->state = TARGET_RESET;
1239
1240 return ERROR_OK;
1241 }
1242
1243 static int cortex_a8_deassert_reset(struct target *target)
1244 {
1245 int retval;
1246
1247 LOG_DEBUG(" ");
1248
1249 /* be certain SRST is off */
1250 jtag_add_reset(0, 0);
1251
1252 retval = cortex_a8_poll(target);
1253
1254 if (target->reset_halt) {
1255 if (target->state != TARGET_HALTED) {
1256 LOG_WARNING("%s: ran after reset and before halt ...",
1257 target_name(target));
1258 if ((retval = target_halt(target)) != ERROR_OK)
1259 return retval;
1260 }
1261 }
1262
1263 return ERROR_OK;
1264 }
1265
1266 /*
1267 * Cortex-A8 Memory access
1268 *
1269 * This is same Cortex M3 but we must also use the correct
1270 * ap number for every access.
1271 */
1272
1273 static int cortex_a8_read_memory(struct target *target, uint32_t address,
1274 uint32_t size, uint32_t count, uint8_t *buffer)
1275 {
1276 struct armv7a_common *armv7a = target_to_armv7a(target);
1277 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1278 int retval = ERROR_INVALID_ARGUMENTS;
1279
1280 /* cortex_a8 handles unaligned memory access */
1281
1282 // ??? dap_ap_select(swjdp, swjdp_memoryap);
1283
1284 if (count && buffer) {
1285 switch (size) {
1286 case 4:
1287 retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
1288 break;
1289 case 2:
1290 retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
1291 break;
1292 case 1:
1293 retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
1294 break;
1295 }
1296 }
1297
1298 return retval;
1299 }
1300
1301 static int cortex_a8_write_memory(struct target *target, uint32_t address,
1302 uint32_t size, uint32_t count, uint8_t *buffer)
1303 {
1304 struct armv7a_common *armv7a = target_to_armv7a(target);
1305 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1306 int retval = ERROR_INVALID_ARGUMENTS;
1307
1308 // ??? dap_ap_select(swjdp, swjdp_memoryap);
1309
1310 if (count && buffer) {
1311 switch (size) {
1312 case 4:
1313 retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
1314 break;
1315 case 2:
1316 retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
1317 break;
1318 case 1:
1319 retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
1320 break;
1321 }
1322 }
1323
1324 /* REVISIT this op is generic ARMv7-A/R stuff */
1325 if (retval == ERROR_OK && target->state == TARGET_HALTED)
1326 {
1327 struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
1328
1329 retval = dpm->prepare(dpm);
1330 if (retval != ERROR_OK)
1331 return retval;
1332
1333 /* The Cache handling will NOT work with MMU active, the
1334 * wrong addresses will be invalidated!
1335 *
1336 * For both ICache and DCache, walk all cache lines in the
1337 * address range. Cortex-A8 has fixed 64 byte line length.
1338 *
1339 * REVISIT per ARMv7, these may trigger watchpoints ...
1340 */
1341
1342 /* invalidate I-Cache */
1343 if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
1344 {
1345 /* ICIMVAU - Invalidate Cache single entry
1346 * with MVA to PoU
1347 * MCR p15, 0, r0, c7, c5, 1
1348 */
1349 for (uint32_t cacheline = address;
1350 cacheline < address + size * count;
1351 cacheline += 64) {
1352 retval = dpm->instr_write_data_r0(dpm,
1353 ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
1354 cacheline);
1355 }
1356 }
1357
1358 /* invalidate D-Cache */
1359 if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
1360 {
1361 /* DCIMVAC - Invalidate data Cache line
1362 * with MVA to PoC
1363 * MCR p15, 0, r0, c7, c6, 1
1364 */
1365 for (uint32_t cacheline = address;
1366 cacheline < address + size * count;
1367 cacheline += 64) {
1368 retval = dpm->instr_write_data_r0(dpm,
1369 ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
1370 cacheline);
1371 }
1372 }
1373
1374 /* (void) */ dpm->finish(dpm);
1375 }
1376
1377 return retval;
1378 }
1379
1380 static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address,
1381 uint32_t count, uint8_t *buffer)
1382 {
1383 return cortex_a8_write_memory(target, address, 4, count, buffer);
1384 }
1385
1386
1387 static int cortex_a8_dcc_read(struct swjdp_common *swjdp, uint8_t *value, uint8_t *ctrl)
1388 {
1389 #if 0
1390 u16 dcrdr;
1391
1392 mem_ap_read_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1393 *ctrl = (uint8_t)dcrdr;
1394 *value = (uint8_t)(dcrdr >> 8);
1395
1396 LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
1397
1398 /* write ack back to software dcc register
1399 * signify we have read data */
1400 if (dcrdr & (1 << 0))
1401 {
1402 dcrdr = 0;
1403 mem_ap_write_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1404 }
1405 #endif
1406 return ERROR_OK;
1407 }
1408
1409
1410 static int cortex_a8_handle_target_request(void *priv)
1411 {
1412 struct target *target = priv;
1413 struct armv7a_common *armv7a = target_to_armv7a(target);
1414 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1415
1416 if (!target_was_examined(target))
1417 return ERROR_OK;
1418 if (!target->dbg_msg_enabled)
1419 return ERROR_OK;
1420
1421 if (target->state == TARGET_RUNNING)
1422 {
1423 uint8_t data = 0;
1424 uint8_t ctrl = 0;
1425
1426 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1427
1428 /* check if we have data */
1429 if (ctrl & (1 << 0))
1430 {
1431 uint32_t request;
1432
1433 /* we assume target is quick enough */
1434 request = data;
1435 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1436 request |= (data << 8);
1437 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1438 request |= (data << 16);
1439 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1440 request |= (data << 24);
1441 target_request(target, request);
1442 }
1443 }
1444
1445 return ERROR_OK;
1446 }
1447
1448 /*
1449 * Cortex-A8 target information and configuration
1450 */
1451
1452 static int cortex_a8_examine_first(struct target *target)
1453 {
1454 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1455 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1456 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1457 int i;
1458 int retval = ERROR_OK;
1459 uint32_t didr, ctypr, ttypr, cpuid;
1460
1461 /* stop assuming this is an OMAP! */
1462 LOG_DEBUG("TODO - autoconfigure");
1463
1464 /* Here we shall insert a proper ROM Table scan */
1465 armv7a->debug_base = OMAP3530_DEBUG_BASE;
1466
1467 /* We do one extra read to ensure DAP is configured,
1468 * we call ahbap_debugport_init(swjdp) instead
1469 */
1470 ahbap_debugport_init(swjdp);
1471 mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_CPUID, &cpuid);
1472 if ((retval = mem_ap_read_atomic_u32(swjdp,
1473 armv7a->debug_base + CPUDBG_CPUID, &cpuid)) != ERROR_OK)
1474 {
1475 LOG_DEBUG("Examine %s failed", "CPUID");
1476 return retval;
1477 }
1478
1479 if ((retval = mem_ap_read_atomic_u32(swjdp,
1480 armv7a->debug_base + CPUDBG_CTYPR, &ctypr)) != ERROR_OK)
1481 {
1482 LOG_DEBUG("Examine %s failed", "CTYPR");
1483 return retval;
1484 }
1485
1486 if ((retval = mem_ap_read_atomic_u32(swjdp,
1487 armv7a->debug_base + CPUDBG_TTYPR, &ttypr)) != ERROR_OK)
1488 {
1489 LOG_DEBUG("Examine %s failed", "TTYPR");
1490 return retval;
1491 }
1492
1493 if ((retval = mem_ap_read_atomic_u32(swjdp,
1494 armv7a->debug_base + CPUDBG_DIDR, &didr)) != ERROR_OK)
1495 {
1496 LOG_DEBUG("Examine %s failed", "DIDR");
1497 return retval;
1498 }
1499
1500 LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
1501 LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr);
1502 LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
1503 LOG_DEBUG("didr = 0x%08" PRIx32, didr);
1504
1505 armv7a->armv4_5_common.core_type = ARM_MODE_MON;
1506 cortex_a8_dpm_setup(cortex_a8, didr);
1507
1508 /* Setup Breakpoint Register Pairs */
1509 cortex_a8->brp_num = ((didr >> 24) & 0x0F) + 1;
1510 cortex_a8->brp_num_context = ((didr >> 20) & 0x0F) + 1;
1511 cortex_a8->brp_num_available = cortex_a8->brp_num;
1512 cortex_a8->brp_list = calloc(cortex_a8->brp_num, sizeof(struct cortex_a8_brp));
1513 // cortex_a8->brb_enabled = ????;
1514 for (i = 0; i < cortex_a8->brp_num; i++)
1515 {
1516 cortex_a8->brp_list[i].used = 0;
1517 if (i < (cortex_a8->brp_num-cortex_a8->brp_num_context))
1518 cortex_a8->brp_list[i].type = BRP_NORMAL;
1519 else
1520 cortex_a8->brp_list[i].type = BRP_CONTEXT;
1521 cortex_a8->brp_list[i].value = 0;
1522 cortex_a8->brp_list[i].control = 0;
1523 cortex_a8->brp_list[i].BRPn = i;
1524 }
1525
1526 LOG_DEBUG("Configured %i hw breakpoints", cortex_a8->brp_num);
1527
1528 target_set_examined(target);
1529 return ERROR_OK;
1530 }
1531
1532 static int cortex_a8_examine(struct target *target)
1533 {
1534 int retval = ERROR_OK;
1535
1536 /* don't re-probe hardware after each reset */
1537 if (!target_was_examined(target))
1538 retval = cortex_a8_examine_first(target);
1539
1540 /* Configure core debug access */
1541 if (retval == ERROR_OK)
1542 retval = cortex_a8_init_debug_access(target);
1543
1544 return retval;
1545 }
1546
1547 /*
1548 * Cortex-A8 target creation and initialization
1549 */
1550
1551 static int cortex_a8_init_target(struct command_context *cmd_ctx,
1552 struct target *target)
1553 {
1554 /* examine_first() does a bunch of this */
1555 return ERROR_OK;
1556 }
1557
1558 static int cortex_a8_init_arch_info(struct target *target,
1559 struct cortex_a8_common *cortex_a8, struct jtag_tap *tap)
1560 {
1561 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1562 struct arm *armv4_5 = &armv7a->armv4_5_common;
1563 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1564
1565 /* Setup struct cortex_a8_common */
1566 cortex_a8->common_magic = CORTEX_A8_COMMON_MAGIC;
1567 armv4_5->arch_info = armv7a;
1568
1569 /* prepare JTAG information for the new target */
1570 cortex_a8->jtag_info.tap = tap;
1571 cortex_a8->jtag_info.scann_size = 4;
1572
1573 swjdp->dp_select_value = -1;
1574 swjdp->ap_csw_value = -1;
1575 swjdp->ap_tar_value = -1;
1576 swjdp->jtag_info = &cortex_a8->jtag_info;
1577 swjdp->memaccess_tck = 80;
1578
1579 /* Number of bits for tar autoincrement, impl. dep. at least 10 */
1580 swjdp->tar_autoincr_block = (1 << 10);
1581
1582 cortex_a8->fast_reg_read = 0;
1583
1584 /* register arch-specific functions */
1585 armv7a->examine_debug_reason = NULL;
1586
1587 armv7a->post_debug_entry = cortex_a8_post_debug_entry;
1588
1589 armv7a->pre_restore_context = NULL;
1590 armv7a->post_restore_context = NULL;
1591 armv7a->armv4_5_mmu.armv4_5_cache.ctype = -1;
1592 // armv7a->armv4_5_mmu.get_ttb = armv7a_get_ttb;
1593 armv7a->armv4_5_mmu.read_memory = cortex_a8_read_memory;
1594 armv7a->armv4_5_mmu.write_memory = cortex_a8_write_memory;
1595 // armv7a->armv4_5_mmu.disable_mmu_caches = armv7a_disable_mmu_caches;
1596 // armv7a->armv4_5_mmu.enable_mmu_caches = armv7a_enable_mmu_caches;
1597 armv7a->armv4_5_mmu.has_tiny_pages = 1;
1598 armv7a->armv4_5_mmu.mmu_enabled = 0;
1599
1600
1601 // arm7_9->handle_target_request = cortex_a8_handle_target_request;
1602
1603 /* REVISIT v7a setup should be in a v7a-specific routine */
1604 arm_init_arch_info(target, armv4_5);
1605 armv7a->common_magic = ARMV7_COMMON_MAGIC;
1606
1607 target_register_timer_callback(cortex_a8_handle_target_request, 1, 1, target);
1608
1609 return ERROR_OK;
1610 }
1611
1612 static int cortex_a8_target_create(struct target *target, Jim_Interp *interp)
1613 {
1614 struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common));
1615
1616 cortex_a8_init_arch_info(target, cortex_a8, target->tap);
1617
1618 return ERROR_OK;
1619 }
1620
1621 COMMAND_HANDLER(cortex_a8_handle_cache_info_command)
1622 {
1623 struct target *target = get_current_target(CMD_CTX);
1624 struct armv7a_common *armv7a = target_to_armv7a(target);
1625
1626 return armv4_5_handle_cache_info_command(CMD_CTX,
1627 &armv7a->armv4_5_mmu.armv4_5_cache);
1628 }
1629
1630
1631 COMMAND_HANDLER(cortex_a8_handle_dbginit_command)
1632 {
1633 struct target *target = get_current_target(CMD_CTX);
1634
1635 cortex_a8_init_debug_access(target);
1636
1637 return ERROR_OK;
1638 }
1639
1640 static const struct command_registration cortex_a8_exec_command_handlers[] = {
1641 {
1642 .name = "cache_info",
1643 .handler = cortex_a8_handle_cache_info_command,
1644 .mode = COMMAND_EXEC,
1645 .help = "display information about target caches",
1646 },
1647 {
1648 .name = "dbginit",
1649 .handler = cortex_a8_handle_dbginit_command,
1650 .mode = COMMAND_EXEC,
1651 .help = "Initialize core debug",
1652 },
1653 COMMAND_REGISTRATION_DONE
1654 };
1655 static const struct command_registration cortex_a8_command_handlers[] = {
1656 {
1657 .chain = arm_command_handlers,
1658 },
1659 {
1660 .chain = armv7a_command_handlers,
1661 },
1662 {
1663 .name = "cortex_a8",
1664 .mode = COMMAND_ANY,
1665 .help = "Cortex-A8 command group",
1666 .chain = cortex_a8_exec_command_handlers,
1667 },
1668 COMMAND_REGISTRATION_DONE
1669 };
1670
1671 struct target_type cortexa8_target = {
1672 .name = "cortex_a8",
1673
1674 .poll = cortex_a8_poll,
1675 .arch_state = armv7a_arch_state,
1676
1677 .target_request_data = NULL,
1678
1679 .halt = cortex_a8_halt,
1680 .resume = cortex_a8_resume,
1681 .step = cortex_a8_step,
1682
1683 .assert_reset = cortex_a8_assert_reset,
1684 .deassert_reset = cortex_a8_deassert_reset,
1685 .soft_reset_halt = NULL,
1686
1687 /* REVISIT allow exporting VFP3 registers ... */
1688 .get_gdb_reg_list = arm_get_gdb_reg_list,
1689
1690 .read_memory = cortex_a8_read_memory,
1691 .write_memory = cortex_a8_write_memory,
1692 .bulk_write_memory = cortex_a8_bulk_write_memory,
1693
1694 .checksum_memory = arm_checksum_memory,
1695 .blank_check_memory = arm_blank_check_memory,
1696
1697 .run_algorithm = armv4_5_run_algorithm,
1698
1699 .add_breakpoint = cortex_a8_add_breakpoint,
1700 .remove_breakpoint = cortex_a8_remove_breakpoint,
1701 .add_watchpoint = NULL,
1702 .remove_watchpoint = NULL,
1703
1704 .commands = cortex_a8_command_handlers,
1705 .target_create = cortex_a8_target_create,
1706 .init_target = cortex_a8_init_target,
1707 .examine = cortex_a8_examine,
1708 };

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)