arm7_9_common.c 80.3 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
14
15
16
17
18
19
20
21
22
23
24
25
 *   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.             *
 ***************************************************************************/
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
29
30
#endif

#include "replacements.h"
31
32
33

#include "embeddedice.h"
#include "target.h"
34
#include "target_request.h"
35
36
37
38
39
40
#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
41
#include "time_support.h"
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

#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);
61
int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
62
int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
63
int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
64

65

66
67
68
69
70
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;
71
	arm7_9->wp0_used = 0;
72
73
	arm7_9->wp1_used = arm7_9->wp1_used_default;
	arm7_9->wp_available = arm7_9->wp_available_max;
74

75
76
77
78
79
80
81
	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)
82
	{
83
84
85
86
87
88
89
90
		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
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
	/* 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;
106
	}
107

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

130
	return jtag_execute_queue();
131
132
}

133
134
/* set things up after a reset / on startup */
int arm7_9_setup(target_t *target)
135
{
136
137
138
139
	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);
140
141
}

142

143
144
145
146
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;
147

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

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

158
159
	*armv4_5_p = armv4_5;
	*arm7_9_p = arm7_9;
160

161
162
163
	return ERROR_OK;
}

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

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

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

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

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

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

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

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

267
	return retval;
268
269
270
271
272

}

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

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

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

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

333
	return retval;
334
335
}

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

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

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

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

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

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

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
		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
386

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
	return ERROR_OK;
}

570
571


572
573
574
575

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

577
578
579
580
	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];
581

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

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

615
616
617
618
619
	return ERROR_OK;
}

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

623
624
625
626
	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];
627

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

mifi's avatar
mifi committed
636
637
638
	if (!set)
	{
		/* check for DBGACK and SYSCOMP set (others don't care) */
639

mifi's avatar
mifi committed
640
641
642
643
644
645
646
647
		/* 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;
	}
648

649
650
651
652
653
654
	/* read debug status register */
	embeddedice_read_reg_w_check(dbg_stat, check_value, check_value);

	return ERROR_OK;
}

655
656
657
658
659
660
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;
661
	int i, retval = ERROR_OK;
662

663
	data = malloc(size * (sizeof(u32)));
664

665
	retval = embeddedice_receive(jtag_info, data, size);
666

667
668
669
670
	for (i = 0; i < size; i++)
	{
		h_u32_to_le(buffer + (i * 4), data[i]);
	}
671

672
	free(data);
673

674
	return retval;
675
676
677
678
}

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


689
690
	if (!target->dbg_msg_enabled)
		return ERROR_OK;
691

692
693
694
695
	if (target->state == TARGET_RUNNING)
	{
		/* read DCC control register */
		embeddedice_read_reg(dcc_control);
696
697
698
699
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
700

701
702
703
704
		/* check W bit */
		if (buf_get_u32(dcc_control->value, 1, 1) == 1)
		{
			u32 request;
705

706
707
708
709
710
711
712
713
			if ((retval = embeddedice_receive(jtag_info, &request, 1)) != ERROR_OK)
			{
				return retval;
			}
			if ((retval = target_request(target, request)) != ERROR_OK)
			{
				return retval;
			}
714
715
		}
	}
716

717
718
719
	return ERROR_OK;
}

720
int arm7_9_poll(target_t *target)
721
722
723
724
725
726
727
728
729
730
{
	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)
	{
731
		return retval;
732
	}
733

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

756
			target->state = TARGET_HALTED;
757

758
759
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
760

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

771
772
773
774
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
			{
				return retval;
			}
775
776
777
778
779
780
		}
		if (target->state == TARGET_DEBUG_RUNNING)
		{
			target->state = TARGET_HALTED;
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
781

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

798
	return ERROR_OK;
799
800
}

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

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

816
817
818
819
820
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
		return ERROR_FAIL;
	}
oharboe's avatar
   
oharboe committed
821

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

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

oharboe's avatar
   
oharboe committed
856

857
858
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
oharboe's avatar
   
oharboe committed
859

860
861
	armv4_5_invalidate_core_regs(target);

862
863
864
865
866
    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;
	}
oharboe's avatar
oharboe committed
867

868
869
870
871
872
873
	return ERROR_OK;

}

int arm7_9_deassert_reset(target_t *target)
{
874
	int retval=ERROR_OK;
oharboe's avatar
oharboe committed
875
	LOG_DEBUG("target->state: %s",
876
877
		  Jim_Nvp_value2name_simple( nvp_target_state,target->state)->name);

878

879
880
	/* deassert reset lines */
	jtag_add_reset(0, 0);
881

882
	if (target->reset_halt&&(jtag_reset_config & RESET_SRST_PULLS_TRST)!=0)
883
	{
884
		LOG_WARNING("srst pulls trst - can not reset into halted mode. Issuing halt after reset.");
885
886
887
		/* set up embedded ice registers again */
		if ((retval=target->type->examine(target))!=ERROR_OK)
			return retval;
888
889
890
891
892

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

894
895
896
897
		if ((retval=target_halt(target))!=ERROR_OK)
		{
			return retval;
		}
oharboe's avatar
oharboe committed
898

899
900
	}
	return retval;
901
902
}

903
904
905
906
907
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];
908

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

948
949
950
	return ERROR_OK;
}

951
952
953
954
955
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];
956
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
957
	int i;
oharboe's avatar
   
oharboe committed
958
	int retval;
959

960
	if ((retval=target_halt(target))!=ERROR_OK)
oharboe's avatar
   
oharboe committed
961
		return retval;
962

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

987
988
989
990
991
992
993
	/* 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);
994

995
996
997
998
	if ((retval = arm7_9_clear_halt(target)) != ERROR_OK)
	{
		return retval;
	}
999

1000
	/* if the target is in Thumb state, change to ARM state */
For faster browsing, not all history is shown. View entire blame