arm7_9_common.c 76 KB
Newer Older
1
2
3
4
/***************************************************************************
 *   Copyright (C) 2005 by Dominic Rath                                    *
 *   Dominic.Rath@gmx.de                                                   *
 *                                                                         *
5
6
7
 *   Copyright (C) 2007,2008 yvind Harboe                                      *
 *   oyvind.harboe@zylin.com                                               *
 *                                                                         *
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
26
27
#endif

#include "replacements.h"
28
29
30

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

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

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

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

/* command handler forward declarations */
int handle_arm7_9_write_xpsr_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_write_xpsr_im8_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_read_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_write_core_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_arm7_9_dbgrq_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
57
int handle_arm7_9_fast_memory_access_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
58
int handle_arm7_9_dcc_downloads_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
59
int handle_arm7_9_etm_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
60

61

62
63
64
65
66
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;
67
	arm7_9->wp0_used = 0;
68
69
	arm7_9->wp1_used = arm7_9->wp1_used_default;
	arm7_9->wp_available = arm7_9->wp_available_max;
70

71
72
73
74
75
76
77
	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)
78
	{
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
		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--;
	
	/* 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;
102
	}
103

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

126
	return jtag_execute_queue();
127
128
}

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

138

139
140
141
142
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;
143

144
145
146
147
	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
	{
		return -1;
	}
148

149
150
151
152
	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
	{
		return -1;
	}
153

154
155
	*armv4_5_p = armv4_5;
	*arm7_9_p = arm7_9;
156

157
158
159
	return ERROR_OK;
}

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

169
170
	if (target->state != TARGET_HALTED)
	{
171
		LOG_WARNING("target not halted");
172
173
		return ERROR_TARGET_NOT_HALTED;
	}
174

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

		retval=jtag_execute_queue();
202
203
204
	}
	else if (breakpoint->type == BKPT_SOFT)
	{
205
206
207
208
209
210
211
		if ((retval=arm7_9_set_software_breakpoints(arm7_9))!=ERROR_OK)
			return retval;
		
		/* did we already set this breakpoint? */
		if (breakpoint->set)
			return ERROR_OK;
		
212
213
		if (breakpoint->length == 4)
		{
ntfreak's avatar
ntfreak committed
214
			u32 verify = 0xffffffff;
215
			/* keep the original instruction in target endianness */
216
			target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
drath's avatar
drath committed
217
			/* write the breakpoint instruction in target endianness (arm7_9->arm_bkpt is host endian) */
218
			target_write_u32(target, breakpoint->address, arm7_9->arm_bkpt);
219

ntfreak's avatar
ntfreak committed
220
221
222
			target->type->read_memory(target, breakpoint->address, 4, 1, (u8 *)&verify);
			if (verify != arm7_9->arm_bkpt)
			{
223
				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
224
225
				return ERROR_OK;
			}
226
227
228
		}
		else
		{
ntfreak's avatar
ntfreak committed
229
			u16 verify = 0xffff;
230
			/* keep the original instruction in target endianness */
231
			target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
drath's avatar
drath committed
232
233
			/* write the breakpoint instruction in target endianness (arm7_9->thumb_bkpt is host endian) */
			target_write_u16(target, breakpoint->address, arm7_9->thumb_bkpt);
234

ntfreak's avatar
ntfreak committed
235
236
237
			target->type->read_memory(target, breakpoint->address, 2, 1, (u8 *)&verify);
			if (verify != arm7_9->thumb_bkpt)
			{
238
				LOG_ERROR("Unable to set thumb 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
244
		}
		breakpoint->set = 1;
	}

245
	return retval;
246
247
248
249
250
251
252

}

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

254
255
	if (!breakpoint->set)
	{
256
		LOG_WARNING("breakpoint not set");
257
258
		return ERROR_OK;
	}
259

260
261
262
263
264
265
266
267
268
269
270
271
	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;
		}
272
		jtag_execute_queue();
273
274
275
276
		breakpoint->set = 0;
	}
	else
	{
277
		/* restore original instruction (kept in target endianness) */
278
279
		if (breakpoint->length == 4)
		{
280
281
282
283
284
			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);
285
286
287
		}
		else
		{
288
289
290
291
292
			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);
293
294
295
296
297
298
299
		}
		breakpoint->set = 0;
	}

	return ERROR_OK;
}

300
int arm7_9_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
301
302
303
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
304

305
306
	if (target->state != TARGET_HALTED)
	{
307
		LOG_WARNING("target not halted");
308
309
		return ERROR_TARGET_NOT_HALTED;
	}
310
311
	
	if (arm7_9->breakpoint_count==0)
312
	{
313
314
315
316
		/* make sure we don't have any dangling breakpoints. This is vital upon 
		 * GDB connect/disconnect 
		 */
		arm7_9_clear_watchpoints(arm7_9);	
317
	}
318

319
	if ((breakpoint->type == BKPT_HARD) && (arm7_9->wp_available < 1))
320
	{
321
		LOG_INFO("no watchpoint unit available for hardware breakpoint");
322
323
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
324

325
	if ((breakpoint->length != 2) && (breakpoint->length != 4))
326
	{
327
		LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
328
329
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
330

331
	if (breakpoint->type == BKPT_HARD)
332
	{
333
		arm7_9->wp_available--;
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
		
		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");
		}
	}
	
351

352
353
354
	arm7_9->breakpoint_count++;
	
	return arm7_9_set_breakpoint(target, breakpoint);
355
356
357
358
359
360
}

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

362
	arm7_9_unset_breakpoint(target, breakpoint);
363

364
365
	if (breakpoint->type == BKPT_HARD)
		arm7_9->wp_available++;
366
367
368
369
370
371
372
	
	arm7_9->breakpoint_count--;
	if (arm7_9->breakpoint_count==0)
	{
		/* make sure we don't have any dangling breakpoints */
		arm7_9_clear_watchpoints(arm7_9);	
	}
373

374
375
376
377
378
379
380
381
382
	return ERROR_OK;
}

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

384
	mask = watchpoint->length - 1;
385

386
387
	if (target->state != TARGET_HALTED)
	{
388
		LOG_WARNING("target not halted");
389
390
		return ERROR_TARGET_NOT_HALTED;
	}
391

392
393
394
395
	if (watchpoint->rw == WPT_ACCESS)
		rw_mask = 0;
	else
		rw_mask = 1;
396

397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
	if (!arm7_9->wp0_used)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], watchpoint->address);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], watchpoint->mask);
		if( watchpoint->mask != 0xffffffffu )
			embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_VALUE], watchpoint->value);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xff & ~EICE_W_CTRL_nOPC & ~rw_mask);
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE | EICE_W_CTRL_nOPC | (watchpoint->rw & 1));

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

		jtag_execute_queue();
		watchpoint->set = 2;
		arm7_9->wp1_used = 2;
424
	}
425
426
	else
	{
427
		LOG_ERROR("BUG: no hardware comparator available");
428
429
		return ERROR_OK;
	}
430

431
432
433
434
435
436
437
	return ERROR_OK;
}

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

439
440
	if (target->state != TARGET_HALTED)
	{
441
		LOG_WARNING("target not halted");
442
443
		return ERROR_TARGET_NOT_HALTED;
	}
444

445
446
	if (!watchpoint->set)
	{
447
		LOG_WARNING("breakpoint not set");
448
449
		return ERROR_OK;
	}
450

451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
	if (watchpoint->set == 1)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x0);
		jtag_execute_queue();
		arm7_9->wp0_used = 0;
	}
	else if (watchpoint->set == 2)
	{
		embeddedice_set_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE], 0x0);
		jtag_execute_queue();
		arm7_9->wp1_used = 0;
	}
	watchpoint->set = 0;

	return ERROR_OK;
}

468
int arm7_9_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
469
470
471
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
472

473
474
	if (target->state != TARGET_HALTED)
	{
475
		LOG_WARNING("target not halted");
476
477
		return ERROR_TARGET_NOT_HALTED;
	}
478

479
480
481
482
	if (arm7_9->wp_available < 1)
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
483

484
	if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
485
486
487
	{
		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
	}
488

489
	arm7_9->wp_available--;
490

491
492
493
494
495
496
497
	return ERROR_OK;
}

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

499
500
501
502
	if (watchpoint->set)
	{
		arm7_9_unset_watchpoint(target, watchpoint);
	}
503

504
	arm7_9->wp_available++;
505

506
507
508
	return ERROR_OK;
}

509
510


511
512
513
514
515

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

517
518
519
520
	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];
521

522
523
	/* set RESTART instruction */
	jtag_add_end_state(TAP_RTI);
oharboe's avatar
oharboe committed
524
525
526
527
	if (arm7_9->need_bypass_before_restart) {
		arm7_9->need_bypass_before_restart = 0;
		arm_jtag_set_instr(jtag_info, 0xf, NULL);
	}
528
	arm_jtag_set_instr(jtag_info, 0x4, NULL);
529

530
531
532
533
534
535
536
537
538
	for (timeout=0; timeout<50; timeout++)
	{
		/* read debug status register */
		embeddedice_read_reg(dbg_stat);
		if ((retval = jtag_execute_queue()) != ERROR_OK)
			return retval;
		if ((buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
				   && (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_SYSCOMP, 1)))
			break;
539
		usleep(100000);
540
541
542
	}
	if (timeout == 50)
	{
543
		LOG_ERROR("timeout waiting for SYSCOMP & DBGACK, last DBG_STATUS: %x", buf_get_u32(dbg_stat->value, 0, dbg_stat->size));
544
545
		return ERROR_TARGET_TIMEOUT;
	}
546

547
548
549
550
551
	return ERROR_OK;
}

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

555
556
557
558
	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];
559

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

mifi's avatar
mifi committed
568
569
570
	if (!set)
	{
		/* check for DBGACK and SYSCOMP set (others don't care) */
571

mifi's avatar
mifi committed
572
573
574
575
576
577
578
579
		/* 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;
	}
580

581
582
583
584
585
586
	/* read debug status register */
	embeddedice_read_reg_w_check(dbg_stat, check_value, check_value);

	return ERROR_OK;
}

587
588
589
590
591
592
593
int arm7_9_target_request_data(target_t *target, u32 size, u8 *buffer)
{
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
	u32 *data;
	int i;
594

595
	data = malloc(size * (sizeof(u32)));
596

597
	embeddedice_receive(jtag_info, data, size);
598

599
600
601
602
	for (i = 0; i < size; i++)
	{
		h_u32_to_le(buffer + (i * 4), data[i]);
	}
603

604
	free(data);
605

606
607
608
609
610
611
	return ERROR_OK;
}

int arm7_9_handle_target_request(void *priv)
{
	target_t *target = priv;
612
613
	if (!target->type->examined)
		return ERROR_OK;
614
615
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
616
	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
617
	reg_t *dcc_control = &arm7_9->eice_cache->reg_list[EICE_COMMS_CTRL];
618
619


620
621
	if (!target->dbg_msg_enabled)
		return ERROR_OK;
622

623
624
625
626
627
	if (target->state == TARGET_RUNNING)
	{
		/* read DCC control register */
		embeddedice_read_reg(dcc_control);
		jtag_execute_queue();
628

629
630
631
632
		/* check W bit */
		if (buf_get_u32(dcc_control->value, 1, 1) == 1)
		{
			u32 request;
633

634
635
636
637
			embeddedice_receive(jtag_info, &request, 1);
			target_request(target, request);
		}
	}
638

639
640
641
	return ERROR_OK;
}

642
int arm7_9_poll(target_t *target)
643
644
645
646
647
648
649
650
651
652
{
	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)
	{
653
		return retval;
654
	}
655

656
657
	if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1))
	{
658
/*		LOG_DEBUG("DBGACK set, dbg_state->value: 0x%x", buf_get_u32(dbg_stat->value, 0, 32));*/
659
		if (target->state == TARGET_UNKNOWN)
660
		{
661
			target->state = TARGET_RUNNING;
662
			LOG_WARNING("DBGACK set while target was in unknown state. Reset or initialize target.");
663
664
665
		}
		if ((target->state == TARGET_RUNNING) || (target->state == TARGET_RESET))
		{
666
667
668
			int check_pc=0;
			if (target->state == TARGET_RESET)
			{
oharboe's avatar
   
oharboe committed
669
				if (target->reset_halt)
670
671
672
673
674
675
676
				{
					if ((jtag_reset_config & RESET_SRST_PULLS_TRST)==0)
					{
						check_pc = 1;
					}
				}
			}
677

678
			target->state = TARGET_HALTED;
679

680
681
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
682

683
684
685
686
687
688
			if (check_pc)
			{
				reg_t *reg = register_get_by_name(target->reg_cache, "pc", 1);
				u32 t=*((u32 *)reg->value);
				if (t!=0)
				{
689
					LOG_ERROR("PC was not 0. Does this target need srst_pulls_trst?");
690
691
				}
			}
692

693
694
695
696
697
698
699
			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
		}
		if (target->state == TARGET_DEBUG_RUNNING)
		{
			target->state = TARGET_HALTED;
			if ((retval = arm7_9_debug_entry(target)) != ERROR_OK)
				return retval;
700

701
702
			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
		}
703
704
		if (target->state != TARGET_HALTED)
		{
705
			LOG_WARNING("DBGACK set, but the target did not end up in the halted stated %d", target->state);
706
		}
707
	}
708
709
710
711
712
	else
	{
		if (target->state != TARGET_DEBUG_RUNNING)
			target->state = TARGET_RUNNING;
	}
713

714
	return ERROR_OK;
715
716
}

717
718
719
/*
  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
720
  while the core is held in reset(SRST). It isn't possible to program the halt
721
722
723
724
  condition once reset was asserted, hence a hook that allows the target to set
  up its reset-halt condition prior to asserting reset.
*/

725
726
int arm7_9_assert_reset(target_t *target)
{
727
728
	armv4_5_common_t *armv4_5 = target->arch_info;
	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
729
	LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
730

731
732
733
734
735
	if (!(jtag_reset_config & RESET_HAS_SRST))
	{
		LOG_ERROR("Can't assert SRST");
		return ERROR_FAIL;
	}
oharboe's avatar
   
oharboe committed
736

oharboe's avatar
   
oharboe committed
737
	if (target->reset_halt)
738
	{
oharboe's avatar
   
oharboe committed
739
740
741
		/*
		 * Some targets do not support communication while SRST is asserted. We need to
		 * set up the reset vector catch here.
742
		 *
oharboe's avatar
   
oharboe committed
743
		 * If TRST is asserted, then these settings will be reset anyway, so setting them
744
		 * here is harmless.
oharboe's avatar
   
oharboe committed
745
746
747
748
749
750
751
752
753
		 */
		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 */
754
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0);
oharboe's avatar
   
oharboe committed
755
			embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
756
757
758
			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
759
		}
760
761
	}

oharboe's avatar
   
oharboe committed
762
	/* here we should issue a srst only, but we may have to assert trst as well */
763
	if (jtag_reset_config & RESET_SRST_PULLS_TRST)
764
	{
765
766
767
768
		jtag_add_reset(1, 1);
	} else
	{
		jtag_add_reset(0, 1);
769
	}
770

oharboe's avatar
   
oharboe committed
771

772
773
	target->state = TARGET_RESET;
	jtag_add_sleep(50000);
oharboe's avatar
   
oharboe committed
774

775
776
	armv4_5_invalidate_core_regs(target);

777
778
779
780
781
782
    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;
	}
	
783
784
785
786
787
788
	return ERROR_OK;

}

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

792
793
	/* deassert reset lines */
	jtag_add_reset(0, 0);
794

795
	if (target->reset_halt&&(jtag_reset_config & RESET_SRST_PULLS_TRST)!=0)
796
	{
797
		LOG_WARNING("srst pulls trst - can not reset into halted mode. Issuing halt after reset.");
798
799
800
		/* set up embedded ice registers again */
		if ((retval=target->type->examine(target))!=ERROR_OK)
			return retval;
801
802
803
804
805
806
807
808
809
810
811

		if ((retval=target_poll(target))!=ERROR_OK)
		{
			return retval;
		}
		
		if ((retval=target_halt(target))!=ERROR_OK)
		{
			return retval;
		}
		
812
813
	}
	return retval;
814
815
}

816
817
818
819
820
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];
821

822
823
	/* we used DBGRQ only if we didn't come out of reset */
	if (!arm7_9->debug_entry_from_reset && arm7_9->use_dbgrq)
824
825
826
	{
		/* program EmbeddedICE Debug Control Register to deassert DBGRQ
		 */
827
		buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 0);
828
829
830
831
		embeddedice_store_reg(dbg_ctrl);
	}
	else
	{
832
		if (arm7_9->debug_entry_from_reset && arm7_9->has_vector_catch)
833
		{
834
835
836
837
838
839
840
841
842
843
844
845
			/* 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)
			{
846
847
848
849
				if (arm7_9->debug_entry_from_reset)
				{
					embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE]);
				}
850
851
852
853
				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]);
			}
854
			/* control value always has to be restored, as it was either disabled,
855
856
857
			 * or enabled with possibly different bits
			 */
			embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE]);
858
859
		}
	}
860

861
862
863
	return ERROR_OK;
}

864
865
866
867
868
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];
869
	reg_t *dbg_ctrl = &arm7_9->eice_cache->reg_list[EICE_DBG_CTRL];
870
	int i;
oharboe's avatar
   
oharboe committed
871
	int retval;
872

873
	if ((retval=target_halt(target))!=ERROR_OK)
oharboe's avatar
   
oharboe committed
874
		return retval;
875

oharboe's avatar
   
oharboe committed
876
	for (i=0; i<10; i++)
877
	{
oharboe's avatar
   
oharboe committed
878
879
		if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) != 0)
			break;
880
		embeddedice_read_reg(dbg_stat);
oharboe's avatar
   
oharboe committed
881
882
883
884
		if ((retval=jtag_execute_queue())!=ERROR_OK)
			return retval;
		/* do not eat all CPU, time out after 1 se*/
		usleep(100*1000);
885

oharboe's avatar
   
oharboe committed
886
887
888
	}
	if (i==10)
	{
889
		LOG_ERROR("Failed to halt CPU after 1 sec");
oharboe's avatar
   
oharboe committed
890
		return ERROR_TARGET_TIMEOUT;
891
892
	}
	target->state = TARGET_HALTED;
893

894
895
896
897
898
899
900
	/* 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);
901

902
	arm7_9_clear_halt(target);
903

904
905
906
907
	/* 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;
908
		LOG_DEBUG("target entered debug from Thumb state, changing to ARM");
909
910
911
912
		/* Entered debug from Thumb mode */
		armv4_5->core_state = ARMV4_5_STATE_THUMB;
		arm7_9->change_to_arm(target, &r0_thumb, &pc_thumb);
	}
913

914
915
	/* all register content is now invalid */
	armv4_5_invalidate_core_regs(target);
916

917
918
919
920
	/* 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;
921

922
923
924
925
	/* 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;
926

927
928
	armv4_5->core_mode = ARMV4_5_MODE_SVC;
	armv4_5->core_state = ARMV4_5_STATE_ARM;
929
930
931

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

933
934
	/* reset registers */
	for (i = 0; i <= 14; i++)
935
	{
936
937
938
939
		buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, 0xffffffff);
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 1;
		ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
	}
940

941
	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
942

943
944
945
946
947
	return ERROR_OK;
}

int arm7_9_halt(target_t *target)
{
948
	if (target->state==TARGET_RESET)
949
	{
950
		LOG_ERROR("BUG: arm7/9 does not support halt during reset. This is handled in arm7_9_assert_reset()");
951
952
953
		return ERROR_OK;
	}

954
955
956
	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];
957

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

960
961
	if (target->state == TARGET_HALTED)
	{
962
		LOG_DEBUG("target was already halted");
oharboe's avatar
   
oharboe committed
963
		return ERROR_OK;
964
	}
965

966
967
	if (target->state == TARGET_UNKNOWN)
	{
968
		LOG_WARNING("target was in unknown state when halt was requested");
969
	}
970

971
972
973
974
	if (arm7_9->use_dbgrq)
	{
		/* program EmbeddedICE Debug Control Register to assert DBGRQ
		 */
oharboe's avatar
oharboe committed
975
976
977
		if (arm7_9->set_special_dbgrq) {
			arm7_9->set_special_dbgrq(target);
		} else {
978
			buf_set_u32(dbg_ctrl->value, EICE_DBG_CONTROL_DBGRQ, 1, 1);
oharboe's avatar
oharboe committed
979
980
			embeddedice_store_reg(dbg_ctrl);
		}
981
982
983
984
985
986
987
	}
	else
	{
		/* program watchpoint unit to match on any address
		 */
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0xffffffff);
		embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff);
988
989
		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);
990
991
992
	}

	target->debug_reason = DBG_REASON_DBGRQ;
993

994
995
996
997
998
999
1000
	return ERROR_OK;
}

int arm7_9_debug_entry(target_t *target)
{
	int i;
	u32 context[16];
For faster browsing, not all history is shown. View entire blame