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

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)