ARMv7-M: make DAP commands verify target is an ARMv7-M
[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(
699 armv4_5->core_cache->reg_list[15].value,
700 0, 32);
701 if (!current)
702 resume_pc = address;
703
704 /* Make sure that the Armv7 gdb thumb fixups does not
705 * kill the return address
706 */
707 switch (armv4_5->core_state)
708 {
709 case ARM_STATE_ARM:
710 resume_pc &= 0xFFFFFFFC;
711 break;
712 case ARM_STATE_THUMB:
713 case ARM_STATE_THUMB_EE:
714 /* When the return address is loaded into PC
715 * bit 0 must be 1 to stay in Thumb state
716 */
717 resume_pc |= 0x1;
718 break;
719 case ARM_STATE_JAZELLE:
720 LOG_ERROR("How do I resume into Jazelle state??");
721 return ERROR_FAIL;
722 }
723 LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
724 buf_set_u32(armv4_5->core_cache->reg_list[15].value,
725 0, 32, resume_pc);
726 armv4_5->core_cache->reg_list[15].dirty = 1;
727 armv4_5->core_cache->reg_list[15].valid = 1;
728
729 cortex_a8_restore_context(target, handle_breakpoints);
730
731 #if 0
732 /* the front-end may request us not to handle breakpoints */
733 if (handle_breakpoints)
734 {
735 /* Single step past breakpoint at current address */
736 if ((breakpoint = breakpoint_find(target, resume_pc)))
737 {
738 LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
739 cortex_m3_unset_breakpoint(target, breakpoint);
740 cortex_m3_single_step_core(target);
741 cortex_m3_set_breakpoint(target, breakpoint);
742 }
743 }
744
745 #endif
746 /* Restart core and wait for it to be started
747 * NOTE: this clears DSCR_ITR_EN and other bits.
748 *
749 * REVISIT: for single stepping, we probably want to
750 * disable IRQs by default, with optional override...
751 */
752 mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DRCR, 0x2);
753
754 do {
755 mem_ap_read_atomic_u32(swjdp,
756 armv7a->debug_base + CPUDBG_DSCR, &dscr);
757 } while ((dscr & DSCR_CORE_RESTARTED) == 0);
758
759 target->debug_reason = DBG_REASON_NOTHALTED;
760 target->state = TARGET_RUNNING;
761
762 /* registers are now invalid */
763 register_cache_invalidate(armv4_5->core_cache);
764
765 if (!debug_execution)
766 {
767 target->state = TARGET_RUNNING;
768 target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
769 LOG_DEBUG("target resumed at 0x%" PRIx32, resume_pc);
770 }
771 else
772 {
773 target->state = TARGET_DEBUG_RUNNING;
774 target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
775 LOG_DEBUG("target debug resumed at 0x%" PRIx32, resume_pc);
776 }
777
778 dap_ap_select(swjdp, saved_apsel);
779
780 return ERROR_OK;
781 }
782
783 static int cortex_a8_debug_entry(struct target *target)
784 {
785 int i;
786 uint32_t regfile[16], cpsr, dscr;
787 int retval = ERROR_OK;
788 struct working_area *regfile_working_area = NULL;
789 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
790 struct armv7a_common *armv7a = target_to_armv7a(target);
791 struct arm *armv4_5 = &armv7a->armv4_5_common;
792 struct swjdp_common *swjdp = &armv7a->swjdp_info;
793 struct reg *reg;
794
795 LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a8->cpudbg_dscr);
796
797 /* REVISIT surely we should not re-read DSCR !! */
798 mem_ap_read_atomic_u32(swjdp,
799 armv7a->debug_base + CPUDBG_DSCR, &dscr);
800
801 /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any
802 * imprecise data aborts get discarded by issuing a Data
803 * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4).
804 */
805
806 /* Enable the ITR execution once we are in debug mode */
807 dscr |= DSCR_ITR_EN;
808 retval = mem_ap_write_atomic_u32(swjdp,
809 armv7a->debug_base + CPUDBG_DSCR, dscr);
810
811 /* Examine debug reason */
812 arm_dpm_report_dscr(&armv7a->dpm, cortex_a8->cpudbg_dscr);
813
814 /* save address of instruction that triggered the watchpoint? */
815 if (target->debug_reason == DBG_REASON_WATCHPOINT) {
816 uint32_t wfar;
817
818 retval = mem_ap_read_atomic_u32(swjdp,
819 armv7a->debug_base + CPUDBG_WFAR,
820 &wfar);
821 arm_dpm_report_wfar(&armv7a->dpm, wfar);
822 }
823
824 /* REVISIT fast_reg_read is never set ... */
825
826 /* Examine target state and mode */
827 if (cortex_a8->fast_reg_read)
828 target_alloc_working_area(target, 64, &regfile_working_area);
829
830 /* First load register acessible through core debug port*/
831 if (!regfile_working_area)
832 {
833 retval = arm_dpm_read_current_registers(&armv7a->dpm);
834 }
835 else
836 {
837 dap_ap_select(swjdp, swjdp_memoryap);
838 cortex_a8_read_regs_through_mem(target,
839 regfile_working_area->address, regfile);
840 dap_ap_select(swjdp, swjdp_memoryap);
841 target_free_working_area(target, regfile_working_area);
842
843 /* read Current PSR */
844 cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
845 dap_ap_select(swjdp, swjdp_debugap);
846 LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
847
848 arm_set_cpsr(armv4_5, cpsr);
849
850 /* update cache */
851 for (i = 0; i <= ARM_PC; i++)
852 {
853 reg = arm_reg_current(armv4_5, i);
854
855 buf_set_u32(reg->value, 0, 32, regfile[i]);
856 reg->valid = 1;
857 reg->dirty = 0;
858 }
859
860 /* Fixup PC Resume Address */
861 if (cpsr & (1 << 5))
862 {
863 // T bit set for Thumb or ThumbEE state
864 regfile[ARM_PC] -= 4;
865 }
866 else
867 {
868 // ARM state
869 regfile[ARM_PC] -= 8;
870 }
871
872 reg = armv4_5->core_cache->reg_list + 15;
873 buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
874 reg->dirty = reg->valid;
875 }
876
877 #if 0
878 /* TODO, Move this */
879 uint32_t cp15_control_register, cp15_cacr, cp15_nacr;
880 cortex_a8_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
881 LOG_DEBUG("cp15_control_register = 0x%08x", cp15_control_register);
882
883 cortex_a8_read_cp(target, &cp15_cacr, 15, 0, 1, 0, 2);
884 LOG_DEBUG("cp15 Coprocessor Access Control Register = 0x%08x", cp15_cacr);
885
886 cortex_a8_read_cp(target, &cp15_nacr, 15, 0, 1, 1, 2);
887 LOG_DEBUG("cp15 Nonsecure Access Control Register = 0x%08x", cp15_nacr);
888 #endif
889
890 /* Are we in an exception handler */
891 // armv4_5->exception_number = 0;
892 if (armv7a->post_debug_entry)
893 armv7a->post_debug_entry(target);
894
895 return retval;
896 }
897
898 static void cortex_a8_post_debug_entry(struct target *target)
899 {
900 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
901 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
902 int retval;
903
904 /* MRC p15,0,<Rt>,c1,c0,0 ; Read CP15 System Control Register */
905 retval = armv7a->armv4_5_common.mrc(target, 15,
906 0, 0, /* op1, op2 */
907 1, 0, /* CRn, CRm */
908 &cortex_a8->cp15_control_reg);
909 LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a8->cp15_control_reg);
910
911 if (armv7a->armv4_5_mmu.armv4_5_cache.ctype == -1)
912 {
913 uint32_t cache_type_reg;
914
915 /* MRC p15,0,<Rt>,c0,c0,1 ; Read CP15 Cache Type Register */
916 retval = armv7a->armv4_5_common.mrc(target, 15,
917 0, 1, /* op1, op2 */
918 0, 0, /* CRn, CRm */
919 &cache_type_reg);
920 LOG_DEBUG("cp15 cache type: %8.8x", (unsigned) cache_type_reg);
921
922 /* FIXME the armv4_4 cache info DOES NOT APPLY to Cortex-A8 */
923 armv4_5_identify_cache(cache_type_reg,
924 &armv7a->armv4_5_mmu.armv4_5_cache);
925 }
926
927 armv7a->armv4_5_mmu.mmu_enabled =
928 (cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0;
929 armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
930 (cortex_a8->cp15_control_reg & 0x4U) ? 1 : 0;
931 armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
932 (cortex_a8->cp15_control_reg & 0x1000U) ? 1 : 0;
933
934
935 }
936
937 static int cortex_a8_step(struct target *target, int current, uint32_t address,
938 int handle_breakpoints)
939 {
940 struct armv7a_common *armv7a = target_to_armv7a(target);
941 struct arm *armv4_5 = &armv7a->armv4_5_common;
942 struct breakpoint *breakpoint = NULL;
943 struct breakpoint stepbreakpoint;
944 struct reg *r;
945
946 int timeout = 100;
947
948 if (target->state != TARGET_HALTED)
949 {
950 LOG_WARNING("target not halted");
951 return ERROR_TARGET_NOT_HALTED;
952 }
953
954 /* current = 1: continue on current pc, otherwise continue at <address> */
955 r = armv4_5->core_cache->reg_list + 15;
956 if (!current)
957 {
958 buf_set_u32(r->value, 0, 32, address);
959 }
960 else
961 {
962 address = buf_get_u32(r->value, 0, 32);
963 }
964
965 /* The front-end may request us not to handle breakpoints.
966 * But since Cortex-A8 uses breakpoint for single step,
967 * we MUST handle breakpoints.
968 */
969 handle_breakpoints = 1;
970 if (handle_breakpoints) {
971 breakpoint = breakpoint_find(target, address);
972 if (breakpoint)
973 cortex_a8_unset_breakpoint(target, breakpoint);
974 }
975
976 /* Setup single step breakpoint */
977 stepbreakpoint.address = address;
978 stepbreakpoint.length = (armv4_5->core_state == ARM_STATE_THUMB)
979 ? 2 : 4;
980 stepbreakpoint.type = BKPT_HARD;
981 stepbreakpoint.set = 0;
982
983 /* Break on IVA mismatch */
984 cortex_a8_set_breakpoint(target, &stepbreakpoint, 0x04);
985
986 target->debug_reason = DBG_REASON_SINGLESTEP;
987
988 cortex_a8_resume(target, 1, address, 0, 0);
989
990 while (target->state != TARGET_HALTED)
991 {
992 cortex_a8_poll(target);
993 if (--timeout == 0)
994 {
995 LOG_WARNING("timeout waiting for target halt");
996 break;
997 }
998 }
999
1000 cortex_a8_unset_breakpoint(target, &stepbreakpoint);
1001 if (timeout > 0)
1002 target->debug_reason = DBG_REASON_BREAKPOINT;
1003
1004 if (breakpoint)
1005 cortex_a8_set_breakpoint(target, breakpoint, 0);
1006
1007 if (target->state != TARGET_HALTED)
1008 LOG_DEBUG("target stepped");
1009
1010 return ERROR_OK;
1011 }
1012
1013 static int cortex_a8_restore_context(struct target *target, bool bpwp)
1014 {
1015 struct armv7a_common *armv7a = target_to_armv7a(target);
1016
1017 LOG_DEBUG(" ");
1018
1019 if (armv7a->pre_restore_context)
1020 armv7a->pre_restore_context(target);
1021
1022 arm_dpm_write_dirty_registers(&armv7a->dpm, bpwp);
1023
1024 if (armv7a->post_restore_context)
1025 armv7a->post_restore_context(target);
1026
1027 return ERROR_OK;
1028 }
1029
1030
1031 /*
1032 * Cortex-A8 Breakpoint and watchpoint fuctions
1033 */
1034
1035 /* Setup hardware Breakpoint Register Pair */
1036 static int cortex_a8_set_breakpoint(struct target *target,
1037 struct breakpoint *breakpoint, uint8_t matchmode)
1038 {
1039 int retval;
1040 int brp_i=0;
1041 uint32_t control;
1042 uint8_t byte_addr_select = 0x0F;
1043 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1044 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1045 struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
1046
1047 if (breakpoint->set)
1048 {
1049 LOG_WARNING("breakpoint already set");
1050 return ERROR_OK;
1051 }
1052
1053 if (breakpoint->type == BKPT_HARD)
1054 {
1055 while (brp_list[brp_i].used && (brp_i < cortex_a8->brp_num))
1056 brp_i++ ;
1057 if (brp_i >= cortex_a8->brp_num)
1058 {
1059 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1060 return ERROR_FAIL;
1061 }
1062 breakpoint->set = brp_i + 1;
1063 if (breakpoint->length == 2)
1064 {
1065 byte_addr_select = (3 << (breakpoint->address & 0x02));
1066 }
1067 control = ((matchmode & 0x7) << 20)
1068 | (byte_addr_select << 5)
1069 | (3 << 1) | 1;
1070 brp_list[brp_i].used = 1;
1071 brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
1072 brp_list[brp_i].control = control;
1073 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1074 + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
1075 brp_list[brp_i].value);
1076 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1077 + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
1078 brp_list[brp_i].control);
1079 LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
1080 brp_list[brp_i].control,
1081 brp_list[brp_i].value);
1082 }
1083 else if (breakpoint->type == BKPT_SOFT)
1084 {
1085 uint8_t code[4];
1086 if (breakpoint->length == 2)
1087 {
1088 buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
1089 }
1090 else
1091 {
1092 buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
1093 }
1094 retval = target->type->read_memory(target,
1095 breakpoint->address & 0xFFFFFFFE,
1096 breakpoint->length, 1,
1097 breakpoint->orig_instr);
1098 if (retval != ERROR_OK)
1099 return retval;
1100 retval = target->type->write_memory(target,
1101 breakpoint->address & 0xFFFFFFFE,
1102 breakpoint->length, 1, code);
1103 if (retval != ERROR_OK)
1104 return retval;
1105 breakpoint->set = 0x11; /* Any nice value but 0 */
1106 }
1107
1108 return ERROR_OK;
1109 }
1110
1111 static int cortex_a8_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
1112 {
1113 int retval;
1114 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1115 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1116 struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
1117
1118 if (!breakpoint->set)
1119 {
1120 LOG_WARNING("breakpoint not set");
1121 return ERROR_OK;
1122 }
1123
1124 if (breakpoint->type == BKPT_HARD)
1125 {
1126 int brp_i = breakpoint->set - 1;
1127 if ((brp_i < 0) || (brp_i >= cortex_a8->brp_num))
1128 {
1129 LOG_DEBUG("Invalid BRP number in breakpoint");
1130 return ERROR_OK;
1131 }
1132 LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx32, brp_i,
1133 brp_list[brp_i].control, brp_list[brp_i].value);
1134 brp_list[brp_i].used = 0;
1135 brp_list[brp_i].value = 0;
1136 brp_list[brp_i].control = 0;
1137 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1138 + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn,
1139 brp_list[brp_i].control);
1140 cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
1141 + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn,
1142 brp_list[brp_i].value);
1143 }
1144 else
1145 {
1146 /* restore original instruction (kept in target endianness) */
1147 if (breakpoint->length == 4)
1148 {
1149 retval = target->type->write_memory(target,
1150 breakpoint->address & 0xFFFFFFFE,
1151 4, 1, breakpoint->orig_instr);
1152 if (retval != ERROR_OK)
1153 return retval;
1154 }
1155 else
1156 {
1157 retval = target->type->write_memory(target,
1158 breakpoint->address & 0xFFFFFFFE,
1159 2, 1, breakpoint->orig_instr);
1160 if (retval != ERROR_OK)
1161 return retval;
1162 }
1163 }
1164 breakpoint->set = 0;
1165
1166 return ERROR_OK;
1167 }
1168
1169 static int cortex_a8_add_breakpoint(struct target *target,
1170 struct breakpoint *breakpoint)
1171 {
1172 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1173
1174 if ((breakpoint->type == BKPT_HARD) && (cortex_a8->brp_num_available < 1))
1175 {
1176 LOG_INFO("no hardware breakpoint available");
1177 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1178 }
1179
1180 if (breakpoint->type == BKPT_HARD)
1181 cortex_a8->brp_num_available--;
1182 cortex_a8_set_breakpoint(target, breakpoint, 0x00); /* Exact match */
1183
1184 return ERROR_OK;
1185 }
1186
1187 static int cortex_a8_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
1188 {
1189 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1190
1191 #if 0
1192 /* It is perfectly possible to remove brakpoints while the taget is running */
1193 if (target->state != TARGET_HALTED)
1194 {
1195 LOG_WARNING("target not halted");
1196 return ERROR_TARGET_NOT_HALTED;
1197 }
1198 #endif
1199
1200 if (breakpoint->set)
1201 {
1202 cortex_a8_unset_breakpoint(target, breakpoint);
1203 if (breakpoint->type == BKPT_HARD)
1204 cortex_a8->brp_num_available++ ;
1205 }
1206
1207
1208 return ERROR_OK;
1209 }
1210
1211
1212
1213 /*
1214 * Cortex-A8 Reset fuctions
1215 */
1216
1217 static int cortex_a8_assert_reset(struct target *target)
1218 {
1219 struct armv7a_common *armv7a = target_to_armv7a(target);
1220
1221 LOG_DEBUG(" ");
1222
1223 /* FIXME when halt is requested, make it work somehow... */
1224
1225 /* Issue some kind of warm reset. */
1226 if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
1227 target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
1228 } else if (jtag_get_reset_config() & RESET_HAS_SRST) {
1229 /* REVISIT handle "pulls" cases, if there's
1230 * hardware that needs them to work.
1231 */
1232 jtag_add_reset(0, 1);
1233 } else {
1234 LOG_ERROR("%s: how to reset?", target_name(target));
1235 return ERROR_FAIL;
1236 }
1237
1238 /* registers are now invalid */
1239 register_cache_invalidate(armv7a->armv4_5_common.core_cache);
1240
1241 target->state = TARGET_RESET;
1242
1243 return ERROR_OK;
1244 }
1245
1246 static int cortex_a8_deassert_reset(struct target *target)
1247 {
1248 int retval;
1249
1250 LOG_DEBUG(" ");
1251
1252 /* be certain SRST is off */
1253 jtag_add_reset(0, 0);
1254
1255 retval = cortex_a8_poll(target);
1256
1257 if (target->reset_halt) {
1258 if (target->state != TARGET_HALTED) {
1259 LOG_WARNING("%s: ran after reset and before halt ...",
1260 target_name(target));
1261 if ((retval = target_halt(target)) != ERROR_OK)
1262 return retval;
1263 }
1264 }
1265
1266 return ERROR_OK;
1267 }
1268
1269 /*
1270 * Cortex-A8 Memory access
1271 *
1272 * This is same Cortex M3 but we must also use the correct
1273 * ap number for every access.
1274 */
1275
1276 static int cortex_a8_read_memory(struct target *target, uint32_t address,
1277 uint32_t size, uint32_t count, uint8_t *buffer)
1278 {
1279 struct armv7a_common *armv7a = target_to_armv7a(target);
1280 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1281 int retval = ERROR_INVALID_ARGUMENTS;
1282
1283 /* cortex_a8 handles unaligned memory access */
1284
1285 // ??? dap_ap_select(swjdp, swjdp_memoryap);
1286
1287 if (count && buffer) {
1288 switch (size) {
1289 case 4:
1290 retval = mem_ap_read_buf_u32(swjdp, buffer, 4 * count, address);
1291 break;
1292 case 2:
1293 retval = mem_ap_read_buf_u16(swjdp, buffer, 2 * count, address);
1294 break;
1295 case 1:
1296 retval = mem_ap_read_buf_u8(swjdp, buffer, count, address);
1297 break;
1298 }
1299 }
1300
1301 return retval;
1302 }
1303
1304 static int cortex_a8_write_memory(struct target *target, uint32_t address,
1305 uint32_t size, uint32_t count, uint8_t *buffer)
1306 {
1307 struct armv7a_common *armv7a = target_to_armv7a(target);
1308 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1309 int retval = ERROR_INVALID_ARGUMENTS;
1310
1311 // ??? dap_ap_select(swjdp, swjdp_memoryap);
1312
1313 if (count && buffer) {
1314 switch (size) {
1315 case 4:
1316 retval = mem_ap_write_buf_u32(swjdp, buffer, 4 * count, address);
1317 break;
1318 case 2:
1319 retval = mem_ap_write_buf_u16(swjdp, buffer, 2 * count, address);
1320 break;
1321 case 1:
1322 retval = mem_ap_write_buf_u8(swjdp, buffer, count, address);
1323 break;
1324 }
1325 }
1326
1327 /* REVISIT this op is generic ARMv7-A/R stuff */
1328 if (retval == ERROR_OK && target->state == TARGET_HALTED)
1329 {
1330 struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
1331
1332 retval = dpm->prepare(dpm);
1333 if (retval != ERROR_OK)
1334 return retval;
1335
1336 /* The Cache handling will NOT work with MMU active, the
1337 * wrong addresses will be invalidated!
1338 *
1339 * For both ICache and DCache, walk all cache lines in the
1340 * address range. Cortex-A8 has fixed 64 byte line length.
1341 *
1342 * REVISIT per ARMv7, these may trigger watchpoints ...
1343 */
1344
1345 /* invalidate I-Cache */
1346 if (armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
1347 {
1348 /* ICIMVAU - Invalidate Cache single entry
1349 * with MVA to PoU
1350 * MCR p15, 0, r0, c7, c5, 1
1351 */
1352 for (uint32_t cacheline = address;
1353 cacheline < address + size * count;
1354 cacheline += 64) {
1355 retval = dpm->instr_write_data_r0(dpm,
1356 ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
1357 cacheline);
1358 }
1359 }
1360
1361 /* invalidate D-Cache */
1362 if (armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
1363 {
1364 /* DCIMVAC - Invalidate data Cache line
1365 * with MVA to PoC
1366 * MCR p15, 0, r0, c7, c6, 1
1367 */
1368 for (uint32_t cacheline = address;
1369 cacheline < address + size * count;
1370 cacheline += 64) {
1371 retval = dpm->instr_write_data_r0(dpm,
1372 ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
1373 cacheline);
1374 }
1375 }
1376
1377 /* (void) */ dpm->finish(dpm);
1378 }
1379
1380 return retval;
1381 }
1382
1383 static int cortex_a8_bulk_write_memory(struct target *target, uint32_t address,
1384 uint32_t count, uint8_t *buffer)
1385 {
1386 return cortex_a8_write_memory(target, address, 4, count, buffer);
1387 }
1388
1389
1390 static int cortex_a8_dcc_read(struct swjdp_common *swjdp, uint8_t *value, uint8_t *ctrl)
1391 {
1392 #if 0
1393 u16 dcrdr;
1394
1395 mem_ap_read_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1396 *ctrl = (uint8_t)dcrdr;
1397 *value = (uint8_t)(dcrdr >> 8);
1398
1399 LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
1400
1401 /* write ack back to software dcc register
1402 * signify we have read data */
1403 if (dcrdr & (1 << 0))
1404 {
1405 dcrdr = 0;
1406 mem_ap_write_buf_u16(swjdp, (uint8_t*)&dcrdr, 1, DCB_DCRDR);
1407 }
1408 #endif
1409 return ERROR_OK;
1410 }
1411
1412
1413 static int cortex_a8_handle_target_request(void *priv)
1414 {
1415 struct target *target = priv;
1416 struct armv7a_common *armv7a = target_to_armv7a(target);
1417 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1418
1419 if (!target_was_examined(target))
1420 return ERROR_OK;
1421 if (!target->dbg_msg_enabled)
1422 return ERROR_OK;
1423
1424 if (target->state == TARGET_RUNNING)
1425 {
1426 uint8_t data = 0;
1427 uint8_t ctrl = 0;
1428
1429 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1430
1431 /* check if we have data */
1432 if (ctrl & (1 << 0))
1433 {
1434 uint32_t request;
1435
1436 /* we assume target is quick enough */
1437 request = data;
1438 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1439 request |= (data << 8);
1440 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1441 request |= (data << 16);
1442 cortex_a8_dcc_read(swjdp, &data, &ctrl);
1443 request |= (data << 24);
1444 target_request(target, request);
1445 }
1446 }
1447
1448 return ERROR_OK;
1449 }
1450
1451 /*
1452 * Cortex-A8 target information and configuration
1453 */
1454
1455 static int cortex_a8_examine_first(struct target *target)
1456 {
1457 struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
1458 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1459 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1460 int i;
1461 int retval = ERROR_OK;
1462 uint32_t didr, ctypr, ttypr, cpuid;
1463
1464 /* stop assuming this is an OMAP! */
1465 LOG_DEBUG("TODO - autoconfigure");
1466
1467 /* Here we shall insert a proper ROM Table scan */
1468 armv7a->debug_base = OMAP3530_DEBUG_BASE;
1469
1470 /* We do one extra read to ensure DAP is configured,
1471 * we call ahbap_debugport_init(swjdp) instead
1472 */
1473 ahbap_debugport_init(swjdp);
1474 mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_CPUID, &cpuid);
1475 if ((retval = mem_ap_read_atomic_u32(swjdp,
1476 armv7a->debug_base + CPUDBG_CPUID, &cpuid)) != ERROR_OK)
1477 {
1478 LOG_DEBUG("Examine %s failed", "CPUID");
1479 return retval;
1480 }
1481
1482 if ((retval = mem_ap_read_atomic_u32(swjdp,
1483 armv7a->debug_base + CPUDBG_CTYPR, &ctypr)) != ERROR_OK)
1484 {
1485 LOG_DEBUG("Examine %s failed", "CTYPR");
1486 return retval;
1487 }
1488
1489 if ((retval = mem_ap_read_atomic_u32(swjdp,
1490 armv7a->debug_base + CPUDBG_TTYPR, &ttypr)) != ERROR_OK)
1491 {
1492 LOG_DEBUG("Examine %s failed", "TTYPR");
1493 return retval;
1494 }
1495
1496 if ((retval = mem_ap_read_atomic_u32(swjdp,
1497 armv7a->debug_base + CPUDBG_DIDR, &didr)) != ERROR_OK)
1498 {
1499 LOG_DEBUG("Examine %s failed", "DIDR");
1500 return retval;
1501 }
1502
1503 LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid);
1504 LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr);
1505 LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
1506 LOG_DEBUG("didr = 0x%08" PRIx32, didr);
1507
1508 armv7a->armv4_5_common.core_type = ARM_MODE_MON;
1509 cortex_a8_dpm_setup(cortex_a8, didr);
1510
1511 /* Setup Breakpoint Register Pairs */
1512 cortex_a8->brp_num = ((didr >> 24) & 0x0F) + 1;
1513 cortex_a8->brp_num_context = ((didr >> 20) & 0x0F) + 1;
1514 cortex_a8->brp_num_available = cortex_a8->brp_num;
1515 cortex_a8->brp_list = calloc(cortex_a8->brp_num, sizeof(struct cortex_a8_brp));
1516 // cortex_a8->brb_enabled = ????;
1517 for (i = 0; i < cortex_a8->brp_num; i++)
1518 {
1519 cortex_a8->brp_list[i].used = 0;
1520 if (i < (cortex_a8->brp_num-cortex_a8->brp_num_context))
1521 cortex_a8->brp_list[i].type = BRP_NORMAL;
1522 else
1523 cortex_a8->brp_list[i].type = BRP_CONTEXT;
1524 cortex_a8->brp_list[i].value = 0;
1525 cortex_a8->brp_list[i].control = 0;
1526 cortex_a8->brp_list[i].BRPn = i;
1527 }
1528
1529 LOG_DEBUG("Configured %i hw breakpoints", cortex_a8->brp_num);
1530
1531 target_set_examined(target);
1532 return ERROR_OK;
1533 }
1534
1535 static int cortex_a8_examine(struct target *target)
1536 {
1537 int retval = ERROR_OK;
1538
1539 /* don't re-probe hardware after each reset */
1540 if (!target_was_examined(target))
1541 retval = cortex_a8_examine_first(target);
1542
1543 /* Configure core debug access */
1544 if (retval == ERROR_OK)
1545 retval = cortex_a8_init_debug_access(target);
1546
1547 return retval;
1548 }
1549
1550 /*
1551 * Cortex-A8 target creation and initialization
1552 */
1553
1554 static int cortex_a8_init_target(struct command_context *cmd_ctx,
1555 struct target *target)
1556 {
1557 /* examine_first() does a bunch of this */
1558 return ERROR_OK;
1559 }
1560
1561 static int cortex_a8_init_arch_info(struct target *target,
1562 struct cortex_a8_common *cortex_a8, struct jtag_tap *tap)
1563 {
1564 struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
1565 struct arm *armv4_5 = &armv7a->armv4_5_common;
1566 struct swjdp_common *swjdp = &armv7a->swjdp_info;
1567
1568 /* Setup struct cortex_a8_common */
1569 cortex_a8->common_magic = CORTEX_A8_COMMON_MAGIC;
1570 armv4_5->arch_info = armv7a;
1571
1572 /* prepare JTAG information for the new target */
1573 cortex_a8->jtag_info.tap = tap;
1574 cortex_a8->jtag_info.scann_size = 4;
1575
1576 swjdp->dp_select_value = -1;
1577 swjdp->ap_csw_value = -1;
1578 swjdp->ap_tar_value = -1;
1579 swjdp->jtag_info = &cortex_a8->jtag_info;
1580 swjdp->memaccess_tck = 80;
1581
1582 /* Number of bits for tar autoincrement, impl. dep. at least 10 */
1583 swjdp->tar_autoincr_block = (1 << 10);
1584
1585 cortex_a8->fast_reg_read = 0;
1586
1587 /* register arch-specific functions */
1588 armv7a->examine_debug_reason = NULL;
1589
1590 armv7a->post_debug_entry = cortex_a8_post_debug_entry;
1591
1592 armv7a->pre_restore_context = NULL;
1593 armv7a->post_restore_context = NULL;
1594 armv7a->armv4_5_mmu.armv4_5_cache.ctype = -1;
1595 // armv7a->armv4_5_mmu.get_ttb = armv7a_get_ttb;
1596 armv7a->armv4_5_mmu.read_memory = cortex_a8_read_memory;
1597 armv7a->armv4_5_mmu.write_memory = cortex_a8_write_memory;
1598 // armv7a->armv4_5_mmu.disable_mmu_caches = armv7a_disable_mmu_caches;
1599 // armv7a->armv4_5_mmu.enable_mmu_caches = armv7a_enable_mmu_caches;
1600 armv7a->armv4_5_mmu.has_tiny_pages = 1;
1601 armv7a->armv4_5_mmu.mmu_enabled = 0;
1602
1603
1604 // arm7_9->handle_target_request = cortex_a8_handle_target_request;
1605
1606 /* REVISIT v7a setup should be in a v7a-specific routine */
1607 arm_init_arch_info(target, armv4_5);
1608 armv7a->common_magic = ARMV7_COMMON_MAGIC;
1609
1610 target_register_timer_callback(cortex_a8_handle_target_request, 1, 1, target);
1611
1612 return ERROR_OK;
1613 }
1614
1615 static int cortex_a8_target_create(struct target *target, Jim_Interp *interp)
1616 {
1617 struct cortex_a8_common *cortex_a8 = calloc(1, sizeof(struct cortex_a8_common));
1618
1619 cortex_a8_init_arch_info(target, cortex_a8, target->tap);
1620
1621 return ERROR_OK;
1622 }
1623
1624 COMMAND_HANDLER(cortex_a8_handle_cache_info_command)
1625 {
1626 struct target *target = get_current_target(CMD_CTX);
1627 struct armv7a_common *armv7a = target_to_armv7a(target);
1628
1629 return armv4_5_handle_cache_info_command(CMD_CTX,
1630 &armv7a->armv4_5_mmu.armv4_5_cache);
1631 }
1632
1633
1634 COMMAND_HANDLER(cortex_a8_handle_dbginit_command)
1635 {
1636 struct target *target = get_current_target(CMD_CTX);
1637
1638 cortex_a8_init_debug_access(target);
1639
1640 return ERROR_OK;
1641 }
1642
1643 static const struct command_registration cortex_a8_exec_command_handlers[] = {
1644 {
1645 .name = "cache_info",
1646 .handler = cortex_a8_handle_cache_info_command,
1647 .mode = COMMAND_EXEC,
1648 .help = "display information about target caches",
1649 },
1650 {
1651 .name = "dbginit",
1652 .handler = cortex_a8_handle_dbginit_command,
1653 .mode = COMMAND_EXEC,
1654 .help = "Initialize core debug",
1655 },
1656 COMMAND_REGISTRATION_DONE
1657 };
1658 static const struct command_registration cortex_a8_command_handlers[] = {
1659 {
1660 .chain = arm_command_handlers,
1661 },
1662 {
1663 .chain = armv7a_command_handlers,
1664 },
1665 {
1666 .name = "cortex_a8",
1667 .mode = COMMAND_ANY,
1668 .help = "Cortex-A8 command group",
1669 .chain = cortex_a8_exec_command_handlers,
1670 },
1671 COMMAND_REGISTRATION_DONE
1672 };
1673
1674 struct target_type cortexa8_target = {
1675 .name = "cortex_a8",
1676
1677 .poll = cortex_a8_poll,
1678 .arch_state = armv7a_arch_state,
1679
1680 .target_request_data = NULL,
1681
1682 .halt = cortex_a8_halt,
1683 .resume = cortex_a8_resume,
1684 .step = cortex_a8_step,
1685
1686 .assert_reset = cortex_a8_assert_reset,
1687 .deassert_reset = cortex_a8_deassert_reset,
1688 .soft_reset_halt = NULL,
1689
1690 /* REVISIT allow exporting VFP3 registers ... */
1691 .get_gdb_reg_list = arm_get_gdb_reg_list,
1692
1693 .read_memory = cortex_a8_read_memory,
1694 .write_memory = cortex_a8_write_memory,
1695 .bulk_write_memory = cortex_a8_bulk_write_memory,
1696
1697 .checksum_memory = arm_checksum_memory,
1698 .blank_check_memory = arm_blank_check_memory,
1699
1700 .run_algorithm = armv4_5_run_algorithm,
1701
1702 .add_breakpoint = cortex_a8_add_breakpoint,
1703 .remove_breakpoint = cortex_a8_remove_breakpoint,
1704 .add_watchpoint = NULL,
1705 .remove_watchpoint = NULL,
1706
1707 .commands = cortex_a8_command_handlers,
1708 .target_create = cortex_a8_target_create,
1709 .init_target = cortex_a8_init_target,
1710 .examine = cortex_a8_examine,
1711 };

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)