arm7_9_common.c 79.7 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
			target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
drath's avatar
drath committed
221
			/* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
222
223
224
225
			if ((retval = target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt)) != ERROR_OK)
			{
				return retval;
			}
226

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

ntfreak's avatar
ntfreak committed
245
246
247
			target->type->read_memory(target, breakpoint->address, 2, 1, (u8 *)&verify);
			if (verify != arm7_9->thumb_bkpt)
			{
248
				LOG_ERROR("Unable to set thumb software breakpoint at address %08x - check that memory is read/writable", breakpoint->address);
ntfreak's avatar
ntfreak committed
249
250
				return ERROR_OK;
			}
251
252
253
254
		}
		breakpoint->set = 1;
	}

255
	return retval;
256
257
258
259
260

}

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

263
264
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
265

266
267
	if (!breakpoint->set)
	{
268
		LOG_WARNING("breakpoint not set");
269
270
		return ERROR_OK;
	}
271

272
273
274
275
276
277
278
279
280
281
282
283
	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;
		}
284
		retval = jtag_execute_queue();
285
286
287
288
		breakpoint->set = 0;
	}
	else
	{
289
		/* restore original instruction (kept in target endianness) */
290
291
		if (breakpoint->length == 4)
		{
292
293
294
295
296
			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);
297
298
299
		}
		else
		{
300
301
302
303
304
			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);
305
306
307
308
		}
		breakpoint->set = 0;
	}

309
	return retval;
310
311
}

312
int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
313
314
315
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
316

317
318
	if (target->state != TARGET_HALTED)
	{
319
		LOG_WARNING("target not halted");
320
321
		return ERROR_TARGET_NOT_HALTED;
	}
oharboe's avatar
oharboe committed
322

323
	if (arm7_9->breakpoint_count==0)
324
	{
oharboe's avatar
oharboe committed
325
326
		/* make sure we don't have any dangling breakpoints. This is vital upon
		 * GDB connect/disconnect
327
		 */
oharboe's avatar
oharboe committed
328
		arm7_9_clear_watchpoints(arm7_9);
329
	}
330

331
	if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
332
	{
333
		LOG_INFO("no watchpoint unit available for hardware breakpoint");
334
335
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
336

337
	if ((breakpoint->length != 2) && (breakpoint->length != 4))
338
	{
339
		LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
340
341
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
342

343
	if (breakpoint->type == BKPT_HARD)
344
	{
345
		arm7_9->wp_available--;
oharboe's avatar
oharboe committed
346

347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
		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
362

363

364
	arm7_9->breakpoint_count++;
oharboe's avatar
oharboe committed
365

366
	return arm7_9_set_breakpoint(target, breakpoint);
367
368
369
370
}

int arm7_9_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
{
371
	int retval = ERROR_OK;
372
373
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
374

375
376
377
378
	if((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK)
	{
		return retval;
	}
379

380
381
	if (breakpoint->type == BKPT_HARD)
		arm7_9->wp_available++;
oharboe's avatar
oharboe committed
382

383
384
385
386
	arm7_9->breakpoint_count--;
	if (arm7_9->breakpoint_count==0)
	{
		/* make sure we don't have any dangling breakpoints */
387
388
389
390
		if((retval = arm7_9_clear_watchpoints(arm7_9)) != ERROR_OK)
		{
			return retval;
		}
391
	}
392

393
394
395
396
397
	return ERROR_OK;
}

int arm7_9_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
398
	int retval = ERROR_OK;
399
400
401
402
	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;
403

404
	mask = watchpoint->length - 1;
405

406
407
	if (target->state != TARGET_HALTED)
	{
408
		LOG_WARNING("target not halted");
409
410
		return ERROR_TARGET_NOT_HALTED;
	}
411

412
413
414
415
	if (watchpoint->rw == WPT_ACCESS)
		rw_mask = 0;
	else
		rw_mask = 1;
416

417
418
419
420
421
422
423
424
425
426
	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));

427
428
429
430
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
431
432
433
434
435
436
437
438
439
440
441
442
443
		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));

444
445
446
447
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
448
449
		watchpoint->set = 2;
		arm7_9->wp1_used = 2;
450
	}
451
452
	else
	{
453
		LOG_ERROR("BUG: no hardware comparator available");
454
455
		return ERROR_OK;
	}
456

457
458
459
460
461
	return ERROR_OK;
}

int arm7_9_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
462
	int retval = ERROR_OK;
463
464
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
465

466
467
	if (target->state != TARGET_HALTED)
	{
468
		LOG_WARNING("target not halted");
469
470
		return ERROR_TARGET_NOT_HALTED;
	}
471

472
473
	if (!watchpoint->set)
	{
474
		LOG_WARNING("breakpoint not set");
475
476
		return ERROR_OK;
	}
477

478
479
480
	if (watchpoint->set == 1)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
481
482
483
484
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
485
486
487
488
489
		arm7_9->wp0_used = 0;
	}
	else if (watchpoint->set == 2)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
490
491
492
493
		if((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
494
495
496
497
498
499
500
		arm7_9->wp1_used = 0;
	}
	watchpoint->set = 0;

	return ERROR_OK;
}

501
int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
502
503
504
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
505

506
507
	if (target->state != TARGET_HALTED)
	{
508
		LOG_WARNING("target not halted");
509
510
		return ERROR_TARGET_NOT_HALTED;
	}
511

512
513
514
515
	if (arm7_9->wp_available < 1)
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
516

517
	if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
518
519
520
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
521

522
	arm7_9->wp_available--;
523

524
525
526
527
528
	return ERROR_OK;
}

int arm7_9_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
{
529
	int retval = ERROR_OK;
530
531
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
532

533
534
	if (watchpoint->set)
	{
535
536
537
538
		if((retval = arm7_9_unset_watchpoint(target, watchpoint)) != ERROR_OK)
		{
			return retval;
		}
539
	}
540

541
	arm7_9->wp_available++;
542

543
544
545
	return ERROR_OK;
}

546
547


548
549
550
551

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

553
554
555
556
	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];
557

558
559
	/* set RESTART instruction */
	jtag_add_end_state(TAP_RTI);
oharboe's avatar
oharboe committed
560
561
562
563
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
564
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
565

oharboe's avatar
oharboe committed
566
567
568
	long long then=timeval_ms();
	int timeout;
	while (!(timeout=((timeval_ms()-then)>1000)))
569
570
571
572
573
574
575
576
	{
		/* 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
577
578
579
580
581
582
583
		if (debug_level>=3)
		{
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
584
	}
oharboe's avatar
oharboe committed
585
	if (timeout)
586
	{
587
		LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %x", buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
588
589
		return ERROR_TARGET_TIMEOUT;
	}
590

591
592
593
594
595
	return ERROR_OK;
}

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

599
600
601
602
	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];
603

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

mifi's avatar
mifi committed
612
613
614
	if (!set)
	{
		/* check for DBGACK and SYSCOMP set (others don't care) */
615

mifi's avatar
mifi committed
616
617
618
619
620
621
622
623
		/* 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;
	}
624

625
626
627
628
629
630
	/* read debug status register */
	embeddedice_read_reg_w_check(dbg_stat, check_value, check_value);

	return ERROR_OK;
}

631
632
633
634
635
636
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;
637
	int i, retval = ERROR_OK;
638

639
	data = malloc(size * (sizeof(u32)));
640

641
	retval = embeddedice_receive(jtag_info, data, size);
642

643
644
645
646
	for (i = 0; i < size; i++)
	{
		h_u32_to_le(buffer + (i * 4), data[i]);
	}
647

648
	free(data);
649

650
	return retval;
651
652
653
654
}

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


665
666
	if (!target->dbg_msg_enabled)
		return ERROR_OK;
667

668
669
670
671
	if (target->state == TARGET_RUNNING)
	{
		/* read DCC control register */
		embeddedice_read_reg(dcc_control);
672
673
674
675
		if ((retval = jtag_execute_queue()) != ERROR_OK)
		{
			return retval;
		}
676

677
678
679
680
		/* check W bit */
		if (buf_get_u32(dcc_control->value, 1, 1) == 1)
		{
			u32 request;
681

682
683
684
685
686
687
688
689
			if ((retval = embeddedice_receive(jtag_info, &request, 1)) != ERROR_OK)
			{
				return retval;
			}
			if ((retval = target_request(target, request)) != ERROR_OK)
			{
				return retval;
			}
690
691
		}
	}
692

693
694
695
	return ERROR_OK;
}

696
int arm7_9_poll(target_t *target)
697
698
699
700
701
702
703
704
705
706
{
	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)
	{
707
		return retval;
708
	}
709

710
711
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
	{
712
/*		LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/
713
		if (target->state == TARGET_UNKNOWN)
714
		{
715
			target->state = TARGET_RUNNING;
716
			LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
717
718
719
		}
		if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
		{
720
721
722
			int check_pc=0;
			if (target->state == TARGET_RESET)
			{
oharboe's avatar
   
oharboe committed
723
				if (target->reset_halt)
724
725
726
727
728
729
730
				{
					if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)
					{
						check_pc = 1;
					}
				}
			}
731

732
			target->state = TARGET_HALTED;
733

734
735
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
736

737
738
739
740
741
742
			if (check_pc)
			{
				reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
				u32 t=*((u32 *)reg->value);
				if (t!=0)
				{
743
					LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?");
744
745
				}
			}
746

747
748
749
750
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
			{
				return retval;
			}
751
752
753
754
755
756
		}
		if (target->state == TARGET_DEBUG_RUNNING)
		{
			target->state = TARGET_HALTED;
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
757

758
759
760
761
			if ((retval = target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED)) != ERROR_OK)
			{
				return retval;
			}
762
		}
763
764
		if (target->state != TARGET_HALTED)
		{
765
			LOG_WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
766
		}
767
	}
768
769
770
771
772
	else
	{
		if (target->state != TARGET_DEBUG_RUNNING)
			target->state = TARGET_RUNNING;
	}
773

774
	return ERROR_OK;
775
776
}

777
778
779
/*
  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
780
  while the core is held in reset(SRST). It isn't possible to program the halt
781
782
783
784
  condition once reset was asserted, hence a hook that allows the target to set
  up its reset-halt condition prior to asserting reset.
*/

785
786
int arm7_9_assert_reset(target_t *target)
{
787
788
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
oharboe's avatar
oharboe committed
789
	LOG_DEBUG("target->state: %s",
790
		  Jim_Nvp_value2name_simple( nvp_target_state,target->state)->name);
791

792
793
794
795
796
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
		return ERROR_FAIL;
	}
oharboe's avatar
   
oharboe committed
797

oharboe's avatar
   
oharboe committed
798
	if (target->reset_halt)
799
	{
oharboe's avatar
   
oharboe committed
800
801
802
		/*
		 * Some targets do not support communication while SRST is asserted. We need to
		 * set up the reset vector catch here.
803
		 *
oharboe's avatar
   
oharboe committed
804
		 * If TRST is asserted, then these settings will be reset anyway, so setting them
805
		 * here is harmless.
oharboe's avatar
   
oharboe committed
806
807
808
809
810
811
812
813
814
		 */
		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 */
815
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0);
oharboe's avatar
   
oharboe committed
816
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
817
818
819
			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
820
		}
821
822
	}

oharboe's avatar
   
oharboe committed
823
	/* here we should issue a srst only, but we may have to assert trst as well */
824
	if (jtag_reset_config & RESET_SRST_PULLS_TRST)
825
	{
826
827
828
829
		jtag_add_reset(1, 1);
	} else
	{
		jtag_add_reset(0, 1);
830
	}
831

oharboe's avatar
   
oharboe committed
832

833
834
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
oharboe's avatar
   
oharboe committed
835

836
837
	armv4_5_invalidate_core_regs(target);

838
839
840
841
842
    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
843

844
845
846
847
848
849
	return ERROR_OK;

}

int arm7_9_deassert_reset(target_t *target)
{
850
	int retval=ERROR_OK;
oharboe's avatar
oharboe committed
851
	LOG_DEBUG("target->state: %s",
852
853
		  Jim_Nvp_value2name_simple( nvp_target_state,target->state)->name);

854

855
856
	/* deassert reset lines */
	jtag_add_reset(0, 0);
857

858
	if (target->reset_halt&&(jtag_reset_config & RESET_SRST_PULLS_TRST)!=0)
859
	{
860
		LOG_WARNING("srst pulls trst - can not reset into halted mode. Issuing halt after reset.");
861
862
863
		/* set up embedded ice registers again */
		if ((retval=target->type->examine(target))!=ERROR_OK)
			return retval;
864
865
866
867
868

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

870
871
872
873
		if ((retval=target_halt(target))!=ERROR_OK)
		{
			return retval;
		}
oharboe's avatar
oharboe committed
874

875
876
	}
	return retval;
877
878
}

879
880
881
882
883
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];
884

885
886
	/* we used DBGRQ only if we didn't come out of reset */
	if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq)
887
888
889
	{
		/* program EmbeddedICE Debug Control Register to deassert DBGRQ
		 */
890
		buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
891
892
893
894
		embeddedice_store_reg(dbg_ctrl);
	}
	else
	{
895
		if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch)
896
		{
897
898
899
900
901
902
903
904
905
906
907
908
			/* 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)
			{
909
910
911
912
				if (arm7_9->debug_entry_from_reset)
				{
					embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
				}
913
914
915
916
				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]);
			}
917
			/* control value always has to be restored, as it was either disabled,
918
919
920
			 * or enabled with possibly different bits
			 */
			embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
921
922
		}
	}
923

924
925
926
	return ERROR_OK;
}

927
928
929
930
931
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];
932
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
933
	int i;
oharboe's avatar
   
oharboe committed
934
	int retval;
935

936
	if ((retval=target_halt(target))!=ERROR_OK)
oharboe's avatar
   
oharboe committed
937
		return retval;
938

oharboe's avatar
oharboe committed
939
940
941
	long long then=timeval_ms();
	int timeout;
	while (!(timeout=((timeval_ms()-then)>1000)))
942
	{
oharboe's avatar
   
oharboe committed
943
944
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) != 0)
			break;
945
		embeddedice_read_reg(dbg_stat);
oharboe's avatar
   
oharboe committed
946
947
		if ((retval=jtag_execute_queue())!=ERROR_OK)
			return retval;
oharboe's avatar
oharboe committed
948
949
950
951
952
953
954
		if (debug_level>=3)
		{
			alive_sleep(100);
		} else
		{
			keep_alive();
		}
oharboe's avatar
   
oharboe committed
955
	}
oharboe's avatar
oharboe committed
956
	if (timeout)
oharboe's avatar
   
oharboe committed
957
	{
958
		LOG_ERROR("Failed to halt CPU after 1 sec");
oharboe's avatar
   
oharboe committed
959
		return ERROR_TARGET_TIMEOUT;
960
961
	}
	target->state = TARGET_HALTED;
962

963
964
965
966
967
968
969
	/* 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);
970

971
972
973
974
	if ((retval = arm7_9_clear_halt(target)) != ERROR_OK)
	{
		return retval;
	}
975

976
977
978
979
	/* 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;
980
		LOG_DEBUG("target entered debug from Thumb state, changing to ARM");
981
982
983
984
		/* Entered debug from Thumb mode */
		armv4_5->core_state = ARMV4_5_STATE_THUMB;
		arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
	}
985

986
	/* all register content is now invalid */
987
988
989
990
	if ((retval = armv4_5_invalidate_core_regs(target)) != ERROR_OK)
	{
		return retval;
	}
991

992
993
994
995
	/* 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;
996

997
998
999
1000
	/* 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;
For faster browsing, not all history is shown. View entire blame