arm: add error propagation to generic get_ttb fn
[openocd.git] / src / target / arm720t.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2009 by Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "arm720t.h"
28 #include <helper/time_support.h>
29 #include "target_type.h"
30 #include "register.h"
31 #include "arm_opcodes.h"
32
33
34 /*
35 * ARM720 is an ARM7TDMI-S with MMU and ETM7. For information, see
36 * ARM DDI 0229C especially Chapter 9 about debug support.
37 */
38
39 #if 0
40 #define _DEBUG_INSTRUCTION_EXECUTION_
41 #endif
42
43 static int arm720t_scan_cp15(struct target *target,
44 uint32_t out, uint32_t *in, int instruction, int clock_arg)
45 {
46 int retval;
47 struct arm720t_common *arm720t = target_to_arm720(target);
48 struct arm_jtag *jtag_info;
49 struct scan_field fields[2];
50 uint8_t out_buf[4];
51 uint8_t instruction_buf = instruction;
52
53 jtag_info = &arm720t->arm7_9_common.jtag_info;
54
55 buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
56
57 if ((retval = arm_jtag_scann(jtag_info, 0xf, TAP_DRPAUSE)) != ERROR_OK)
58 {
59 return retval;
60 }
61 if ((retval = arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL, TAP_DRPAUSE)) != ERROR_OK)
62 {
63 return retval;
64 }
65
66 fields[0].num_bits = 1;
67 fields[0].out_value = &instruction_buf;
68 fields[0].in_value = NULL;
69
70 fields[1].num_bits = 32;
71 fields[1].out_value = out_buf;
72 fields[1].in_value = NULL;
73
74 if (in)
75 {
76 fields[1].in_value = (uint8_t *)in;
77 jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
78 jtag_add_callback(arm7flip32, (jtag_callback_data_t)in);
79 } else
80 {
81 jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
82 }
83
84 if (clock_arg)
85 jtag_add_runtest(0, TAP_DRPAUSE);
86
87 #ifdef _DEBUG_INSTRUCTION_EXECUTION_
88 if ((retval = jtag_execute_queue()) != ERROR_OK)
89 {
90 return retval;
91 }
92
93 if (in)
94 LOG_DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
95 else
96 LOG_DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock_arg);
97 #else
98 LOG_DEBUG("out: %8.8" PRIx32 ", instruction: %i, clock: %i", out, instruction, clock_arg);
99 #endif
100
101 return ERROR_OK;
102 }
103
104 static int arm720t_read_cp15(struct target *target, uint32_t opcode, uint32_t *value)
105 {
106 /* fetch CP15 opcode */
107 arm720t_scan_cp15(target, opcode, NULL, 1, 1);
108 /* "DECODE" stage */
109 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
110 /* "EXECUTE" stage (1) */
111 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
112 arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
113 /* "EXECUTE" stage (2) */
114 arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
115 /* "EXECUTE" stage (3), CDATA is read */
116 arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);
117
118 return ERROR_OK;
119 }
120
121 static int arm720t_write_cp15(struct target *target, uint32_t opcode, uint32_t value)
122 {
123 /* fetch CP15 opcode */
124 arm720t_scan_cp15(target, opcode, NULL, 1, 1);
125 /* "DECODE" stage */
126 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
127 /* "EXECUTE" stage (1) */
128 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
129 arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
130 /* "EXECUTE" stage (2) */
131 arm720t_scan_cp15(target, value, NULL, 0, 1);
132 arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
133
134 return ERROR_OK;
135 }
136
137 static int arm720t_get_ttb(struct target *target, uint32_t *result)
138 {
139 uint32_t ttb = 0x0;
140
141 int retval;
142
143 retval = arm720t_read_cp15(target, 0xee120f10, &ttb);
144 if (retval != ERROR_OK)
145 return retval;
146 retval = jtag_execute_queue();
147 if (retval != ERROR_OK)
148 return retval;
149
150 ttb &= 0xffffc000;
151
152 *result = ttb;
153
154 return ERROR_OK;
155 }
156
157 static void arm720t_disable_mmu_caches(struct target *target,
158 int mmu, int d_u_cache, int i_cache)
159 {
160 uint32_t cp15_control;
161
162 /* read cp15 control register */
163 arm720t_read_cp15(target, 0xee110f10, &cp15_control);
164 jtag_execute_queue();
165
166 if (mmu)
167 cp15_control &= ~0x1U;
168
169 if (d_u_cache || i_cache)
170 cp15_control &= ~0x4U;
171
172 arm720t_write_cp15(target, 0xee010f10, cp15_control);
173 }
174
175 static void arm720t_enable_mmu_caches(struct target *target,
176 int mmu, int d_u_cache, int i_cache)
177 {
178 uint32_t cp15_control;
179
180 /* read cp15 control register */
181 arm720t_read_cp15(target, 0xee110f10, &cp15_control);
182 jtag_execute_queue();
183
184 if (mmu)
185 cp15_control |= 0x1U;
186
187 if (d_u_cache || i_cache)
188 cp15_control |= 0x4U;
189
190 arm720t_write_cp15(target, 0xee010f10, cp15_control);
191 }
192
193 static void arm720t_post_debug_entry(struct target *target)
194 {
195 struct arm720t_common *arm720t = target_to_arm720(target);
196
197 /* examine cp15 control reg */
198 arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);
199 jtag_execute_queue();
200 LOG_DEBUG("cp15_control_reg: %8.8" PRIx32 "", arm720t->cp15_control_reg);
201
202 arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
203 arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
204 arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
205
206 /* save i/d fault status and address register */
207 arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
208 arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);
209 jtag_execute_queue();
210 }
211
212 static void arm720t_pre_restore_context(struct target *target)
213 {
214 struct arm720t_common *arm720t = target_to_arm720(target);
215
216 /* restore i/d fault status and address register */
217 arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);
218 arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
219 }
220
221 static int arm720t_verify_pointer(struct command_context *cmd_ctx,
222 struct arm720t_common *arm720t)
223 {
224 if (arm720t->common_magic != ARM720T_COMMON_MAGIC) {
225 command_print(cmd_ctx, "target is not an ARM720");
226 return ERROR_TARGET_INVALID;
227 }
228 return ERROR_OK;
229 }
230
231 static int arm720t_arch_state(struct target *target)
232 {
233 struct arm720t_common *arm720t = target_to_arm720(target);
234 struct arm *armv4_5;
235
236 static const char *state[] =
237 {
238 "disabled", "enabled"
239 };
240
241 armv4_5 = &arm720t->arm7_9_common.armv4_5_common;
242
243 arm_arch_state(target);
244 LOG_USER("MMU: %s, Cache: %s",
245 state[arm720t->armv4_5_mmu.mmu_enabled],
246 state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
247
248 return ERROR_OK;
249 }
250
251 static int arm720_mmu(struct target *target, int *enabled)
252 {
253 if (target->state != TARGET_HALTED) {
254 LOG_ERROR("%s: target not halted", __func__);
255 return ERROR_TARGET_INVALID;
256 }
257
258 *enabled = target_to_arm720(target)->armv4_5_mmu.mmu_enabled;
259 return ERROR_OK;
260 }
261
262 static int arm720_virt2phys(struct target *target,
263 uint32_t virtual, uint32_t *physical)
264 {
265 uint32_t cb;
266 struct arm720t_common *arm720t = target_to_arm720(target);
267
268 uint32_t ret;
269 int retval = armv4_5_mmu_translate_va(target,
270 &arm720t->armv4_5_mmu, virtual, &cb, &ret);
271 if (retval != ERROR_OK)
272 return retval;
273 *physical = ret;
274 return ERROR_OK;
275 }
276
277 static int arm720t_read_memory(struct target *target,
278 uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
279 {
280 int retval;
281 struct arm720t_common *arm720t = target_to_arm720(target);
282
283 /* disable cache, but leave MMU enabled */
284 if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
285 arm720t_disable_mmu_caches(target, 0, 1, 0);
286
287 retval = arm7_9_read_memory(target, address, size, count, buffer);
288
289 if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
290 arm720t_enable_mmu_caches(target, 0, 1, 0);
291
292 return retval;
293 }
294
295 static int arm720t_read_phys_memory(struct target *target,
296 uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
297 {
298 struct arm720t_common *arm720t = target_to_arm720(target);
299
300 return armv4_5_mmu_read_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
301 }
302
303 static int arm720t_write_phys_memory(struct target *target,
304 uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
305 {
306 struct arm720t_common *arm720t = target_to_arm720(target);
307
308 return armv4_5_mmu_write_physical(target, &arm720t->armv4_5_mmu, address, size, count, buffer);
309 }
310
311 static int arm720t_soft_reset_halt(struct target *target)
312 {
313 int retval = ERROR_OK;
314 struct arm720t_common *arm720t = target_to_arm720(target);
315 struct reg *dbg_stat = &arm720t->arm7_9_common
316 .eice_cache->reg_list[EICE_DBG_STAT];
317 struct arm *armv4_5 = &arm720t->arm7_9_common
318 .armv4_5_common;
319
320 if ((retval = target_halt(target)) != ERROR_OK)
321 {
322 return retval;
323 }
324
325 long long then = timeval_ms();
326 int timeout;
327 while (!(timeout = ((timeval_ms()-then) > 1000)))
328 {
329 if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
330 {
331 embeddedice_read_reg(dbg_stat);
332 if ((retval = jtag_execute_queue()) != ERROR_OK)
333 {
334 return retval;
335 }
336 } else
337 {
338 break;
339 }
340 if (debug_level >= 3)
341 {
342 alive_sleep(100);
343 } else
344 {
345 keep_alive();
346 }
347 }
348 if (timeout)
349 {
350 LOG_ERROR("Failed to halt CPU after 1 sec");
351 return ERROR_TARGET_TIMEOUT;
352 }
353
354 target->state = TARGET_HALTED;
355
356 /* SVC, ARM state, IRQ and FIQ disabled */
357 uint32_t cpsr;
358
359 cpsr = buf_get_u32(armv4_5->cpsr->value, 0, 32);
360 cpsr &= ~0xff;
361 cpsr |= 0xd3;
362 arm_set_cpsr(armv4_5, cpsr);
363 armv4_5->cpsr->dirty = 1;
364
365 /* start fetching from 0x0 */
366 buf_set_u32(armv4_5->pc->value, 0, 32, 0x0);
367 armv4_5->pc->dirty = 1;
368 armv4_5->pc->valid = 1;
369
370 arm720t_disable_mmu_caches(target, 1, 1, 1);
371 arm720t->armv4_5_mmu.mmu_enabled = 0;
372 arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
373 arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
374
375 if ((retval = target_call_event_callbacks(target, TARGET_EVENT_HALTED)) != ERROR_OK)
376 {
377 return retval;
378 }
379
380 return ERROR_OK;
381 }
382
383 static int arm720t_init_target(struct command_context *cmd_ctx, struct target *target)
384 {
385 return arm7tdmi_init_target(cmd_ctx, target);
386 }
387
388 /* FIXME remove forward decls */
389 static int arm720t_mrc(struct target *target, int cpnum,
390 uint32_t op1, uint32_t op2,
391 uint32_t CRn, uint32_t CRm,
392 uint32_t *value);
393 static int arm720t_mcr(struct target *target, int cpnum,
394 uint32_t op1, uint32_t op2,
395 uint32_t CRn, uint32_t CRm,
396 uint32_t value);
397
398 static int arm720t_init_arch_info(struct target *target,
399 struct arm720t_common *arm720t, struct jtag_tap *tap)
400 {
401 struct arm7_9_common *arm7_9 = &arm720t->arm7_9_common;
402
403 arm7_9->armv4_5_common.mrc = arm720t_mrc;
404 arm7_9->armv4_5_common.mcr = arm720t_mcr;
405
406 arm7tdmi_init_arch_info(target, arm7_9, tap);
407
408 arm720t->common_magic = ARM720T_COMMON_MAGIC;
409
410 arm7_9->post_debug_entry = arm720t_post_debug_entry;
411 arm7_9->pre_restore_context = arm720t_pre_restore_context;
412
413 arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;
414 arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;
415 arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;
416 arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;
417 arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
418 arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
419 arm720t->armv4_5_mmu.has_tiny_pages = 0;
420 arm720t->armv4_5_mmu.mmu_enabled = 0;
421
422 return ERROR_OK;
423 }
424
425 static int arm720t_target_create(struct target *target, Jim_Interp *interp)
426 {
427 struct arm720t_common *arm720t = calloc(1, sizeof(*arm720t));
428
429 arm720t->arm7_9_common.armv4_5_common.is_armv4 = true;
430 return arm720t_init_arch_info(target, arm720t, target->tap);
431 }
432
433 COMMAND_HANDLER(arm720t_handle_cp15_command)
434 {
435 int retval;
436 struct target *target = get_current_target(CMD_CTX);
437 struct arm720t_common *arm720t = target_to_arm720(target);
438 struct arm_jtag *jtag_info;
439
440 retval = arm720t_verify_pointer(CMD_CTX, arm720t);
441 if (retval != ERROR_OK)
442 return retval;
443
444 jtag_info = &arm720t->arm7_9_common.jtag_info;
445
446 if (target->state != TARGET_HALTED)
447 {
448 command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
449 return ERROR_OK;
450 }
451
452 /* one or more argument, access a single register (write if second argument is given */
453 if (CMD_ARGC >= 1)
454 {
455 uint32_t opcode;
456 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], opcode);
457
458 if (CMD_ARGC == 1)
459 {
460 uint32_t value;
461 if ((retval = arm720t_read_cp15(target, opcode, &value)) != ERROR_OK)
462 {
463 command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
464 return ERROR_OK;
465 }
466
467 if ((retval = jtag_execute_queue()) != ERROR_OK)
468 {
469 return retval;
470 }
471
472 command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
473 }
474 else if (CMD_ARGC == 2)
475 {
476 uint32_t value;
477 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
478
479 if ((retval = arm720t_write_cp15(target, opcode, value)) != ERROR_OK)
480 {
481 command_print(CMD_CTX, "couldn't access cp15 with opcode 0x%8.8" PRIx32 "", opcode);
482 return ERROR_OK;
483 }
484 command_print(CMD_CTX, "0x%8.8" PRIx32 ": 0x%8.8" PRIx32 "", opcode, value);
485 }
486 }
487
488 return ERROR_OK;
489 }
490
491 static int arm720t_mrc(struct target *target, int cpnum,
492 uint32_t op1, uint32_t op2,
493 uint32_t CRn, uint32_t CRm,
494 uint32_t *value)
495 {
496 if (cpnum!=15)
497 {
498 LOG_ERROR("Only cp15 is supported");
499 return ERROR_FAIL;
500 }
501
502 /* read "to" r0 */
503 return arm720t_read_cp15(target,
504 ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
505 value);
506
507 }
508
509 static int arm720t_mcr(struct target *target, int cpnum,
510 uint32_t op1, uint32_t op2,
511 uint32_t CRn, uint32_t CRm,
512 uint32_t value)
513 {
514 if (cpnum!=15)
515 {
516 LOG_ERROR("Only cp15 is supported");
517 return ERROR_FAIL;
518 }
519
520 /* write "from" r0 */
521 return arm720t_write_cp15(target,
522 ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
523 value);
524 }
525
526 static const struct command_registration arm720t_exec_command_handlers[] = {
527 {
528 .name = "cp15",
529 .handler = arm720t_handle_cp15_command,
530 .mode = COMMAND_EXEC,
531 /* prefer using less error-prone "arm mcr" or "arm mrc" */
532 .help = "display/modify cp15 register using ARM opcode"
533 " (DEPRECATED)",
534 .usage = "instruction [value]",
535 },
536 COMMAND_REGISTRATION_DONE
537 };
538
539 static const struct command_registration arm720t_command_handlers[] = {
540 {
541 .chain = arm7_9_command_handlers,
542 },
543 {
544 .name = "arm720t",
545 .mode = COMMAND_ANY,
546 .help = "arm720t command group",
547 .chain = arm720t_exec_command_handlers,
548 },
549 COMMAND_REGISTRATION_DONE
550 };
551
552 /** Holds methods for ARM720 targets. */
553 struct target_type arm720t_target =
554 {
555 .name = "arm720t",
556
557 .poll = arm7_9_poll,
558 .arch_state = arm720t_arch_state,
559
560 .halt = arm7_9_halt,
561 .resume = arm7_9_resume,
562 .step = arm7_9_step,
563
564 .assert_reset = arm7_9_assert_reset,
565 .deassert_reset = arm7_9_deassert_reset,
566 .soft_reset_halt = arm720t_soft_reset_halt,
567
568 .get_gdb_reg_list = arm_get_gdb_reg_list,
569
570 .read_memory = arm720t_read_memory,
571 .write_memory = arm7_9_write_memory,
572 .read_phys_memory = arm720t_read_phys_memory,
573 .write_phys_memory = arm720t_write_phys_memory,
574 .mmu = arm720_mmu,
575 .virt2phys = arm720_virt2phys,
576
577 .bulk_write_memory = arm7_9_bulk_write_memory,
578
579 .checksum_memory = arm_checksum_memory,
580 .blank_check_memory = arm_blank_check_memory,
581
582 .run_algorithm = armv4_5_run_algorithm,
583
584 .add_breakpoint = arm7_9_add_breakpoint,
585 .remove_breakpoint = arm7_9_remove_breakpoint,
586 .add_watchpoint = arm7_9_add_watchpoint,
587 .remove_watchpoint = arm7_9_remove_watchpoint,
588
589 .commands = arm720t_command_handlers,
590 .target_create = arm720t_target_create,
591 .init_target = arm720t_init_target,
592 .examine = arm7_9_examine,
593 .check_reset = arm7_9_check_reset,
594 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)