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

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)