arm7_9_common.c 79.4 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
6
7
 *   Copyright (C) 2007,2008 yvind Harboe                                      *
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *   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.             *
 ***************************************************************************/
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
26
27
#endif

#include "replacements.h"
28
29
30

#include "embeddedice.h"
#include "target.h"
31
#include "target_request.h"
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include "armv4_5.h"
#include "arm_jtag.h"
#include "jtag.h"
#include "log.h"
#include "arm7_9_common.h"
#include "breakpoints.h"

#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <errno.h>

int arm7_9_debug_entry(target_t *target);
int arm7_9_enable_sw_bkpts(struct target_s *target);

/* command handler forward declarations */
int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_read_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_write_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_sw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
59
int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
60
int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
61
int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
62
63
64
65
66

int arm7_9_reinit_embeddedice(target_t *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
67

68
	breakpoint_t *breakpoint = target->breakpoints;
69

70
71
72
	arm7_9->wp_available = 2;
	arm7_9->wp0_used = 0;
	arm7_9->wp1_used = 0;
73

74
75
76
77
78
79
80
81
82
	/* mark all hardware breakpoints as unset */
	while (breakpoint)
	{
		if (breakpoint->type == BKPT_HARD)
		{
			breakpoint->set = 0;
		}
		breakpoint = breakpoint->next;
	}
83

84
85
86
87
88
	if (arm7_9->sw_bkpts_enabled && arm7_9->sw_bkpts_use_wp)
	{
		arm7_9->sw_bkpts_enabled = 0;
		arm7_9_enable_sw_bkpts(target);
	}
89

90
91
92
	return ERROR_OK;
}

93
94
/* set things up after a reset / on startup */
int arm7_9_setup(target_t *target)
95
{
96
	/* a test-logic reset have occured
97
98
99
	 * the EmbeddedICE registers have been reset
	 * hardware breakpoints have been cleared
	 */
100
	return arm7_9_reinit_embeddedice(target);
101
102
103
104
105
106
}

int arm7_9_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
107

108
109
110
111
	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
	{
		return -1;
	}
112

113
114
115
116
	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
	{
		return -1;
	}
117

118
119
	*armv4_5_p = armv4_5;
	*arm7_9_p = arm7_9;
120

121
122
123
124
125
126
127
	return ERROR_OK;
}

int arm7_9_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
128

129
130
	if (target->state != TARGET_HALTED)
	{
131
		LOG_WARNING("target not halted");
132
133
		return ERROR_TARGET_NOT_HALTED;
	}
134

135
136
137
138
139
	if (arm7_9->force_hw_bkpts)
		breakpoint->type = BKPT_HARD;

	if (breakpoint->set)
	{
140
		LOG_WARNING("breakpoint already set");
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
		return ERROR_OK;
	}

	if (breakpoint->type == BKPT_HARD)
	{
		/* either an ARM (4 byte) or Thumb (2 byte) breakpoint */
		u32 mask = (breakpoint->length == 4) ? 0x3u : 0x1u;
		if (!arm7_9->wp0_used)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], breakpoint->address);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffffu);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);

			jtag_execute_queue();
			arm7_9->wp0_used = 1;
			breakpoint->set = 1;
		}
		else if (!arm7_9->wp1_used)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], breakpoint->address);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0xffffffffu);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE);

			jtag_execute_queue();
			arm7_9->wp1_used = 1;
			breakpoint->set = 2;
		}
		else
		{
174
			LOG_ERROR("BUG: no hardware comparator available");
175
176
177
178
179
180
181
			return ERROR_OK;
		}
	}
	else if (breakpoint->type == BKPT_SOFT)
	{
		if (breakpoint->length == 4)
		{
ntfreak's avatar
ntfreak committed
182
			u32 verify = 0xffffffff;
183
			/* keep the original instruction in target endianness */
184
			target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
drath's avatar
drath committed
185
			/* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
186
			target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt);
187

ntfreak's avatar
ntfreak committed
188
189
190
			target->type->read_memory(target, breakpoint->address, 4, 1, (u8 *)&verify);
			if (verify != arm7_9->arm_bkpt)
			{
191
				LOG_ERROR("Unable to set 32 bit software breakpoint at address %08x - check that memory is read/writable", breakpoint->address);
ntfreak's avatar
ntfreak committed
192
193
				return ERROR_OK;
			}
194
195
196
		}
		else
		{
ntfreak's avatar
ntfreak committed
197
			u16 verify = 0xffff;
198
			/* keep the original instruction in target endianness */
199
			target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
drath's avatar
drath committed
200
201
			/* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
			target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt);
202

ntfreak's avatar
ntfreak committed
203
204
205
			target->type->read_memory(target, breakpoint->address, 2, 1, (u8 *)&verify);
			if (verify != arm7_9->thumb_bkpt)
			{
206
				LOG_ERROR("Unable to set thumb software breakpoint at address %08x - check that memory is read/writable", breakpoint->address);
ntfreak's avatar
ntfreak committed
207
208
				return ERROR_OK;
			}
209
210
211
212
213
214
215
216
217
218
219
220
		}
		breakpoint->set = 1;
	}

	return ERROR_OK;

}

int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
221

222
223
	if (target->state != TARGET_HALTED)
	{
224
		LOG_WARNING("target not halted");
225
226
227
228
229
		return ERROR_TARGET_NOT_HALTED;
	}

	if (!breakpoint->set)
	{
230
		LOG_WARNING("breakpoint not set");
231
232
		return ERROR_OK;
	}
233

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
	if (breakpoint->type == BKPT_HARD)
	{
		if (breakpoint->set == 1)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
			jtag_execute_queue();
			arm7_9->wp0_used = 0;
		}
		else if (breakpoint->set == 2)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
			jtag_execute_queue();
			arm7_9->wp1_used = 0;
		}
		breakpoint->set = 0;
	}
	else
	{
252
		/* restore original instruction (kept in target endianness) */
253
254
		if (breakpoint->length == 4)
		{
255
256
257
258
259
			u32 current_instr;
			/* check that user program as not modified breakpoint instruction */
			target->type->read_memory(target, breakpoint->address, 4, 1, (u8*)&current_instr);
			if (current_instr==arm7_9->arm_bkpt)
				target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
260
261
262
		}
		else
		{
263
264
265
266
267
			u16 current_instr;
			/* check that user program as not modified breakpoint instruction */
			target->type->read_memory(target, breakpoint->address, 2, 1, (u8*)&current_instr);
			if (current_instr==arm7_9->thumb_bkpt)
				target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
268
269
270
271
272
273
274
		}
		breakpoint->set = 0;
	}

	return ERROR_OK;
}

275
int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
276
277
278
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
279

280
281
	if (target->state != TARGET_HALTED)
	{
282
		LOG_WARNING("target not halted");
283
284
		return ERROR_TARGET_NOT_HALTED;
	}
285

286
287
	if (arm7_9->force_hw_bkpts)
	{
288
		LOG_DEBUG("forcing use of hardware breakpoint at address 0x%8.8x", breakpoint->address);
289
		breakpoint->type = BKPT_HARD;
290
	}
291

292
	if ((breakpoint->type == BKPT_SOFT) && (arm7_9->sw_bkpts_enabled == 0))
293
	{
294
		LOG_INFO("sw breakpoint requested, but software breakpoints not enabled");
295
296
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
297

298
	if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
299
	{
300
		LOG_INFO("no watchpoint unit available for hardware breakpoint");
301
302
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
303

304
	if ((breakpoint->length != 2) && (breakpoint->length != 4))
305
	{
306
		LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
307
308
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
309

310
	if (breakpoint->type == BKPT_HARD)
311
		arm7_9->wp_available--;
312

313
314
315
316
317
318
319
	return ERROR_OK;
}

int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
320

321
322
	if (target->state != TARGET_HALTED)
	{
323
		LOG_WARNING("target not halted");
324
325
		return ERROR_TARGET_NOT_HALTED;
	}
326

327
328
329
330
	if (breakpoint->set)
	{
		arm7_9_unset_breakpoint(target, breakpoint);
	}
331

332
333
	if (breakpoint->type == BKPT_HARD)
		arm7_9->wp_available++;
334

335
336
337
338
339
340
341
342
343
	return ERROR_OK;
}

int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	int rw_mask = 1;
	u32 mask;
344

345
	mask = watchpoint->length - 1;
346

347
348
	if (target->state != TARGET_HALTED)
	{
349
		LOG_WARNING("target not halted");
350
351
		return ERROR_TARGET_NOT_HALTED;
	}
352

353
354
355
356
	if (watchpoint->rw == WPT_ACCESS)
		rw_mask = 0;
	else
		rw_mask = 1;
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
	if (!arm7_9->wp0_used)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], watchpoint->address);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], watchpoint->mask);
		if( watchpoint->mask != 0xffffffffu )
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], watchpoint->value);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));

		jtag_execute_queue();
		watchpoint->set = 1;
		arm7_9->wp0_used = 2;
	}
	else if (!arm7_9->wp1_used)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_VALUE], watchpoint->address);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], watchpoint->mask);
		if( watchpoint->mask != 0xffffffffu )
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], watchpoint->value);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));

		jtag_execute_queue();
		watchpoint->set = 2;
		arm7_9->wp1_used = 2;
385
	}
386
387
	else
	{
388
		LOG_ERROR("BUG: no hardware comparator available");
389
390
		return ERROR_OK;
	}
391

392
393
394
395
396
397
398
	return ERROR_OK;
}

int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
399

400
401
	if (target->state != TARGET_HALTED)
	{
402
		LOG_WARNING("target not halted");
403
404
		return ERROR_TARGET_NOT_HALTED;
	}
405

406
407
	if (!watchpoint->set)
	{
408
		LOG_WARNING("breakpoint not set");
409
410
		return ERROR_OK;
	}
411

412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
	if (watchpoint->set == 1)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
		jtag_execute_queue();
		arm7_9->wp0_used = 0;
	}
	else if (watchpoint->set == 2)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
		jtag_execute_queue();
		arm7_9->wp1_used = 0;
	}
	watchpoint->set = 0;

	return ERROR_OK;
}

429
int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
430
431
432
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
433

434
435
	if (target->state != TARGET_HALTED)
	{
436
		LOG_WARNING("target not halted");
437
438
		return ERROR_TARGET_NOT_HALTED;
	}
439

440
441
442
443
	if (arm7_9->wp_available < 1)
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
444

445
	if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
446
447
448
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
449

450
	arm7_9->wp_available--;
451

452
453
454
455
456
457
458
	return ERROR_OK;
}

int arm7_9_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
459

460
461
	if (target->state != TARGET_HALTED)
	{
462
		LOG_WARNING("target not halted");
463
464
		return ERROR_TARGET_NOT_HALTED;
	}
465

466
467
468
469
	if (watchpoint->set)
	{
		arm7_9_unset_watchpoint(target, watchpoint);
	}
470

471
	arm7_9->wp_available++;
472

473
474
475
476
477
478
479
480
	return ERROR_OK;
}

int arm7_9_enable_sw_bkpts(struct target_s *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	int retval;
481

482
483
	if (arm7_9->sw_bkpts_enabled)
		return ERROR_OK;
484

485
	if (arm7_9->wp_available < 1)
486
	{
487
		LOG_WARNING("can't enable sw breakpoints with no watchpoint unit available");
488
489
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
490
	arm7_9->wp_available--;
491

492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
	if (!arm7_9->wp0_used)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], arm7_9->arm_bkpt);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0x0);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffffu);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
		arm7_9->sw_bkpts_enabled = 1;
		arm7_9->wp0_used = 3;
	}
	else if (!arm7_9->wp1_used)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_VALUE], arm7_9->arm_bkpt);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_DATA_MASK], 0x0);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_ADDR_MASK], 0xffffffffu);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
		arm7_9->sw_bkpts_enabled = 2;
		arm7_9->wp1_used = 3;
	}
	else
	{
514
		LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
515
		return ERROR_FAIL;
516
	}
517

518
519
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
520
		LOG_ERROR("error writing EmbeddedICE registers to enable sw breakpoints");
521
		return ERROR_FAIL;
522
	};
523

524
525
526
527
528
529
530
	return ERROR_OK;
}

int arm7_9_disable_sw_bkpts(struct target_s *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
531

532
533
	if (!arm7_9->sw_bkpts_enabled)
		return ERROR_OK;
534

535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
	if (arm7_9->sw_bkpts_enabled == 1)
	{
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
		arm7_9->sw_bkpts_enabled = 0;
		arm7_9->wp0_used = 0;
		arm7_9->wp_available++;
	}
	else if (arm7_9->sw_bkpts_enabled == 2)
	{
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
		arm7_9->sw_bkpts_enabled = 0;
		arm7_9->wp1_used = 0;
		arm7_9->wp_available++;
	}

	return ERROR_OK;
}

int arm7_9_execute_sys_speed(struct target_s *target)
{
	int timeout;
	int retval;
557

558
559
560
561
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
562

563
564
	/* set RESTART instruction */
	jtag_add_end_state(TAP_RTI);
oharboe's avatar
oharboe committed
565
566
567
568
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
569
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
570

571
572
573
574
575
576
577
578
579
	for (timeout=0; timeout<50; timeout++)
	{
		/* read debug status register */
		embeddedice_read_reg(dbg_stat);
		if ((retval = jtag_execute_queue()) != ERROR_OK)
			return retval;
		if ((buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
				   && (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_SYSCOMP, 1)))
			break;
580
		usleep(100000);
581
582
583
	}
	if (timeout == 50)
	{
584
		LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %x", buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
585
586
		return ERROR_TARGET_TIMEOUT;
	}
587

588
589
590
591
592
	return ERROR_OK;
}

int arm7_9_execute_fast_sys_speed(struct target_s *target)
{
mifi's avatar
mifi committed
593
594
	static int set=0;
	static u8 check_value[4], check_mask[4];
595

596
597
598
599
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
600

601
602
	/* set RESTART instruction */
	jtag_add_end_state(TAP_RTI);
oharboe's avatar
oharboe committed
603
604
605
606
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
607
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
608

mifi's avatar
mifi committed
609
610
611
	if (!set)
	{
		/* check for DBGACK and SYSCOMP set (others don't care) */
612

mifi's avatar
mifi committed
613
614
615
616
617
618
619
620
		/* NB! These are constants that must be available until after next jtag_execute() and
		   we evaluate the values upon first execution in lieu of setting up these constants
		   during early setup.
		*/
		buf_set_u32(check_value, 0, 32, 0x9);
		buf_set_u32(check_mask, 0, 32, 0x9);
		set=1;
	}
621

622
623
624
625
626
627
	/* read debug status register */
	embeddedice_read_reg_w_check(dbg_stat, check_value, check_value);

	return ERROR_OK;
}

628
629
630
631
632
633
634
int arm7_9_target_request_data(target_t *target, u32 size, u8 *buffer)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
	u32 *data;
	int i;
635

636
	data = malloc(size * (sizeof(u32)));
637

638
	embeddedice_receive(jtag_info, data, size);
639

640
641
642
643
	for (i = 0; i < size; i++)
	{
		h_u32_to_le(buffer + (i * 4), data[i]);
	}
644

645
	free(data);
646

647
648
649
650
651
652
	return ERROR_OK;
}

int arm7_9_handle_target_request(void *priv)
{
	target_t *target = priv;
653
654
	if (!target->type->examined)
		return ERROR_OK;
655
656
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
657
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
658
	reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
659
660


661
662
	if (!target->dbg_msg_enabled)
		return ERROR_OK;
663

664
665
666
667
668
	if (target->state == TARGET_RUNNING)
	{
		/* read DCC control register */
		embeddedice_read_reg(dcc_control);
		jtag_execute_queue();
669

670
671
672
673
		/* check W bit */
		if (buf_get_u32(dcc_control->value, 1, 1) == 1)
		{
			u32 request;
674

675
676
677
678
			embeddedice_receive(jtag_info, &request, 1);
			target_request(target, request);
		}
	}
679

680
681
682
	return ERROR_OK;
}

683
int arm7_9_poll(target_t *target)
684
685
686
687
688
689
690
691
692
693
{
	int retval;
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];

	/* read debug status register */
	embeddedice_read_reg(dbg_stat);
	if ((retval = jtag_execute_queue()) != ERROR_OK)
	{
694
		return retval;
695
	}
696

697
698
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
	{
699
/*		LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/
700
		if (target->state == TARGET_UNKNOWN)
701
		{
702
			target->state = TARGET_RUNNING;
703
			LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
704
705
706
		}
		if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
		{
707
708
709
			int check_pc=0;
			if (target->state == TARGET_RESET)
			{
oharboe's avatar
   
oharboe committed
710
				if (target->reset_halt)
711
712
713
714
715
716
717
				{
					if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)
					{
						check_pc = 1;
					}
				}
			}
718

719
			target->state = TARGET_HALTED;
720

721
722
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
723

724
725
726
727
728
729
			if (check_pc)
			{
				reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
				u32 t=*((u32 *)reg->value);
				if (t!=0)
				{
730
					LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?");
731
732
				}
			}
733

734
735
736
737
738
739
740
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
		}
		if (target->state == TARGET_DEBUG_RUNNING)
		{
			target->state = TARGET_HALTED;
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
741

742
743
			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
		}
744
745
		if (target->state != TARGET_HALTED)
		{
746
			LOG_WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
747
		}
748
	}
749
750
751
752
753
	else
	{
		if (target->state != TARGET_DEBUG_RUNNING)
			target->state = TARGET_RUNNING;
	}
754

755
	return ERROR_OK;
756
757
}

758
759
760
/*
  Some -S targets (ARM966E-S in the STR912 isn't affected, ARM926EJ-S
  in the LPC3180 and AT91SAM9260 is affected) completely stop the JTAG clock
oharboe's avatar
   
oharboe committed
761
  while the core is held in reset(SRST). It isn't possible to program the halt
762
763
764
765
  condition once reset was asserted, hence a hook that allows the target to set
  up its reset-halt condition prior to asserting reset.
*/

766
767
int arm7_9_assert_reset(target_t *target)
{
768
769
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
770
	LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
771

772
773
774
775
776
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
		return ERROR_FAIL;
	}
oharboe's avatar
   
oharboe committed
777

oharboe's avatar
   
oharboe committed
778
	if (target->reset_halt)
779
	{
oharboe's avatar
   
oharboe committed
780
781
782
		/*
		 * Some targets do not support communication while SRST is asserted. We need to
		 * set up the reset vector catch here.
783
		 *
oharboe's avatar
   
oharboe committed
784
		 * If TRST is asserted, then these settings will be reset anyway, so setting them
785
		 * here is harmless.
oharboe's avatar
   
oharboe committed
786
787
788
789
790
791
792
793
794
		 */
		if (arm7_9->has_vector_catch)
		{
			/* program vector catch register to catch reset vector */
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1);
		}
		else
		{
			/* program watchpoint unit to match on reset vector address */
795
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0);
oharboe's avatar
   
oharboe committed
796
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
797
798
799
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE);
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff);
oharboe's avatar
   
oharboe committed
800
		}
801
802
	}

oharboe's avatar
   
oharboe committed
803
	/* here we should issue a srst only, but we may have to assert trst as well */
804
	if (jtag_reset_config & RESET_SRST_PULLS_TRST)
805
	{
806
807
808
809
		jtag_add_reset(1, 1);
	} else
	{
		jtag_add_reset(0, 1);
810
	}
811

oharboe's avatar
   
oharboe committed
812

813
814
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
oharboe's avatar
   
oharboe committed
815

816
817
	armv4_5_invalidate_core_regs(target);

818
819
820
821
822
823
    if ((target->reset_halt)&&((jtag_reset_config & RESET_SRST_PULLS_TRST)==0))
	{
		/* debug entry was already prepared in arm7_9_assert_reset() */
		target->debug_reason = DBG_REASON_DBGRQ;
	}
	
824
825
826
827
828
829
	return ERROR_OK;

}

int arm7_9_deassert_reset(target_t *target)
{
830
	int retval=ERROR_OK;
831
	LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
832

833
834
	/* deassert reset lines */
	jtag_add_reset(0, 0);
835

836
837
838
839
840
841
842
	if ((jtag_reset_config & RESET_SRST_PULLS_TRST)!=0)
	{
		/* set up embedded ice registers again */
		if ((retval=target->type->examine(target))!=ERROR_OK)
			return retval;
	}
	return retval;
843
844
}

845
846
847
848
849
int arm7_9_clear_halt(target_t *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
850

851
852
	/* we used DBGRQ only if we didn't come out of reset */
	if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq)
853
854
855
	{
		/* program EmbeddedICE Debug Control Register to deassert DBGRQ
		 */
856
		buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
857
858
859
860
		embeddedice_store_reg(dbg_ctrl);
	}
	else
	{
861
		if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch)
862
		{
863
864
865
866
867
868
869
870
871
872
873
874
			/* if we came out of reset, and vector catch is supported, we used
			 * vector catch to enter debug state
			 * restore the register in that case
			 */
			embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH]);
		}
		else
		{
			/* restore registers if watchpoint unit 0 was in use
			 */
			if (arm7_9->wp0_used)
			{
875
876
877
878
				if (arm7_9->debug_entry_from_reset)
				{
					embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
				}
879
880
881
882
				embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK]);
				embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK]);
				embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK]);
			}
883
			/* control value always has to be restored, as it was either disabled,
884
885
886
			 * or enabled with possibly different bits
			 */
			embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
887
888
		}
	}
889

890
891
892
	return ERROR_OK;
}

893
894
895
896
897
int arm7_9_soft_reset_halt(struct target_s *target)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
898
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
899
	int i;
oharboe's avatar
   
oharboe committed
900
	int retval;
901

902
	if ((retval=target_halt(target))!=ERROR_OK)
oharboe's avatar
   
oharboe committed
903
		return retval;
904

oharboe's avatar
   
oharboe committed
905
	for (i=0; i<10; i++)
906
	{
oharboe's avatar
   
oharboe committed
907
908
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) != 0)
			break;
909
		embeddedice_read_reg(dbg_stat);
oharboe's avatar
   
oharboe committed
910
911
912
913
		if ((retval=jtag_execute_queue())!=ERROR_OK)
			return retval;
		/* do not eat all CPU, time out after 1 se*/
		usleep(100*1000);
914

oharboe's avatar
   
oharboe committed
915
916
917
	}
	if (i==10)
	{
918
		LOG_ERROR("Failed to halt CPU after 1 sec");
oharboe's avatar
   
oharboe committed
919
		return ERROR_TARGET_TIMEOUT;
920
921
	}
	target->state = TARGET_HALTED;
922

923
924
925
926
927
928
929
	/* program EmbeddedICE Debug Control Register to assert DBGACK and INTDIS
	 * ensure that DBGRQ is cleared
	 */
	buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGACK, 1, 1);
	buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
	buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_INTDIS, 1, 1);
	embeddedice_store_reg(dbg_ctrl);
930

931
	arm7_9_clear_halt(target);
932

933
934
935
936
	/* if the target is in Thumb state, change to ARM state */
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_ITBIT, 1))
	{
		u32 r0_thumb, pc_thumb;
937
		LOG_DEBUG("target entered debug from Thumb state, changing to ARM");
938
939
940
941
		/* Entered debug from Thumb mode */
		armv4_5->core_state = ARMV4_5_STATE_THUMB;
		arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
	}
942

943
944
	/* all register content is now invalid */
	armv4_5_invalidate_core_regs(target);
945

946
947
948
949
	/* SVC, ARM state, IRQ and FIQ disabled */
	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
950

951
952
953
954
	/* start fetching from 0x0 */
	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
	armv4_5->core_cache->reg_list[15].dirty = 1;
	armv4_5->core_cache->reg_list[15].valid = 1;
955

956
957
	armv4_5->core_mode = ARMV4_5_MODE_SVC;
	armv4_5->core_state = ARMV4_5_STATE_ARM;
958
959
960

	if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
		return ERROR_FAIL;
961

962
963
	/* reset registers */
	for (i = 0; i <= 14; i++)
964
	{
965
966
967
968
		buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, 0xffffffff);
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 1;
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
	}
969

970
	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
971

972
973
974
975
976
	return ERROR_OK;
}

int arm7_9_halt(target_t *target)
{
977
	if (target->state==TARGET_RESET)
978
	{
979
		LOG_ERROR("BUG: arm7/9 does not support halt during reset. This is handled in arm7_9_assert_reset()");
980
981
982
		return ERROR_OK;
	}

983
984
985
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
986

987
	LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
988

989
990
	if (target->state == TARGET_HALTED)
	{
991
		LOG_DEBUG("target was already halted");
oharboe's avatar
   
oharboe committed
992
		return ERROR_OK;
993
	}
994

995
996
	if (target->state == TARGET_UNKNOWN)
	{
997
		LOG_WARNING("target was in unknown state when halt was requested");
998
	}
999

1000
	if (arm7_9->use_dbgrq)
For faster browsing, not all history is shown. View entire blame