arm7_9_common.c 81.9 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
 *   Copyright (C) 2007,2008 yvind Harboe                                 *
6
7
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
 *   Copyright (C) 2008 by Spencer Oliver                                  *
 *   spen@spen-soft.co.uk                                                  *
 *                                                                         *
11
12
13
 *   Copyright (C) 2008 by Hongtao Zheng                                   *
 *   hontor@126.com                                                        *
 *                                                                         *
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 *   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.             *
 ***************************************************************************/
29
#ifdef HAVE_CONFIG_H
30
#include "config.h"
31
32
33
#endif

#include "replacements.h"
34
35
36

#include "embeddedice.h"
#include "target.h"
37
#include "target_request.h"
38
39
40
41
42
43
#include "armv4_5.h"
#include "arm_jtag.h"
#include "jtag.h"
#include "log.h"
#include "arm7_9_common.h"
#include "breakpoints.h"
oharboe's avatar
oharboe committed
44
#include "time_support.h"
45
#include "arm_simulator.h"
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#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_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
65
int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
66
int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
67
int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
68

69
70
71
72
73
static int arm7_9_clear_watchpoints(arm7_9_common_t *arm7_9)
{
	embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
	embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
	arm7_9->sw_breakpoints_added = 0;
74
	arm7_9->wp0_used = 0;
75
76
	arm7_9->wp1_used = arm7_9->wp1_used_default;
	arm7_9->wp_available = arm7_9->wp_available_max;
77

78
79
80
81
82
83
84
	return jtag_execute_queue();
}

/* set up embedded ice registers */
static int arm7_9_set_software_breakpoints(arm7_9_common_t *arm7_9)
{
	if (arm7_9->sw_breakpoints_added)
85
	{
86
87
88
89
90
91
92
93
		return ERROR_OK;
	}
	if (arm7_9->wp_available < 1)
	{
		LOG_WARNING("can't enable sw breakpoints with no watchpoint unit available");
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
	arm7_9->wp_available--;
oharboe's avatar
oharboe committed
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
	/* pick a breakpoint unit */
	if (!arm7_9->wp0_used)
	{
		arm7_9->sw_breakpoints_added=1;
		arm7_9->wp0_used = 3;
	} else if (!arm7_9->wp1_used)
	{
		arm7_9->sw_breakpoints_added=2;
		arm7_9->wp1_used = 3;
	}
	else
	{
		LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
		return ERROR_FAIL;
109
	}
110

111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
	if (arm7_9->sw_breakpoints_added==1)
	{
		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);
	}
	else if (arm7_9->sw_breakpoints_added==2)
	{
		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);
	}
	else
128
	{
129
130
		LOG_ERROR("BUG: both watchpoints used, but wp_available >= 1");
		return ERROR_FAIL;
131
	}
132

133
	return jtag_execute_queue();
134
135
}

136
137
/* set things up after a reset / on startup */
int arm7_9_setup(target_t *target)
138
{
139
140
141
142
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;

	return arm7_9_clear_watchpoints(arm7_9);
143
144
145
146
147
148
}

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;
149

150
151
152
153
	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
	{
		return -1;
	}
154

155
156
157
158
	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
	{
		return -1;
	}
159

160
161
	*armv4_5_p = armv4_5;
	*arm7_9_p = arm7_9;
162

163
164
165
	return ERROR_OK;
}

166
167
168
/* we set up the breakpoint even if it is already set. Some action, e.g. reset
 * might have erased the values in embedded ice
 */
169
170
171
172
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;
173
	int retval=ERROR_OK;
174

175
176
	if (target->state != TARGET_HALTED)
	{
177
		LOG_WARNING("target not halted");
178
179
		return ERROR_TARGET_NOT_HALTED;
	}
180

181
182
183
184
	if (breakpoint->type == BKPT_HARD)
	{
		/* either an ARM (4 byte) or Thumb (2 byte) breakpoint */
		u32 mask = (breakpoint->length == 4) ? 0x3u : 0x1u;
185
		if (breakpoint->set==1)
186
187
188
189
190
191
192
		{
			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);
		}
193
		else if (breakpoint->set==2)
194
195
196
197
198
199
200
201
202
		{
			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);
		}
		else
		{
203
			LOG_ERROR("BUG: no hardware comparator available");
204
205
			return ERROR_OK;
		}
206
207

		retval=jtag_execute_queue();
208
209
210
	}
	else if (breakpoint->type == BKPT_SOFT)
	{
211
212
		if ((retval=arm7_9_set_software_breakpoints(arm7_9))!=ERROR_OK)
			return retval;
oharboe's avatar
oharboe committed
213

214
215
216
		/* did we already set this breakpoint? */
		if (breakpoint->set)
			return ERROR_OK;
oharboe's avatar
oharboe committed
217

218
219
		if (breakpoint->length == 4)
		{
ntfreak's avatar
ntfreak committed
220
			u32 verify = 0xffffffff;
221
			/* keep the original instruction in target endianness */
222
223
224
225
			if ((retval = target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
			{
				return retval;
			}
drath's avatar
drath committed
226
			/* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
227
228
229
230
			if ((retval = target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt)) != ERROR_OK)
			{
				return retval;
			}
231

232
			if ((retval = target_read_u32(target, breakpoint->address, &verify)) != ERROR_OK)
233
234
235
			{
				return retval;
			}
ntfreak's avatar
ntfreak committed
236
237
			if (verify != arm7_9->arm_bkpt)
			{
238
				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
239
240
				return ERROR_OK;
			}
241
242
243
		}
		else
		{
ntfreak's avatar
ntfreak committed
244
			u16 verify = 0xffff;
245
			/* keep the original instruction in target endianness */
246
247
248
249
			if ((retval = target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
			{
				return retval;
			}
drath's avatar
drath committed
250
			/* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
251
252
253
254
			if ((retval = target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt)) != ERROR_OK)
			{
				return retval;
			}
255

256
			if ((retval = target_read_u16(target, breakpoint->address, &verify)) != ERROR_OK)
257
258
259
			{
				return retval;
			}
ntfreak's avatar
ntfreak committed
260
261
			if (verify != arm7_9->thumb_bkpt)
			{
262
				LOG_ERROR("Unable to set thumb software breakpoint at address %08x - check that memory is read/writable", breakpoint->address);
ntfreak's avatar
ntfreak committed
263
264
				return ERROR_OK;
			}
265
266
267
268
		}
		breakpoint->set = 1;
	}

269
	return retval;
270
271
272
273
}

int arm7_9_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
274
275
	int retval = ERROR_OK;

276
277
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
278

279
280
	if (!breakpoint->set)
	{
281
		LOG_WARNING("breakpoint not set");
282
283
		return ERROR_OK;
	}
284

285
286
287
288
289
290
291
292
293
294
295
296
	if (breakpoint->type == BKPT_HARD)
	{
		if (breakpoint->set == 1)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
			arm7_9->wp0_used = 0;
		}
		else if (breakpoint->set == 2)
		{
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
			arm7_9->wp1_used = 0;
		}
297
		retval = jtag_execute_queue();
298
299
300
301
		breakpoint->set = 0;
	}
	else
	{
302
		/* restore original instruction (kept in target endianness) */
303
304
		if (breakpoint->length == 4)
		{
305
306
			u32 current_instr;
			/* check that user program as not modified breakpoint instruction */
307
308
309
310
			if ((retval = target->type->read_memory(target, breakpoint->address, 4, 1, (u8*)&current_instr)) != ERROR_OK)
			{
				return retval;
			}
311
			if (current_instr==arm7_9->arm_bkpt)
312
313
314
315
				if ((retval = target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
				{
					return retval;
				}
316
317
318
		}
		else
		{
319
320
			u16 current_instr;
			/* check that user program as not modified breakpoint instruction */
321
322
323
324
			if ((retval = target->type->read_memory(target, breakpoint->address, 2, 1, (u8*)&current_instr)) != ERROR_OK)
			{
				return retval;
			}
325
			if (current_instr==arm7_9->thumb_bkpt)
326
327
328
329
				if ((retval = target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
				{
					return retval;
				}
330
331
332
333
		}
		breakpoint->set = 0;
	}

334
	return retval;
335
336
}

337
int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
338
339
340
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
341

342
343
	if (target->state != TARGET_HALTED)
	{
344
		LOG_WARNING("target not halted");
345
346
		return ERROR_TARGET_NOT_HALTED;
	}
oharboe's avatar
oharboe committed
347

348
	if (arm7_9->breakpoint_count==0)
349
	{
oharboe's avatar
oharboe committed
350
351
		/* make sure we don't have any dangling breakpoints. This is vital upon
		 * GDB connect/disconnect
352
		 */
oharboe's avatar
oharboe committed
353
		arm7_9_clear_watchpoints(arm7_9);
354
	}
355

356
	if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
357
	{
358
		LOG_INFO("no watchpoint unit available for hardware breakpoint");
359
360
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
361

362
	if ((breakpoint->length != 2) && (breakpoint->length != 4))
363
	{
364
		LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
365
366
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
367

368
	if (breakpoint->type == BKPT_HARD)
369
	{
370
		arm7_9->wp_available--;
oharboe's avatar
oharboe committed
371

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
		if (!arm7_9->wp0_used)
		{
			arm7_9->wp0_used = 1;
			breakpoint->set = 1;
		}
		else if (!arm7_9->wp1_used)
		{
			arm7_9->wp1_used = 1;
			breakpoint->set = 2;
		}
		else
		{
			LOG_ERROR("BUG: no hardware comparator available");
		}
	}
oharboe's avatar
oharboe committed
387

388
	arm7_9->breakpoint_count++;
oharboe's avatar
oharboe committed
389

390
	return arm7_9_set_breakpoint(target, breakpoint);
391
392
393
394
}

int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
395
	int retval = ERROR_OK;
396
397
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
398

399
400
401
402
	if((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK)
	{
		return retval;
	}
403

404
405
	if (breakpoint->type == BKPT_HARD)
		arm7_9->wp_available++;
oharboe's avatar
oharboe committed
406

407
408
409
410
	arm7_9->breakpoint_count--;
	if (arm7_9->breakpoint_count==0)
	{
		/* make sure we don't have any dangling breakpoints */
411
412
413
414
		if((retval = arm7_9_clear_watchpoints(arm7_9)) != ERROR_OK)
		{
			return retval;
		}
415
	}
416

417
418
419
420
421
	return ERROR_OK;
}

int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
422
	int retval = ERROR_OK;
423
424
425
426
	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;
427

428
	mask = watchpoint->length - 1;
429

430
431
	if (target->state != TARGET_HALTED)
	{
432
		LOG_WARNING("target not halted");
433
434
		return ERROR_TARGET_NOT_HALTED;
	}
435

436
437
438
439
	if (watchpoint->rw == WPT_ACCESS)
		rw_mask = 0;
	else
		rw_mask = 1;
440

441
442
443
444
445
446
447
448
449
450
	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));

451
452
453
454
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
455
456
457
458
459
460
461
462
463
464
465
466
467
		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));

468
469
470
471
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
472
473
		watchpoint->set = 2;
		arm7_9->wp1_used = 2;
474
	}
475
476
	else
	{
477
		LOG_ERROR("BUG: no hardware comparator available");
478
479
		return ERROR_OK;
	}
480

481
482
483
484
485
	return ERROR_OK;
}

int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
486
	int retval = ERROR_OK;
487
488
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
489

490
491
	if (target->state != TARGET_HALTED)
	{
492
		LOG_WARNING("target not halted");
493
494
		return ERROR_TARGET_NOT_HALTED;
	}
495

496
497
	if (!watchpoint->set)
	{
498
		LOG_WARNING("breakpoint not set");
499
500
		return ERROR_OK;
	}
501

502
503
504
	if (watchpoint->set == 1)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
505
506
507
508
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
509
510
511
512
513
		arm7_9->wp0_used = 0;
	}
	else if (watchpoint->set == 2)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
514
515
516
517
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
518
519
520
521
522
523
524
		arm7_9->wp1_used = 0;
	}
	watchpoint->set = 0;

	return ERROR_OK;
}

525
int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
526
527
528
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
529

530
531
	if (target->state != TARGET_HALTED)
	{
532
		LOG_WARNING("target not halted");
533
534
		return ERROR_TARGET_NOT_HALTED;
	}
535

536
537
538
539
	if (arm7_9->wp_available < 1)
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
540

541
	if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
542
543
544
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
545

546
	arm7_9->wp_available--;
547

548
549
550
551
552
	return ERROR_OK;
}

int arm7_9_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
553
	int retval = ERROR_OK;
554
555
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
556

557
558
	if (watchpoint->set)
	{
559
560
561
562
		if((retval = arm7_9_unset_watchpoint(target, watchpoint)) != ERROR_OK)
		{
			return retval;
		}
563
	}
564

565
	arm7_9->wp_available++;
566

567
568
569
570
571
572
	return ERROR_OK;
}

int arm7_9_execute_sys_speed(struct target_s *target)
{
	int retval;
573

574
575
576
577
	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];
578

579
	/* set RESTART instruction */
580
	jtag_add_end_state(TAP_IDLE);
oharboe's avatar
oharboe committed
581
582
583
584
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
585
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
586

oharboe's avatar
oharboe committed
587
588
589
	long long then=timeval_ms();
	int timeout;
	while (!(timeout=((timeval_ms()-then)>1000)))
590
591
592
593
594
595
596
597
	{
		/* 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;
oharboe's avatar
oharboe committed
598
599
600
601
602
603
604
		if (debug_level>=3)
		{
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
605
	}
oharboe's avatar
oharboe committed
606
	if (timeout)
607
	{
608
		LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %x", buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
609
610
		return ERROR_TARGET_TIMEOUT;
	}
611

612
613
614
615
616
	return ERROR_OK;
}

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

620
621
622
623
	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];
624

625
	/* set RESTART instruction */
626
	jtag_add_end_state(TAP_IDLE);
oharboe's avatar
oharboe committed
627
628
629
630
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
631
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
632

mifi's avatar
mifi committed
633
634
635
	if (!set)
	{
		/* check for DBGACK and SYSCOMP set (others don't care) */
636

mifi's avatar
mifi committed
637
		/* NB! These are constants that must be available until after next jtag_execute() and
638
639
640
		 * we evaluate the values upon first execution in lieu of setting up these constants
		 * during early setup.
		 * */
mifi's avatar
mifi committed
641
642
643
644
		buf_set_u32(check_value, 0, 32, 0x9);
		buf_set_u32(check_mask, 0, 32, 0x9);
		set=1;
	}
645

646
647
648
649
650
651
	/* read debug status register */
	embeddedice_read_reg_w_check(dbg_stat, check_value, check_value);

	return ERROR_OK;
}

652
653
654
655
656
657
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;
658
	int i, retval = ERROR_OK;
659

660
	data = malloc(size * (sizeof(u32)));
661

662
	retval = embeddedice_receive(jtag_info, data, size);
663

664
665
666
667
	for (i = 0; i < size; i++)
	{
		h_u32_to_le(buffer + (i * 4), data[i]);
	}
668

669
	free(data);
670

671
	return retval;
672
673
674
675
}

int arm7_9_handle_target_request(void *priv)
{
676
	int retval = ERROR_OK;
677
	target_t *target = priv;
678
679
	if (!target->type->examined)
		return ERROR_OK;
680
681
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
682
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
683
	reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
684

685
686
	if (!target->dbg_msg_enabled)
		return ERROR_OK;
687

688
689
690
691
	if (target->state == TARGET_RUNNING)
	{
		/* read DCC control register */
		embeddedice_read_reg(dcc_control);
692
693
694
695
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
696

697
698
699
700
		/* check W bit */
		if (buf_get_u32(dcc_control->value, 1, 1) == 1)
		{
			u32 request;
701

702
703
704
705
706
707
708
709
			if ((retval = embeddedice_receive(jtag_info, &request, 1)) != ERROR_OK)
			{
				return retval;
			}
			if ((retval = target_request(target, request)) != ERROR_OK)
			{
				return retval;
			}
710
711
		}
	}
712

713
714
715
	return ERROR_OK;
}

716
int arm7_9_poll(target_t *target)
717
718
719
720
721
722
723
724
725
726
{
	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)
	{
727
		return retval;
728
	}
729

730
731
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
	{
732
/*		LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/
733
		if (target->state == TARGET_UNKNOWN)
734
		{
735
			target->state = TARGET_RUNNING;
736
			LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
737
738
739
		}
		if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
		{
740
741
742
			int check_pc=0;
			if (target->state == TARGET_RESET)
			{
oharboe's avatar
   
oharboe committed
743
				if (target->reset_halt)
744
745
746
747
748
749
750
				{
					if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)
					{
						check_pc = 1;
					}
				}
			}
751

752
			target->state = TARGET_HALTED;
753

754
755
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
756

757
758
759
760
761
762
			if (check_pc)
			{
				reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
				u32 t=*((u32 *)reg->value);
				if (t!=0)
				{
763
					LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?");
764
765
				}
			}
766

767
768
769
770
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
			{
				return retval;
			}
771
772
773
774
775
776
		}
		if (target->state == TARGET_DEBUG_RUNNING)
		{
			target->state = TARGET_HALTED;
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
777

778
779
780
781
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED)) != ERROR_OK)
			{
				return retval;
			}
782
		}
783
784
		if (target->state != TARGET_HALTED)
		{
785
			LOG_WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
786
		}
787
	}
788
789
790
791
792
	else
	{
		if (target->state != TARGET_DEBUG_RUNNING)
			target->state = TARGET_RUNNING;
	}
793

794
	return ERROR_OK;
795
796
}

797
798
799
/*
  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
800
  while the core is held in reset(SRST). It isn't possible to program the halt
801
802
803
804
  condition once reset was asserted, hence a hook that allows the target to set
  up its reset-halt condition prior to asserting reset.
*/

805
806
int arm7_9_assert_reset(target_t *target)
{
807
808
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
oharboe's avatar
oharboe committed
809
	LOG_DEBUG("target->state: %s",
810
		  Jim_Nvp_value2name_simple( nvp_target_state,target->state)->name);
811

812
813
814
815
816
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
		return ERROR_FAIL;
	}
oharboe's avatar
   
oharboe committed
817

oharboe's avatar
   
oharboe committed
818
	if (target->reset_halt)
819
	{
oharboe's avatar
   
oharboe committed
820
821
822
		/*
		 * Some targets do not support communication while SRST is asserted. We need to
		 * set up the reset vector catch here.
823
		 *
oharboe's avatar
   
oharboe committed
824
		 * If TRST is asserted, then these settings will be reset anyway, so setting them
825
		 * here is harmless.
oharboe's avatar
   
oharboe committed
826
827
828
829
830
831
832
833
834
		 */
		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 */
835
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0);
oharboe's avatar
   
oharboe committed
836
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
837
838
839
			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
840
		}
841
842
	}

oharboe's avatar
   
oharboe committed
843
	/* here we should issue a srst only, but we may have to assert trst as well */
844
	if (jtag_reset_config & RESET_SRST_PULLS_TRST)
845
	{
846
847
848
849
		jtag_add_reset(1, 1);
	} else
	{
		jtag_add_reset(0, 1);
850
	}
851

852
853
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
oharboe's avatar
   
oharboe committed
854

855
856
	armv4_5_invalidate_core_regs(target);

857
	if ((target->reset_halt)&&((jtag_reset_config & RESET_SRST_PULLS_TRST)==0))
858
859
860
861
	{
		/* debug entry was already prepared in arm7_9_assert_reset() */
		target->debug_reason = DBG_REASON_DBGRQ;
	}
oharboe's avatar
oharboe committed
862

863
864
865
866
867
	return ERROR_OK;
}

int arm7_9_deassert_reset(target_t *target)
{
868
	int retval=ERROR_OK;
oharboe's avatar
oharboe committed
869
	LOG_DEBUG("target->state: %s",
870
		Jim_Nvp_value2name_simple( nvp_target_state,target->state)->name);
871

872
873
	/* deassert reset lines */
	jtag_add_reset(0, 0);
874

875
	if (target->reset_halt&&(jtag_reset_config & RESET_SRST_PULLS_TRST)!=0)
876
	{
877
		LOG_WARNING("srst pulls trst - can not reset into halted mode. Issuing halt after reset.");
878
879
880
		/* set up embedded ice registers again */
		if ((retval=target->type->examine(target))!=ERROR_OK)
			return retval;
881
882
883
884
885

		if ((retval=target_poll(target))!=ERROR_OK)
		{
			return retval;
		}
oharboe's avatar
oharboe committed
886

887
888
889
890
		if ((retval=target_halt(target))!=ERROR_OK)
		{
			return retval;
		}
oharboe's avatar
oharboe committed
891

892
893
	}
	return retval;
894
895
}

896
897
898
899
900
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];
901

902
903
	/* we used DBGRQ only if we didn't come out of reset */
	if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq)
904
905
906
	{
		/* program EmbeddedICE Debug Control Register to deassert DBGRQ
		 */
907
		buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
908
909
910
911
		embeddedice_store_reg(dbg_ctrl);
	}
	else
	{
912
		if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch)
913
		{
914
915
916
917
918
919
920
921
922
923
924
925
			/* 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)
			{
926
927
928
929
				if (arm7_9->debug_entry_from_reset)
				{
					embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
				}
930
931
932
933
				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]);
			}
934
			/* control value always has to be restored, as it was either disabled,
935
936
937
			 * or enabled with possibly different bits
			 */
			embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
938
939
		}
	}
940

941
942
943
	return ERROR_OK;
}

944
945
946
947
948
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];
949
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
950
	int i;
oharboe's avatar
   
oharboe committed
951
	int retval;
952

953
	if ((retval=target_halt(target))!=ERROR_OK)
oharboe's avatar
   
oharboe committed
954
		return retval;
955

oharboe's avatar
oharboe committed
956
957
958
	long long then=timeval_ms();
	int timeout;
	while (!(timeout=((timeval_ms()-then)>1000)))
959
	{
oharboe's avatar
   
oharboe committed
960
961
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) != 0)
			break;
962
		embeddedice_read_reg(dbg_stat);
oharboe's avatar
   
oharboe committed
963
964
		if ((retval=jtag_execute_queue())!=ERROR_OK)
			return retval;
oharboe's avatar
oharboe committed
965
966
967
968
969
970
971
		if (debug_level>=3)
		{
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
oharboe's avatar
   
oharboe committed
972
	}
oharboe's avatar
oharboe committed
973
	if (timeout)
oharboe's avatar
   
oharboe committed
974
	{
975
		LOG_ERROR("Failed to halt CPU after 1 sec");
oharboe's avatar
   
oharboe committed
976
		return ERROR_TARGET_TIMEOUT;
977
978
	}
	target->state = TARGET_HALTED;
979

980
981
982
983
984
985
986
	/* 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);
987

988
989
990
991
	if ((retval = arm7_9_clear_halt(target)) != ERROR_OK)
	{
		return retval;
	}
992

993
994
995
996
	/* 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;
997
		LOG_DEBUG("target entered debug from Thumb state, changing to ARM");
998
999
1000
		/* Entered debug from Thumb mode */
		armv4_5->core_state = ARMV4_5_STATE_THUMB;
		arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
For faster browsing, not all history is shown. View entire blame