target: no implicit #includes of "register.h"
[openocd.git] / src / target / armv7m.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2006 by Magnus Lundin *
6 * lundin@mlu.mine.nu *
7 * *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
10 * *
11 * Copyright (C) 2007,2008 Øyvind Harboe *
12 * oyvind.harboe@zylin.com *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28 * *
29 * ARMv7-M Architecture, Application Level Reference Manual *
30 * ARM DDI 0405C (September 2008) *
31 * *
32 ***************************************************************************/
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "breakpoints.h"
38 #include "armv7m.h"
39 #include "algorithm.h"
40 #include "register.h"
41
42 #define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
43
44
45 #if 0
46 #define _DEBUG_INSTRUCTION_EXECUTION_
47 #endif
48
49 /** Maps from enum armv7m_mode (except ARMV7M_MODE_ANY) to name. */
50 char *armv7m_mode_strings[] =
51 {
52 "Thread", "Thread (User)", "Handler",
53 };
54
55 static char *armv7m_exception_strings[] =
56 {
57 "", "Reset", "NMI", "HardFault",
58 "MemManage", "BusFault", "UsageFault", "RESERVED",
59 "RESERVED", "RESERVED", "RESERVED", "SVCall",
60 "DebugMonitor", "RESERVED", "PendSV", "SysTick"
61 };
62
63 /* FIXME these dummies are IDENTICAL to the armv4_5, arm11, and armv7a
64 * ones... except for naming/scoping
65 */
66 static uint8_t armv7m_gdb_dummy_fp_value[12];
67
68 static struct reg armv7m_gdb_dummy_fp_reg =
69 {
70 .name = "GDB dummy floating-point register",
71 .value = armv7m_gdb_dummy_fp_value,
72 .dirty = 0,
73 .valid = 1,
74 .size = 96,
75 .arch_info = NULL,
76 .arch_type = 0,
77 };
78
79 static uint8_t armv7m_gdb_dummy_fps_value[4];
80
81 static struct reg armv7m_gdb_dummy_fps_reg =
82 {
83 .name = "GDB dummy floating-point status register",
84 .value = armv7m_gdb_dummy_fps_value,
85 .dirty = 0,
86 .valid = 1,
87 .size = 32,
88 .arch_info = NULL,
89 .arch_type = 0,
90 };
91
92 #ifdef ARMV7_GDB_HACKS
93 uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
94
95 struct reg armv7m_gdb_dummy_cpsr_reg =
96 {
97 .name = "GDB dummy cpsr register",
98 .value = armv7m_gdb_dummy_cpsr_value,
99 .dirty = 0,
100 .valid = 1,
101 .size = 32,
102 .arch_info = NULL,
103 .arch_type = 0,
104 };
105 #endif
106
107 /*
108 * These registers are not memory-mapped. The ARMv7-M profile includes
109 * memory mapped registers too, such as for the NVIC (interrupt controller)
110 * and SysTick (timer) modules; those can mostly be treated as peripherals.
111 *
112 * The ARMv6-M profile is almost identical in this respect, except that it
113 * doesn't include basepri or faultmask registers.
114 */
115 static const struct {
116 unsigned id;
117 char *name;
118 unsigned bits;
119 } armv7m_regs[] = {
120 { ARMV7M_R0, "r0", 32 },
121 { ARMV7M_R1, "r1", 32 },
122 { ARMV7M_R2, "r2", 32 },
123 { ARMV7M_R3, "r3", 32 },
124
125 { ARMV7M_R4, "r4", 32 },
126 { ARMV7M_R5, "r5", 32 },
127 { ARMV7M_R6, "r6", 32 },
128 { ARMV7M_R7, "r7", 32 },
129
130 { ARMV7M_R8, "r8", 32 },
131 { ARMV7M_R9, "r9", 32 },
132 { ARMV7M_R10, "r10", 32 },
133 { ARMV7M_R11, "r11", 32 },
134
135 { ARMV7M_R12, "r12", 32 },
136 { ARMV7M_R13, "sp", 32 },
137 { ARMV7M_R14, "lr", 32 },
138 { ARMV7M_PC, "pc", 32 },
139
140 { ARMV7M_xPSR, "xPSR", 32 },
141 { ARMV7M_MSP, "msp", 32 },
142 { ARMV7M_PSP, "psp", 32 },
143
144 { ARMV7M_PRIMASK, "primask", 1 },
145 { ARMV7M_BASEPRI, "basepri", 8 },
146 { ARMV7M_FAULTMASK, "faultmask", 1 },
147 { ARMV7M_CONTROL, "control", 2 },
148 };
149
150 #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
151
152 static int armv7m_core_reg_arch_type = -1;
153
154 /**
155 * Restores target context using the cache of core registers set up
156 * by armv7m_build_reg_cache(), calling optional core-specific hooks.
157 */
158 int armv7m_restore_context(struct target *target)
159 {
160 int i;
161 struct armv7m_common *armv7m = target_to_armv7m(target);
162
163 LOG_DEBUG(" ");
164
165 if (armv7m->pre_restore_context)
166 armv7m->pre_restore_context(target);
167
168 for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
169 {
170 if (armv7m->core_cache->reg_list[i].dirty)
171 {
172 armv7m->write_core_reg(target, i);
173 }
174 }
175
176 if (armv7m->post_restore_context)
177 armv7m->post_restore_context(target);
178
179 return ERROR_OK;
180 }
181
182 /* Core state functions */
183
184 /**
185 * Maps ISR number (from xPSR) to name.
186 * Note that while names and meanings for the first sixteen are standardized
187 * (with zero not a true exception), external interrupts are only numbered.
188 * They are assigned by vendors, which generally assign different numbers to
189 * peripherals (such as UART0 or a USB peripheral controller).
190 */
191 char *armv7m_exception_string(int number)
192 {
193 static char enamebuf[32];
194
195 if ((number < 0) | (number > 511))
196 return "Invalid exception";
197 if (number < 16)
198 return armv7m_exception_strings[number];
199 sprintf(enamebuf, "External Interrupt(%i)", number - 16);
200 return enamebuf;
201 }
202
203 static int armv7m_get_core_reg(struct reg *reg)
204 {
205 int retval;
206 struct armv7m_core_reg *armv7m_reg = reg->arch_info;
207 struct target *target = armv7m_reg->target;
208 struct armv7m_common *armv7m = target_to_armv7m(target);
209
210 if (target->state != TARGET_HALTED)
211 {
212 return ERROR_TARGET_NOT_HALTED;
213 }
214
215 retval = armv7m->read_core_reg(target, armv7m_reg->num);
216
217 return retval;
218 }
219
220 static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
221 {
222 struct armv7m_core_reg *armv7m_reg = reg->arch_info;
223 struct target *target = armv7m_reg->target;
224 uint32_t value = buf_get_u32(buf, 0, 32);
225
226 if (target->state != TARGET_HALTED)
227 {
228 return ERROR_TARGET_NOT_HALTED;
229 }
230
231 buf_set_u32(reg->value, 0, 32, value);
232 reg->dirty = 1;
233 reg->valid = 1;
234
235 return ERROR_OK;
236 }
237
238 static int armv7m_read_core_reg(struct target *target, int num)
239 {
240 uint32_t reg_value;
241 int retval;
242 struct armv7m_core_reg * armv7m_core_reg;
243 struct armv7m_common *armv7m = target_to_armv7m(target);
244
245 if ((num < 0) || (num >= ARMV7M_NUM_REGS))
246 return ERROR_INVALID_ARGUMENTS;
247
248 armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
249 retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, &reg_value);
250 buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
251 armv7m->core_cache->reg_list[num].valid = 1;
252 armv7m->core_cache->reg_list[num].dirty = 0;
253
254 return retval;
255 }
256
257 static int armv7m_write_core_reg(struct target *target, int num)
258 {
259 int retval;
260 uint32_t reg_value;
261 struct armv7m_core_reg *armv7m_core_reg;
262 struct armv7m_common *armv7m = target_to_armv7m(target);
263
264 if ((num < 0) || (num >= ARMV7M_NUM_REGS))
265 return ERROR_INVALID_ARGUMENTS;
266
267 reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
268 armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
269 retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value);
270 if (retval != ERROR_OK)
271 {
272 LOG_ERROR("JTAG failure");
273 armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
274 return ERROR_JTAG_DEVICE_ERROR;
275 }
276 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
277 armv7m->core_cache->reg_list[num].valid = 1;
278 armv7m->core_cache->reg_list[num].dirty = 0;
279
280 return ERROR_OK;
281 }
282
283 /** Invalidates cache of core registers set up by armv7m_build_reg_cache(). */
284 int armv7m_invalidate_core_regs(struct target *target)
285 {
286 struct armv7m_common *armv7m = target_to_armv7m(target);
287 int i;
288
289 for (i = 0; i < armv7m->core_cache->num_regs; i++)
290 {
291 armv7m->core_cache->reg_list[i].valid = 0;
292 armv7m->core_cache->reg_list[i].dirty = 0;
293 }
294
295 return ERROR_OK;
296 }
297
298 /**
299 * Returns generic ARM userspace registers to GDB.
300 * GDB doesn't quite understand that most ARMs don't have floating point
301 * hardware, so this also fakes a set of long-obsolete FPA registers that
302 * are not used in EABI based software stacks.
303 */
304 int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
305 {
306 struct armv7m_common *armv7m = target_to_armv7m(target);
307 int i;
308
309 *reg_list_size = 26;
310 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
311
312 /*
313 * GDB register packet format for ARM:
314 * - the first 16 registers are r0..r15
315 * - (obsolete) 8 FPA registers
316 * - (obsolete) FPA status
317 * - CPSR
318 */
319 for (i = 0; i < 16; i++)
320 {
321 (*reg_list)[i] = &armv7m->core_cache->reg_list[i];
322 }
323
324 for (i = 16; i < 24; i++)
325 {
326 (*reg_list)[i] = &armv7m_gdb_dummy_fp_reg;
327 }
328
329 (*reg_list)[24] = &armv7m_gdb_dummy_fps_reg;
330
331 #ifdef ARMV7_GDB_HACKS
332 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
333 (*reg_list)[25] = &armv7m_gdb_dummy_cpsr_reg;
334
335 /* ARMV7M is always in thumb mode, try to make GDB understand this
336 * if it does not support this arch */
337 *((char*)armv7m->core_cache->reg_list[15].value) |= 1;
338 #else
339 (*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR];
340 #endif
341
342 return ERROR_OK;
343 }
344
345 /* run to exit point. return error if exit point was not reached. */
346 static int armv7m_run_and_wait(struct target *target, uint32_t entry_point, int timeout_ms, uint32_t exit_point, struct armv7m_common *armv7m)
347 {
348 uint32_t pc;
349 int retval;
350 /* This code relies on the target specific resume() and poll()->debug_entry()
351 * sequence to write register values to the processor and the read them back */
352 if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
353 {
354 return retval;
355 }
356
357 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
358 /* If the target fails to halt due to the breakpoint, force a halt */
359 if (retval != ERROR_OK || target->state != TARGET_HALTED)
360 {
361 if ((retval = target_halt(target)) != ERROR_OK)
362 return retval;
363 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
364 {
365 return retval;
366 }
367 return ERROR_TARGET_TIMEOUT;
368 }
369
370 armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
371 if (pc != exit_point)
372 {
373 LOG_DEBUG("failed algoritm halted at 0x%" PRIx32 " ", pc);
374 return ERROR_TARGET_TIMEOUT;
375 }
376
377 return ERROR_OK;
378 }
379
380 /** Runs a Thumb algorithm in the target. */
381 int armv7m_run_algorithm(struct target *target,
382 int num_mem_params, struct mem_param *mem_params,
383 int num_reg_params, struct reg_param *reg_params,
384 uint32_t entry_point, uint32_t exit_point,
385 int timeout_ms, void *arch_info)
386 {
387 struct armv7m_common *armv7m = target_to_armv7m(target);
388 struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
389 enum armv7m_mode core_mode = armv7m->core_mode;
390 int retval = ERROR_OK;
391 int i;
392 uint32_t context[ARMV7M_NUM_REGS];
393
394 if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
395 {
396 LOG_ERROR("current target isn't an ARMV7M target");
397 return ERROR_TARGET_INVALID;
398 }
399
400 if (target->state != TARGET_HALTED)
401 {
402 LOG_WARNING("target not halted");
403 return ERROR_TARGET_NOT_HALTED;
404 }
405
406 /* refresh core register cache */
407 /* Not needed if core register cache is always consistent with target process state */
408 for (i = 0; i < ARMV7M_NUM_REGS; i++)
409 {
410 if (!armv7m->core_cache->reg_list[i].valid)
411 armv7m->read_core_reg(target, i);
412 context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
413 }
414
415 for (i = 0; i < num_mem_params; i++)
416 {
417 if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
418 return retval;
419 }
420
421 for (i = 0; i < num_reg_params; i++)
422 {
423 struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
424 // uint32_t regvalue;
425
426 if (!reg)
427 {
428 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
429 exit(-1);
430 }
431
432 if (reg->size != reg_params[i].size)
433 {
434 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
435 exit(-1);
436 }
437
438 // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
439 armv7m_set_core_reg(reg, reg_params[i].value);
440 }
441
442 if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
443 {
444 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
445 buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value,
446 0, 1, armv7m_algorithm_info->core_mode);
447 armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
448 armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
449 }
450
451 /* REVISIT speed things up (3% or so in one case) by requiring
452 * algorithms to include a BKPT instruction at each exit point.
453 * This eliminates overheads of adding/removing a breakpoint.
454 */
455
456 /* ARMV7M always runs in Thumb state */
457 if ((retval = breakpoint_add(target, exit_point, 2, BKPT_SOFT)) != ERROR_OK)
458 {
459 LOG_ERROR("can't add breakpoint to finish algorithm execution");
460 return ERROR_TARGET_FAILURE;
461 }
462
463 retval = armv7m_run_and_wait(target, entry_point, timeout_ms, exit_point, armv7m);
464
465 breakpoint_remove(target, exit_point);
466
467 if (retval != ERROR_OK)
468 {
469 return retval;
470 }
471
472 /* Read memory values to mem_params[] */
473 for (i = 0; i < num_mem_params; i++)
474 {
475 if (mem_params[i].direction != PARAM_OUT)
476 if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
477 {
478 return retval;
479 }
480 }
481
482 /* Copy core register values to reg_params[] */
483 for (i = 0; i < num_reg_params; i++)
484 {
485 if (reg_params[i].direction != PARAM_OUT)
486 {
487 struct reg *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
488
489 if (!reg)
490 {
491 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
492 exit(-1);
493 }
494
495 if (reg->size != reg_params[i].size)
496 {
497 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
498 exit(-1);
499 }
500
501 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
502 }
503 }
504
505 for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--)
506 {
507 uint32_t regvalue;
508 regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
509 if (regvalue != context[i])
510 {
511 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
512 armv7m->core_cache->reg_list[i].name, context[i]);
513 buf_set_u32(armv7m->core_cache->reg_list[i].value,
514 0, 32, context[i]);
515 armv7m->core_cache->reg_list[i].valid = 1;
516 armv7m->core_cache->reg_list[i].dirty = 1;
517 }
518 }
519
520 armv7m->core_mode = core_mode;
521
522 return retval;
523 }
524
525 /** Logs summary of ARMv7-M state for a halted target. */
526 int armv7m_arch_state(struct target *target)
527 {
528 struct armv7m_common *armv7m = target_to_armv7m(target);
529 uint32_t ctrl, sp;
530
531 ctrl = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
532 sp = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
533
534 LOG_USER("target halted due to %s, current mode: %s %s\n"
535 "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32,
536 Jim_Nvp_value2name_simple(nvp_target_debug_reason,
537 target->debug_reason)->name,
538 armv7m_mode_strings[armv7m->core_mode],
539 armv7m_exception_string(armv7m->exception_number),
540 buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
541 buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_PC].value, 0, 32),
542 (ctrl & 0x02) ? 'p' : 'm',
543 sp);
544
545 return ERROR_OK;
546 }
547
548 /** Builds cache of architecturally defined registers. */
549 struct reg_cache *armv7m_build_reg_cache(struct target *target)
550 {
551 struct armv7m_common *armv7m = target_to_armv7m(target);
552 int num_regs = ARMV7M_NUM_REGS;
553 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
554 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
555 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
556 struct armv7m_core_reg *arch_info = calloc(num_regs, sizeof(struct armv7m_core_reg));
557 int i;
558
559 if (armv7m_core_reg_arch_type == -1)
560 {
561 armv7m_core_reg_arch_type = register_reg_arch_type(armv7m_get_core_reg, armv7m_set_core_reg);
562 }
563
564 register_init_dummy(&armv7m_gdb_dummy_fps_reg);
565 #ifdef ARMV7_GDB_HACKS
566 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg);
567 #endif
568 register_init_dummy(&armv7m_gdb_dummy_fp_reg);
569
570 /* Build the process context cache */
571 cache->name = "arm v7m registers";
572 cache->next = NULL;
573 cache->reg_list = reg_list;
574 cache->num_regs = num_regs;
575 (*cache_p) = cache;
576 armv7m->core_cache = cache;
577
578 for (i = 0; i < num_regs; i++)
579 {
580 arch_info[i].num = armv7m_regs[i].id;
581 arch_info[i].target = target;
582 arch_info[i].armv7m_common = armv7m;
583 reg_list[i].name = armv7m_regs[i].name;
584 reg_list[i].size = armv7m_regs[i].bits;
585 reg_list[i].value = calloc(1, 4);
586 reg_list[i].dirty = 0;
587 reg_list[i].valid = 0;
588 reg_list[i].arch_type = armv7m_core_reg_arch_type;
589 reg_list[i].arch_info = &arch_info[i];
590 }
591
592 return cache;
593 }
594
595 /** Sets up target as a generic ARMv7-M core */
596 int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
597 {
598 /* register arch-specific functions */
599
600 target->arch_info = armv7m;
601 armv7m->read_core_reg = armv7m_read_core_reg;
602 armv7m->write_core_reg = armv7m_write_core_reg;
603
604 return ERROR_OK;
605 }
606
607 /** Generates a CRC32 checksum of a memory region. */
608 int armv7m_checksum_memory(struct target *target,
609 uint32_t address, uint32_t count, uint32_t* checksum)
610 {
611 struct working_area *crc_algorithm;
612 struct armv7m_algorithm armv7m_info;
613 struct reg_param reg_params[2];
614 int retval;
615
616 static const uint16_t cortex_m3_crc_code[] = {
617 0x4602, /* mov r2, r0 */
618 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
619 0x460B, /* mov r3, r1 */
620 0xF04F, 0x0400, /* mov r4, #0 */
621 0xE013, /* b ncomp */
622 /* nbyte: */
623 0x5D11, /* ldrb r1, [r2, r4] */
624 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
625 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
626
627 0xF04F, 0x0500, /* mov r5, #0 */
628 /* loop: */
629 0x2800, /* cmp r0, #0 */
630 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
631 0xF105, 0x0501, /* add r5, r5, #1 */
632 0x4630, /* mov r0, r6 */
633 0xBFB8, /* it lt */
634 0xEA86, 0x0007, /* eor r0, r6, r7 */
635 0x2D08, /* cmp r5, #8 */
636 0xD1F4, /* bne loop */
637
638 0xF104, 0x0401, /* add r4, r4, #1 */
639 /* ncomp: */
640 0x429C, /* cmp r4, r3 */
641 0xD1E9, /* bne nbyte */
642 /* end: */
643 0xE7FE, /* b end */
644 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
645 };
646
647 uint32_t i;
648
649 if (target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm) != ERROR_OK)
650 {
651 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
652 }
653
654 /* convert flash writing code into a buffer in target endianness */
655 for (i = 0; i < (sizeof(cortex_m3_crc_code)/sizeof(uint16_t)); i++)
656 if ((retval = target_write_u16(target, crc_algorithm->address + i*sizeof(uint16_t), cortex_m3_crc_code[i])) != ERROR_OK)
657 {
658 return retval;
659 }
660
661 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
662 armv7m_info.core_mode = ARMV7M_MODE_ANY;
663
664 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
665 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
666
667 buf_set_u32(reg_params[0].value, 0, 32, address);
668 buf_set_u32(reg_params[1].value, 0, 32, count);
669
670 if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
671 crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code)-6), 20000, &armv7m_info)) != ERROR_OK)
672 {
673 LOG_ERROR("error executing cortex_m3 crc algorithm");
674 destroy_reg_param(&reg_params[0]);
675 destroy_reg_param(&reg_params[1]);
676 target_free_working_area(target, crc_algorithm);
677 return retval;
678 }
679
680 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
681
682 destroy_reg_param(&reg_params[0]);
683 destroy_reg_param(&reg_params[1]);
684
685 target_free_working_area(target, crc_algorithm);
686
687 return ERROR_OK;
688 }
689
690 /** Checks whether a memory region is zeroed. */
691 int armv7m_blank_check_memory(struct target *target,
692 uint32_t address, uint32_t count, uint32_t* blank)
693 {
694 struct working_area *erase_check_algorithm;
695 struct reg_param reg_params[3];
696 struct armv7m_algorithm armv7m_info;
697 int retval;
698 uint32_t i;
699
700 static const uint16_t erase_check_code[] =
701 {
702 /* loop: */
703 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
704 0xEA02, 0x0203, /* and r2, r2, r3 */
705 0x3901, /* subs r1, r1, #1 */
706 0xD1F9, /* bne loop */
707 /* end: */
708 0xE7FE, /* b end */
709 };
710
711 /* make sure we have a working area */
712 if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
713 {
714 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
715 }
716
717 /* convert flash writing code into a buffer in target endianness */
718 for (i = 0; i < (sizeof(erase_check_code)/sizeof(uint16_t)); i++)
719 target_write_u16(target, erase_check_algorithm->address + i*sizeof(uint16_t), erase_check_code[i]);
720
721 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
722 armv7m_info.core_mode = ARMV7M_MODE_ANY;
723
724 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
725 buf_set_u32(reg_params[0].value, 0, 32, address);
726
727 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
728 buf_set_u32(reg_params[1].value, 0, 32, count);
729
730 init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
731 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
732
733 if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
734 erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code)-2), 10000, &armv7m_info)) != ERROR_OK)
735 {
736 destroy_reg_param(&reg_params[0]);
737 destroy_reg_param(&reg_params[1]);
738 destroy_reg_param(&reg_params[2]);
739 target_free_working_area(target, erase_check_algorithm);
740 return 0;
741 }
742
743 *blank = buf_get_u32(reg_params[2].value, 0, 32);
744
745 destroy_reg_param(&reg_params[0]);
746 destroy_reg_param(&reg_params[1]);
747 destroy_reg_param(&reg_params[2]);
748
749 target_free_working_area(target, erase_check_algorithm);
750
751 return ERROR_OK;
752 }
753
754 /*--------------------------------------------------------------------------*/
755
756 /*
757 * Only stuff below this line should need to verify that its target
758 * is an ARMv7-M node.
759 *
760 * FIXME yet none of it _does_ verify target types yet!
761 */
762
763
764 /*
765 * Return the debug ap baseaddress in hexadecimal;
766 * no extra output to simplify script processing
767 */
768 COMMAND_HANDLER(handle_dap_baseaddr_command)
769 {
770 struct target *target = get_current_target(cmd_ctx);
771 struct armv7m_common *armv7m = target_to_armv7m(target);
772 struct swjdp_common *swjdp = &armv7m->swjdp_info;
773 uint32_t apsel, apselsave, baseaddr;
774 int retval;
775
776 apselsave = swjdp->apsel;
777 switch (argc) {
778 case 0:
779 apsel = swjdp->apsel;
780 break;
781 case 1:
782 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
783 break;
784 default:
785 return ERROR_COMMAND_SYNTAX_ERROR;
786 }
787
788 if (apselsave != apsel)
789 dap_ap_select(swjdp, apsel);
790
791 dap_ap_read_reg_u32(swjdp, 0xF8, &baseaddr);
792 retval = swjdp_transaction_endcheck(swjdp);
793 command_print(cmd_ctx, "0x%8.8" PRIx32 "", baseaddr);
794
795 if (apselsave != apsel)
796 dap_ap_select(swjdp, apselsave);
797
798 return retval;
799 }
800
801 /*
802 * Return the debug ap id in hexadecimal;
803 * no extra output to simplify script processing
804 */
805 COMMAND_HANDLER(handle_dap_apid_command)
806 {
807 struct target *target = get_current_target(cmd_ctx);
808 struct armv7m_common *armv7m = target_to_armv7m(target);
809 struct swjdp_common *swjdp = &armv7m->swjdp_info;
810
811 return CALL_COMMAND_HANDLER(dap_apid_command, swjdp);
812 }
813
814 COMMAND_HANDLER(handle_dap_apsel_command)
815 {
816 struct target *target = get_current_target(cmd_ctx);
817 struct armv7m_common *armv7m = target_to_armv7m(target);
818 struct swjdp_common *swjdp = &armv7m->swjdp_info;
819
820 return CALL_COMMAND_HANDLER(dap_apsel_command, swjdp);
821 }
822
823 COMMAND_HANDLER(handle_dap_memaccess_command)
824 {
825 struct target *target = get_current_target(cmd_ctx);
826 struct armv7m_common *armv7m = target_to_armv7m(target);
827 struct swjdp_common *swjdp = &armv7m->swjdp_info;
828
829 return CALL_COMMAND_HANDLER(dap_memaccess_command, swjdp);
830 }
831
832
833 COMMAND_HANDLER(handle_dap_info_command)
834 {
835 struct target *target = get_current_target(cmd_ctx);
836 struct armv7m_common *armv7m = target_to_armv7m(target);
837 struct swjdp_common *swjdp = &armv7m->swjdp_info;
838 uint32_t apsel;
839
840 switch (argc) {
841 case 0:
842 apsel = swjdp->apsel;
843 break;
844 case 1:
845 COMMAND_PARSE_NUMBER(u32, args[0], apsel);
846 break;
847 default:
848 return ERROR_COMMAND_SYNTAX_ERROR;
849 }
850
851 return dap_info_command(cmd_ctx, swjdp, apsel);
852 }
853
854 /** Registers commands used to access DAP resources. */
855 int armv7m_register_commands(struct command_context *cmd_ctx)
856 {
857 struct command *arm_adi_v5_dap_cmd;
858
859 arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap",
860 NULL, COMMAND_ANY,
861 "cortex dap specific commands");
862
863 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info",
864 handle_dap_info_command, COMMAND_EXEC,
865 "Displays dap info for ap [num],"
866 "default currently selected AP");
867 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel",
868 handle_dap_apsel_command, COMMAND_EXEC,
869 "Select a different AP [num] (default 0)");
870 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid",
871 handle_dap_apid_command, COMMAND_EXEC,
872 "Displays id reg from AP [num], "
873 "default currently selected AP");
874 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr",
875 handle_dap_baseaddr_command, COMMAND_EXEC,
876 "Displays debug base address from AP [num],"
877 "default currently selected AP");
878 register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess",
879 handle_dap_memaccess_command, COMMAND_EXEC,
880 "set/get number of extra tck for mem-ap "
881 "memory bus access [0-255]");
882
883 return ERROR_OK;
884 }

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)