cortex_a8.c 44.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
 *   Copyright (C) 2006 by Magnus Lundin                                   *
 *   lundin@mlu.mine.nu                                                    *
 *                                                                         *
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
 *   Copyright (C) 2009 by Dirk Behme                                      *
 *   dirk.behme@gmail.com - copy from cortex_m3                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 *   Cortex-A8(tm) TRM, ARM DDI 0344H                                      *
 *                                                                         *
 ***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "cortex_a8.h"
37
38
39
#include "armv7a.h"
#include "armv4_5.h"

40
#include "target_request.h"
41
#include "target_type.h"
42

43
44
45
46
static int cortex_a8_poll(target_t *target);
static int cortex_a8_debug_entry(target_t *target);
static int cortex_a8_restore_context(target_t *target);
static int cortex_a8_set_breakpoint(struct target_s *target,
47
		struct breakpoint *breakpoint, uint8_t matchmode);
48
static int cortex_a8_unset_breakpoint(struct target_s *target,
49
		struct breakpoint *breakpoint);
50
static int cortex_a8_dap_read_coreregister_u32(target_t *target,
51
		uint32_t *value, int regnum);
52
static int cortex_a8_dap_write_coreregister_u32(target_t *target,
53
54
55
56
57
58
59
60
61
62
63
64
		uint32_t value, int regnum);
/*
 * FIXME do topology discovery using the ROM; don't
 * assume this is an OMAP3.
 */
#define swjdp_memoryap 0
#define swjdp_debugap 1
#define OMAP3530_DEBUG_BASE 0x54011000

/*
 * Cortex-A8 Basic debug access, very low level assumes state is saved
 */
65
static int cortex_a8_init_debug_access(target_t *target)
66
{
67
	struct armv7a_common *armv7a = target_to_armv7a(target);
68
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
69
70
71
72
73
74
75
76
77
78
79
80
81
82

	int retval;
	uint32_t dummy;

	LOG_DEBUG(" ");

	/* Unlocking the debug registers for modification */
	/* The debugport might be uninitialised so try twice */
	retval = mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
	if (retval != ERROR_OK)
		mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55);
	/* Clear Sticky Power Down status Bit in PRSR to enable access to
	   the registers in the Core Power Domain */
	retval = mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_PRSR, &dummy);
83
84
	/* Enabling of instruction execution in debug mode is done in debug_entry code */

85
	/* Resync breakpoint registers */
86

87
88
	/* Since this is likley called from init or reset, update targtet state information*/
	cortex_a8_poll(target);
89

90
	return retval;
91
92
93
94
95
}

int cortex_a8_exec_opcode(target_t *target, uint32_t opcode)
{
	uint32_t dscr;
96
	int retval;
97
	struct armv7a_common *armv7a = target_to_armv7a(target);
98
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
99

ntfreak's avatar
ntfreak committed
100
	LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
101
102
	do
	{
103
		retval = mem_ap_read_atomic_u32(swjdp,
104
				armv7a->debug_base + CPUDBG_DSCR, &dscr);
105
		if (retval != ERROR_OK)
106
107
		{
			LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode);
108
			return retval;
109
		}
110
	}
111
	while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
112

113
	mem_ap_write_u32(swjdp, armv7a->debug_base + CPUDBG_ITR, opcode);
114

115
	do
116
	{
117
		retval = mem_ap_read_atomic_u32(swjdp,
118
				armv7a->debug_base + CPUDBG_DSCR, &dscr);
119
		if (retval != ERROR_OK)
120
121
		{
			LOG_ERROR("Could not read DSCR register");
122
			return retval;
123
		}
124
	}
125
	while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
126

127
	return retval;
128
129
130
131
132
133
}

/**************************************************************************
Read core register with very few exec_opcode, fast but needs work_area.
This can cause problems with MMU active.
**************************************************************************/
134
static int cortex_a8_read_regs_through_mem(target_t *target, uint32_t address,
135
136
137
		uint32_t * regfile)
{
	int retval = ERROR_OK;
138
	struct armv7a_common *armv7a = target_to_armv7a(target);
139
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
140
141
142
143
144
145
146
147
148
149
150

	cortex_a8_dap_read_coreregister_u32(target, regfile, 0);
	cortex_a8_dap_write_coreregister_u32(target, address, 0);
	cortex_a8_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0));
	dap_ap_select(swjdp, swjdp_memoryap);
	mem_ap_read_buf_u32(swjdp, (uint8_t *)(&regfile[1]), 4*15, address);
	dap_ap_select(swjdp, swjdp_debugap);

	return retval;
}

151
static int cortex_a8_read_cp(target_t *target, uint32_t *value, uint8_t CP,
152
153
154
		uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
{
	int retval;
155
	struct armv7a_common *armv7a = target_to_armv7a(target);
156
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
157
158
159
160
161
162
163

	cortex_a8_exec_opcode(target, ARMV4_5_MRC(CP, op1, 0, CRn, CRm, op2));
	/* Move R0 to DTRTX */
	cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));

	/* Read DCCTX */
	retval = mem_ap_read_atomic_u32(swjdp,
164
			armv7a->debug_base + CPUDBG_DTRTX, value);
165
166
167
168

	return retval;
}

169
static int cortex_a8_write_cp(target_t *target, uint32_t value,
170
171
172
	uint8_t CP, uint8_t op1, uint8_t CRn, uint8_t CRm, uint8_t op2)
{
	int retval;
173
	uint32_t dscr;
174
	struct armv7a_common *armv7a = target_to_armv7a(target);
175
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
176

177
178
179
180
181
182
183
184
185
186
187
	LOG_DEBUG("CP%i, CRn %i, value 0x%08" PRIx32, CP, CRn, value);

	/* Check that DCCRX is not full */
	retval = mem_ap_read_atomic_u32(swjdp,
				armv7a->debug_base + CPUDBG_DSCR, &dscr);
	if (dscr & (1 << DSCR_DTR_RX_FULL))
	{
		LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
		/* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode  0xEE000E15 */
		cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
	}
188

189
	retval = mem_ap_write_u32(swjdp,
190
			armv7a->debug_base + CPUDBG_DTRRX, value);
191
192
193
	/* Move DTRRX to r0 */
	cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));

194
	cortex_a8_exec_opcode(target, ARMV4_5_MCR(CP, op1, 0, CRn, CRm, op2));
195
196
197
	return retval;
}

198
static int cortex_a8_read_cp15(target_t *target, uint32_t op1, uint32_t op2,
199
200
201
202
203
		uint32_t CRn, uint32_t CRm, uint32_t *value)
{
	return cortex_a8_read_cp(target, value, 15, op1, CRn, CRm, op2);
}

204
static int cortex_a8_write_cp15(target_t *target, uint32_t op1, uint32_t op2,
205
206
207
208
209
		uint32_t CRn, uint32_t CRm, uint32_t value)
{
	return cortex_a8_write_cp(target, value, 15, op1, CRn, CRm, op2);
}

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
static int cortex_a8_mrc(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
{
	if (cpnum!=15)
	{
		LOG_ERROR("Only cp15 is supported");
		return ERROR_FAIL;
	}
	return cortex_a8_read_cp15(target, op1, op2, CRn, CRm, value);
}

static int cortex_a8_mcr(target_t *target, int cpnum, uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
{
	if (cpnum!=15)
	{
		LOG_ERROR("Only cp15 is supported");
		return ERROR_FAIL;
	}
	return cortex_a8_write_cp15(target, op1, op2, CRn, CRm, value);
}



232
static int cortex_a8_dap_read_coreregister_u32(target_t *target,
233
234
235
236
		uint32_t *value, int regnum)
{
	int retval = ERROR_OK;
	uint8_t reg = regnum&0xFF;
237
	uint32_t dscr;
238
	struct armv7a_common *armv7a = target_to_armv7a(target);
239
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259

	if (reg > 16)
		return retval;

	if (reg < 15)
	{
		/* Rn to DCCTX, MCR p14, 0, Rd, c0, c5, 0,  0xEE000E15 */
		cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, reg, 0, 5, 0));
	}
	else if (reg == 15)
	{
		cortex_a8_exec_opcode(target, 0xE1A0000F);
		cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
	}
	else if (reg == 16)
	{
		cortex_a8_exec_opcode(target, ARMV4_5_MRS(0, 0));
		cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
	}

260
261
262
263
	/* Read DTRRTX */
	do
	{
		retval = mem_ap_read_atomic_u32(swjdp,
264
				armv7a->debug_base + CPUDBG_DSCR, &dscr);
265
	}
266
	while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0); /* Wait for DTRRXfull */
267

268
	retval = mem_ap_read_atomic_u32(swjdp,
269
			armv7a->debug_base + CPUDBG_DTRTX, value);
270
271
272
273

	return retval;
}

274
static int cortex_a8_dap_write_coreregister_u32(target_t *target, uint32_t value, int regnum)
275
276
277
{
	int retval = ERROR_OK;
	uint8_t Rd = regnum&0xFF;
278
	uint32_t dscr;
279
	struct armv7a_common *armv7a = target_to_armv7a(target);
280
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
281

282
283
284
285
286
287
288
289
290
291
292
	LOG_DEBUG("register %i, value 0x%08" PRIx32, regnum, value);

	/* Check that DCCRX is not full */
	retval = mem_ap_read_atomic_u32(swjdp,
				armv7a->debug_base + CPUDBG_DSCR, &dscr);
	if (dscr & (1 << DSCR_DTR_RX_FULL))
	{
		LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
		/* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode  0xEE000E15 */
		cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
	}
293

294
295
296
297
298
	if (Rd > 16)
		return retval;

	/* Write to DCCRX */
	retval = mem_ap_write_u32(swjdp,
299
			armv7a->debug_base + CPUDBG_DTRRX, value);
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321

	if (Rd < 15)
	{
		/* DCCRX to Rd, MCR p14, 0, Rd, c0, c5, 0,  0xEE000E15 */
		cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0));
	}
	else if (Rd == 15)
	{
		cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
		cortex_a8_exec_opcode(target, 0xE1A0F000);
	}
	else if (Rd == 16)
	{
		cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
		cortex_a8_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, 0));
		/* Execute a PrefetchFlush instruction through the ITR. */
		cortex_a8_exec_opcode(target, ARMV4_5_MCR(15, 0, 0, 7, 5, 4));
	}

	return retval;
}

322
/* Write to memory mapped registers directly with no cache or mmu handling */
323
static int cortex_a8_dap_write_memap_register_u32(target_t *target, uint32_t address, uint32_t value)
324
325
{
	int retval;
326
	struct armv7a_common *armv7a = target_to_armv7a(target);
327
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
328
329
330
331
332
333

	retval = mem_ap_write_atomic_u32(swjdp, address, value);

	return retval;
}

334
335
336
337
/*
 * Cortex-A8 Run control
 */

338
static int cortex_a8_poll(target_t *target)
339
340
341
{
	int retval = ERROR_OK;
	uint32_t dscr;
342
	struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
343
	struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
344
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
345
346
	enum target_state prev_target_state = target->state;
	uint8_t saved_apsel = dap_ap_get_select(swjdp);
347

348
349
	dap_ap_select(swjdp, swjdp_debugap);
	retval = mem_ap_read_atomic_u32(swjdp,
350
			armv7a->debug_base + CPUDBG_DSCR, &dscr);
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
	if (retval != ERROR_OK)
	{
		dap_ap_select(swjdp, saved_apsel);
		return retval;
	}
	cortex_a8->cpudbg_dscr = dscr;

	if ((dscr & 0x3) == 0x3)
	{
		if (prev_target_state != TARGET_HALTED)
		{
			/* We have a halting debug event */
			LOG_DEBUG("Target halted");
			target->state = TARGET_HALTED;
			if ((prev_target_state == TARGET_RUNNING)
					|| (prev_target_state == TARGET_RESET))
			{
				retval = cortex_a8_debug_entry(target);
				if (retval != ERROR_OK)
					return retval;

				target_call_event_callbacks(target,
						TARGET_EVENT_HALTED);
			}
			if (prev_target_state == TARGET_DEBUG_RUNNING)
			{
				LOG_DEBUG(" ");

				retval = cortex_a8_debug_entry(target);
				if (retval != ERROR_OK)
					return retval;

				target_call_event_callbacks(target,
						TARGET_EVENT_DEBUG_HALTED);
			}
		}
	}
	else if ((dscr & 0x3) == 0x2)
	{
		target->state = TARGET_RUNNING;
	}
	else
	{
ntfreak's avatar
ntfreak committed
394
		LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr);
395
396
397
398
399
400
401
402
		target->state = TARGET_UNKNOWN;
	}

	dap_ap_select(swjdp, saved_apsel);

	return retval;
}

403
static int cortex_a8_halt(target_t *target)
404
405
{
	int retval = ERROR_OK;
406
	uint32_t dscr;
407
	struct armv7a_common *armv7a = target_to_armv7a(target);
408
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
409
410
411
	uint8_t saved_apsel = dap_ap_get_select(swjdp);
	dap_ap_select(swjdp, swjdp_debugap);

412
413
414
415
	/*
	 * Tell the core to be halted by writing DRCR with 0x1
	 * and then wait for the core to be halted.
	 */
416
	retval = mem_ap_write_atomic_u32(swjdp,
417
			armv7a->debug_base + CPUDBG_DRCR, 0x1);
418

419
420
421
	/*
	 * enter halting debug mode
	 */
422
	mem_ap_read_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DSCR, &dscr);
423
	retval = mem_ap_write_atomic_u32(swjdp,
424
		armv7a->debug_base + CPUDBG_DSCR, dscr | (1 << DSCR_HALT_DBG_MODE));
425

426
427
428
429
430
	if (retval != ERROR_OK)
		goto out;

	do {
		mem_ap_read_atomic_u32(swjdp,
431
			armv7a->debug_base + CPUDBG_DSCR, &dscr);
432
	} while ((dscr & (1 << DSCR_CORE_HALTED)) == 0);
433

434
435
	target->debug_reason = DBG_REASON_DBGRQ;

436
437
out:
	dap_ap_select(swjdp, saved_apsel);
438
439
440
	return retval;
}

441
static int cortex_a8_resume(struct target_s *target, int current,
442
443
		uint32_t address, int handle_breakpoints, int debug_execution)
{
444
	struct armv7a_common *armv7a = target_to_armv7a(target);
445
	struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
446
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
447

448
//	struct breakpoint *breakpoint = NULL;
449
	uint32_t resume_pc, dscr;
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492

	uint8_t saved_apsel = dap_ap_get_select(swjdp);
	dap_ap_select(swjdp, swjdp_debugap);

	if (!debug_execution)
	{
		target_free_all_working_areas(target);
//		cortex_m3_enable_breakpoints(target);
//		cortex_m3_enable_watchpoints(target);
	}

#if 0
	if (debug_execution)
	{
		/* Disable interrupts */
		/* We disable interrupts in the PRIMASK register instead of
		 * masking with C_MASKINTS,
		 * This is probably the same issue as Cortex-M3 Errata 377493:
		 * C_MASKINTS in parallel with disabled interrupts can cause
		 * local faults to not be taken. */
		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1);
		armv7m->core_cache->reg_list[ARMV7M_PRIMASK].dirty = 1;
		armv7m->core_cache->reg_list[ARMV7M_PRIMASK].valid = 1;

		/* Make sure we are in Thumb mode */
		buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32,
			buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1 << 24));
		armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1;
		armv7m->core_cache->reg_list[ARMV7M_xPSR].valid = 1;
	}
#endif

	/* current = 1: continue on current pc, otherwise continue at <address> */
	resume_pc = buf_get_u32(
			ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 15).value,
			0, 32);
	if (!current)
		resume_pc = address;

	/* Make sure that the Armv7 gdb thumb fixups does not
	 * kill the return address
	 */
493
	if (armv7a->core_state == ARMV7A_STATE_ARM)
494
495
496
	{
		resume_pc &= 0xFFFFFFFC;
	}
497
498
499
500
501
502
503
	/* When the return address is loaded into PC
	 * bit 0 must be 1 to stay in Thumb state
	 */
	if (armv7a->core_state == ARMV7A_STATE_THUMB)
	{
		resume_pc |= 0x1;
	}
ntfreak's avatar
ntfreak committed
504
	LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc);
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
	buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 15).value,
			0, 32, resume_pc);
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
			armv4_5->core_mode, 15).dirty = 1;
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
			armv4_5->core_mode, 15).valid = 1;

	cortex_a8_restore_context(target);
//	arm7_9_restore_context(target); TODO Context is currently NOT Properly restored
#if 0
	/* the front-end may request us not to handle breakpoints */
	if (handle_breakpoints)
	{
		/* Single step past breakpoint at current address */
		if ((breakpoint = breakpoint_find(target, resume_pc)))
		{
			LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
			cortex_m3_unset_breakpoint(target, breakpoint);
			cortex_m3_single_step_core(target);
			cortex_m3_set_breakpoint(target, breakpoint);
		}
	}

#endif
530
	/* Restart core and wait for it to be started */
531
	mem_ap_write_atomic_u32(swjdp, armv7a->debug_base + CPUDBG_DRCR, 0x2);
532

533
534
	do {
		mem_ap_read_atomic_u32(swjdp,
535
			armv7a->debug_base + CPUDBG_DSCR, &dscr);
536
	} while ((dscr & (1 << DSCR_CORE_RESTARTED)) == 0);
537

538
539
540
541
542
543
544
545
546
547
	target->debug_reason = DBG_REASON_NOTHALTED;
	target->state = TARGET_RUNNING;

	/* registers are now invalid */
	armv4_5_invalidate_core_regs(target);

	if (!debug_execution)
	{
		target->state = TARGET_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
ntfreak's avatar
ntfreak committed
548
		LOG_DEBUG("target resumed at 0x%" PRIx32, resume_pc);
549
550
551
552
553
	}
	else
	{
		target->state = TARGET_DEBUG_RUNNING;
		target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
ntfreak's avatar
ntfreak committed
554
		LOG_DEBUG("target debug resumed at 0x%" PRIx32, resume_pc);
555
556
557
558
559
560
561
	}

	dap_ap_select(swjdp, saved_apsel);

	return ERROR_OK;
}

562
static int cortex_a8_debug_entry(target_t *target)
563
564
{
	int i;
565
	uint32_t regfile[16], pc, cpsr, dscr;
566
	int retval = ERROR_OK;
567
	struct working_area *regfile_working_area = NULL;
568
	struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
569
	struct armv7a_common *armv7a = target_to_armv7a(target);
570
	struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
571
	struct swjdp_common *swjdp = &armv7a->swjdp_info;
572

ntfreak's avatar
ntfreak committed
573
	LOG_DEBUG("dscr = 0x%08" PRIx32, cortex_a8->cpudbg_dscr);
574

575
576
	/* Enable the ITR execution once we are in debug mode */
	mem_ap_read_atomic_u32(swjdp,
577
				armv7a->debug_base + CPUDBG_DSCR, &dscr);
578
	dscr |= (1 << DSCR_EXT_INT_EN);
579
	retval = mem_ap_write_atomic_u32(swjdp,
580
			armv7a->debug_base + CPUDBG_DSCR, dscr);
581

582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
	/* Examine debug reason */
	switch ((cortex_a8->cpudbg_dscr >> 2)&0xF)
	{
		case 0:
		case 4:
			target->debug_reason = DBG_REASON_DBGRQ;
			break;
		case 1:
		case 3:
			target->debug_reason = DBG_REASON_BREAKPOINT;
			break;
		case 10:
			target->debug_reason = DBG_REASON_WATCHPOINT;
			break;
		default:
			target->debug_reason = DBG_REASON_UNDEFINED;
			break;
	}

	/* Examine target state and mode */
	if (cortex_a8->fast_reg_read)
		target_alloc_working_area(target, 64, &regfile_working_area);

	/* First load register acessible through core debug port*/
	if (!regfile_working_area)
	{
		for (i = 0; i <= 15; i++)
			cortex_a8_dap_read_coreregister_u32(target,
					&regfile[i], i);
	}
	else
	{
614
		dap_ap_select(swjdp, swjdp_memoryap);
615
616
617
618
619
620
621
622
623
		cortex_a8_read_regs_through_mem(target,
				regfile_working_area->address, regfile);
		dap_ap_select(swjdp, swjdp_memoryap);
		target_free_working_area(target, regfile_working_area);
	}

	cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
	pc = regfile[15];
	dap_ap_select(swjdp, swjdp_debugap);
ntfreak's avatar
ntfreak committed
624
	LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
625

626
627
	armv4_5->core_mode = cpsr & 0x1F;
	armv7a->core_state = (cpsr & 0x20)?ARMV7A_STATE_THUMB:ARMV7A_STATE_ARM;
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

	for (i = 0; i <= ARM_PC; i++)
	{
		buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
					armv4_5->core_mode, i).value,
				0, 32, regfile[i]);
		ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, i).valid = 1;
		ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, i).dirty = 0;
	}
	buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 16).value,
			0, 32, cpsr);
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).valid = 1;
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;

	/* Fixup PC Resume Address */
646
	if (armv7a->core_state == ARMV7A_STATE_THUMB)
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
	{
		// T bit set for Thumb or ThumbEE state
		regfile[ARM_PC] -= 4;
	}
	else
	{
		// ARM state
		regfile[ARM_PC] -= 8;
	}
	buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, ARM_PC).value,
			0, 32, regfile[ARM_PC]);

	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0)
		.dirty = ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 0).valid;
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15)
		.dirty = ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 15).valid;

#if 0
/* TODO, Move this */
	uint32_t cp15_control_register, cp15_cacr, cp15_nacr;
	cortex_a8_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
	LOG_DEBUG("cp15_control_register = 0x%08x", cp15_control_register);

	cortex_a8_read_cp(target, &cp15_cacr, 15, 0, 1, 0, 2);
	LOG_DEBUG("cp15 Coprocessor Access Control Register = 0x%08x", cp15_cacr);

	cortex_a8_read_cp(target, &cp15_nacr, 15, 0, 1, 1, 2);
	LOG_DEBUG("cp15 Nonsecure Access Control Register = 0x%08x", cp15_nacr);
#endif

	/* Are we in an exception handler */
//	armv4_5->exception_number = 0;
	if (armv7a->post_debug_entry)
		armv7a->post_debug_entry(target);



	return retval;

}

691
static void cortex_a8_post_debug_entry(target_t *target)
692
{
693
	struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
694
	struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
695
696
697
698
699

//	cortex_a8_read_cp(target, &cp15_control_register, 15, 0, 1, 0, 0);
	/* examine cp15 control reg */
	armv7a->read_cp15(target, 0, 0, 1, 0, &cortex_a8->cp15_control_reg);
	jtag_execute_queue();
ntfreak's avatar
ntfreak committed
700
	LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a8->cp15_control_reg);
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722

	if (armv7a->armv4_5_mmu.armv4_5_cache.ctype == -1)
	{
		uint32_t cache_type_reg;
		/* identify caches */
		armv7a->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
		jtag_execute_queue();
		/* FIXME the armv4_4 cache info DOES NOT APPLY to Cortex-A8 */
		armv4_5_identify_cache(cache_type_reg,
				&armv7a->armv4_5_mmu.armv4_5_cache);
	}

	armv7a->armv4_5_mmu.mmu_enabled =
			(cortex_a8->cp15_control_reg & 0x1U) ? 1 : 0;
	armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled =
			(cortex_a8->cp15_control_reg & 0x4U) ? 1 : 0;
	armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled =
			(cortex_a8->cp15_control_reg & 0x1000U) ? 1 : 0;


}

723
static int cortex_a8_step(struct target_s *target, int current, uint32_t address,
724
725
		int handle_breakpoints)
{
726
	struct armv7a_common *armv7a = target_to_armv7a(target);
727
	struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
728
729
	struct breakpoint *breakpoint = NULL;
	struct breakpoint stepbreakpoint;
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764

	int timeout = 100;

	if (target->state != TARGET_HALTED)
	{
		LOG_WARNING("target not halted");
		return ERROR_TARGET_NOT_HALTED;
	}

	/* current = 1: continue on current pc, otherwise continue at <address> */
	if (!current)
	{
		buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
					armv4_5->core_mode, ARM_PC).value,
				0, 32, address);
	}
	else
	{
		address = buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
					armv4_5->core_mode, ARM_PC).value,
				0, 32);
	}

	/* The front-end may request us not to handle breakpoints.
	 * But since Cortex-A8 uses breakpoint for single step,
	 * we MUST handle breakpoints.
	 */
	handle_breakpoints = 1;
	if (handle_breakpoints) {
		breakpoint = breakpoint_find(target,
				buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
					armv4_5->core_mode, 15).value,
			0, 32));
		if (breakpoint)
			cortex_a8_unset_breakpoint(target, breakpoint);
765
766
	}

767
768
	/* Setup single step breakpoint */
	stepbreakpoint.address = address;
769
	stepbreakpoint.length = (armv7a->core_state == ARMV7A_STATE_THUMB) ? 2 : 4;
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
	stepbreakpoint.type = BKPT_HARD;
	stepbreakpoint.set = 0;

	/* Break on IVA mismatch */
	cortex_a8_set_breakpoint(target, &stepbreakpoint, 0x04);

	target->debug_reason = DBG_REASON_SINGLESTEP;

	cortex_a8_resume(target, 1, address, 0, 0);

	while (target->state != TARGET_HALTED)
	{
		cortex_a8_poll(target);
		if (--timeout == 0)
		{
			LOG_WARNING("timeout waiting for target halt");
			break;
		}
	}

	cortex_a8_unset_breakpoint(target, &stepbreakpoint);
	if (timeout > 0) target->debug_reason = DBG_REASON_BREAKPOINT;

	if (breakpoint)
		cortex_a8_set_breakpoint(target, breakpoint, 0);

	if (target->state != TARGET_HALTED)
		LOG_DEBUG("target stepped");

799
800
801
	return ERROR_OK;
}

802
static int cortex_a8_restore_context(target_t *target)
803
{
804
805
	int i;
	uint32_t value;
806
	struct armv7a_common *armv7a = target_to_armv7a(target);
807
	struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common;
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833

	LOG_DEBUG(" ");

	if (armv7a->pre_restore_context)
		armv7a->pre_restore_context(target);

	for (i = 15; i >= 0; i--)
	{
		if (ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
					armv4_5->core_mode, i).dirty)
		{
			value = buf_get_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
						armv4_5->core_mode, i).value,
					0, 32);
			/* TODO Check return values */
			cortex_a8_dap_write_coreregister_u32(target, value, i);
		}
	}

	if (armv7a->post_restore_context)
		armv7a->post_restore_context(target);

	return ERROR_OK;
}


834
#if 0
835
836
837
/*
 * Cortex-A8 Core register functions
 */
838
static int cortex_a8_load_core_reg_u32(struct target_s *target, int num,
839
840
841
		armv4_5_mode_t mode, uint32_t * value)
{
	int retval;
842
	struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
843
844
845
846
847
848
849
850
851
852
853

	if ((num <= ARM_CPSR))
	{
		/* read a normal core register */
		retval = cortex_a8_dap_read_coreregister_u32(target, value, num);

		if (retval != ERROR_OK)
		{
			LOG_ERROR("JTAG failure %i", retval);
			return ERROR_JTAG_DEVICE_ERROR;
		}
ntfreak's avatar
ntfreak committed
854
		LOG_DEBUG("load from core reg %i value 0x%" PRIx32, num, *value);
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
	}
	else
	{
		return ERROR_INVALID_ARGUMENTS;
	}

	/* Register other than r0 - r14 uses r0 for access */
	if (num > 14)
		ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 0).dirty =
			ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 0).valid;
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 15).dirty =
			ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
				armv4_5->core_mode, 15).valid;

	return ERROR_OK;
}

875
static int cortex_a8_store_core_reg_u32(struct target_s *target, int num,
876
877
878
879
		armv4_5_mode_t mode, uint32_t value)
{
	int retval;
//	uint32_t reg;
880
	struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904

#ifdef ARMV7_GDB_HACKS
	/* If the LR register is being modified, make sure it will put us
	 * in "thumb" mode, or an INVSTATE exception will occur. This is a
	 * hack to deal with the fact that gdb will sometimes "forge"
	 * return addresses, and doesn't set the LSB correctly (i.e., when
	 * printing expressions containing function calls, it sets LR=0.) */

	if (num == 14)
		value |= 0x01;
#endif

	if ((num <= ARM_CPSR))
	{
		retval = cortex_a8_dap_write_coreregister_u32(target, value, num);
		if (retval != ERROR_OK)
		{
			LOG_ERROR("JTAG failure %i", retval);
			ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
					armv4_5->core_mode, num).dirty =
				ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
					armv4_5->core_mode, num).valid;
			return ERROR_JTAG_DEVICE_ERROR;
		}
ntfreak's avatar
ntfreak committed
905
		LOG_DEBUG("write core reg %i value 0x%" PRIx32, num, value);
906
907
908
909
910
911
912
913
	}
	else
	{
		return ERROR_INVALID_ARGUMENTS;
	}

	return ERROR_OK;
}
914
#endif
915
916


917
static int cortex_a8_read_core_reg(struct target_s *target, int num,
918
919
920
921
		enum armv4_5_mode mode)
{
	uint32_t value;
	int retval;
922
923
	struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);

924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
	cortex_a8_dap_read_coreregister_u32(target, &value, num);

	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		return retval;
	}

	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;
	buf_set_u32(ARMV7A_CORE_REG_MODE(armv4_5->core_cache,
			mode, num).value, 0, 32, value);

	return ERROR_OK;
}

int cortex_a8_write_core_reg(struct target_s *target, int num,
		enum armv4_5_mode mode, uint32_t value)
{
	int retval;
943
	struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962

	cortex_a8_dap_write_coreregister_u32(target, value, num);
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
		return retval;
	}

	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).valid = 1;
	ARMV7A_CORE_REG_MODE(armv4_5->core_cache, mode, num).dirty = 0;

	return ERROR_OK;
}


/*
 * Cortex-A8 Breakpoint and watchpoint fuctions
 */

/* Setup hardware Breakpoint Register Pair */
963
static int cortex_a8_set_breakpoint(struct target_s *target,
964
		struct breakpoint *breakpoint, uint8_t matchmode)
965
966
967
968
969
{
	int retval;
	int brp_i=0;
	uint32_t control;
	uint8_t byte_addr_select = 0x0F;
970
	struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
971
	struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
972
	struct cortex_a8_brp * brp_list = cortex_a8->brp_list;
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999

	if (breakpoint->set)
	{
		LOG_WARNING("breakpoint already set");
		return ERROR_OK;
	}

	if (breakpoint->type == BKPT_HARD)
	{
		while (brp_list[brp_i].used && (brp_i < cortex_a8->brp_num))
			brp_i++ ;
		if (brp_i >= cortex_a8->brp_num)
		{
			LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
			exit(-1);
		}
		breakpoint->set = brp_i + 1;
		if (breakpoint->length == 2)
		{
			byte_addr_select = (3 << (breakpoint->address & 0x02));
		}
		control = ((matchmode & 0x7) << 20)
				| (byte_addr_select << 5)
				| (3 << 1) | 1;
		brp_list[brp_i].used = 1;
		brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC);
		brp_list[brp_i].control = control;
1000
		cortex_a8_dap_write_memap_register_u32(target, armv7a->debug_base
For faster browsing, not all history is shown. View entire blame