d32352a75c7eeccf11021e15014c41560879519a
[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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
28 * *
29 * ARMv7-M Architecture, Application Level Reference Manual *
30 * ARM DDI 0405C (September 2008) *
31 * *
32 ***************************************************************************/
33
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37
38 #include "breakpoints.h"
39 #include "armv7m.h"
40 #include "algorithm.h"
41 #include "register.h"
42
43 #if 0
44 #define _DEBUG_INSTRUCTION_EXECUTION_
45 #endif
46
47 static char *armv7m_exception_strings[] = {
48 "", "Reset", "NMI", "HardFault",
49 "MemManage", "BusFault", "UsageFault", "RESERVED",
50 "RESERVED", "RESERVED", "RESERVED", "SVCall",
51 "DebugMonitor", "RESERVED", "PendSV", "SysTick"
52 };
53
54 /* PSP is used in some thread modes */
55 const int armv7m_psp_reg_map[17] = {
56 ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
57 ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
58 ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
59 ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
60 ARMV7M_xPSR,
61 };
62
63 /* MSP is used in handler and some thread modes */
64 const int armv7m_msp_reg_map[17] = {
65 ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
66 ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
67 ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
68 ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
69 ARMV7M_xPSR,
70 };
71
72 #ifdef ARMV7_GDB_HACKS
73 uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
74
75 struct reg armv7m_gdb_dummy_cpsr_reg = {
76 .name = "GDB dummy cpsr register",
77 .value = armv7m_gdb_dummy_cpsr_value,
78 .dirty = 0,
79 .valid = 1,
80 .size = 32,
81 .arch_info = NULL,
82 };
83 #endif
84
85 /*
86 * These registers are not memory-mapped. The ARMv7-M profile includes
87 * memory mapped registers too, such as for the NVIC (interrupt controller)
88 * and SysTick (timer) modules; those can mostly be treated as peripherals.
89 *
90 * The ARMv6-M profile is almost identical in this respect, except that it
91 * doesn't include basepri or faultmask registers.
92 */
93 static const struct {
94 unsigned id;
95 const char *name;
96 unsigned bits;
97 } armv7m_regs[] = {
98 { ARMV7M_R0, "r0", 32 },
99 { ARMV7M_R1, "r1", 32 },
100 { ARMV7M_R2, "r2", 32 },
101 { ARMV7M_R3, "r3", 32 },
102
103 { ARMV7M_R4, "r4", 32 },
104 { ARMV7M_R5, "r5", 32 },
105 { ARMV7M_R6, "r6", 32 },
106 { ARMV7M_R7, "r7", 32 },
107
108 { ARMV7M_R8, "r8", 32 },
109 { ARMV7M_R9, "r9", 32 },
110 { ARMV7M_R10, "r10", 32 },
111 { ARMV7M_R11, "r11", 32 },
112
113 { ARMV7M_R12, "r12", 32 },
114 { ARMV7M_R13, "sp", 32 },
115 { ARMV7M_R14, "lr", 32 },
116 { ARMV7M_PC, "pc", 32 },
117
118 { ARMV7M_xPSR, "xPSR", 32 },
119 { ARMV7M_MSP, "msp", 32 },
120 { ARMV7M_PSP, "psp", 32 },
121
122 { ARMV7M_PRIMASK, "primask", 1 },
123 { ARMV7M_BASEPRI, "basepri", 8 },
124 { ARMV7M_FAULTMASK, "faultmask", 1 },
125 { ARMV7M_CONTROL, "control", 2 },
126 };
127
128 #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
129
130 /**
131 * Restores target context using the cache of core registers set up
132 * by armv7m_build_reg_cache(), calling optional core-specific hooks.
133 */
134 int armv7m_restore_context(struct target *target)
135 {
136 int i;
137 struct armv7m_common *armv7m = target_to_armv7m(target);
138 struct reg_cache *cache = armv7m->arm.core_cache;
139
140 LOG_DEBUG(" ");
141
142 if (armv7m->pre_restore_context)
143 armv7m->pre_restore_context(target);
144
145 for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
146 if (cache->reg_list[i].dirty) {
147 uint32_t value = buf_get_u32(cache->reg_list[i].value, 0, 32);
148 armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, ARM_MODE_ANY, value);
149 }
150 }
151
152 return ERROR_OK;
153 }
154
155 /* Core state functions */
156
157 /**
158 * Maps ISR number (from xPSR) to name.
159 * Note that while names and meanings for the first sixteen are standardized
160 * (with zero not a true exception), external interrupts are only numbered.
161 * They are assigned by vendors, which generally assign different numbers to
162 * peripherals (such as UART0 or a USB peripheral controller).
163 */
164 char *armv7m_exception_string(int number)
165 {
166 static char enamebuf[32];
167
168 if ((number < 0) | (number > 511))
169 return "Invalid exception";
170 if (number < 16)
171 return armv7m_exception_strings[number];
172 sprintf(enamebuf, "External Interrupt(%i)", number - 16);
173 return enamebuf;
174 }
175
176 static int armv7m_get_core_reg(struct reg *reg)
177 {
178 int retval;
179 struct arm_reg *armv7m_reg = reg->arch_info;
180 struct target *target = armv7m_reg->target;
181 struct arm *arm = target_to_arm(target);
182
183 if (target->state != TARGET_HALTED)
184 return ERROR_TARGET_NOT_HALTED;
185
186 retval = arm->read_core_reg(target, reg, armv7m_reg->num, arm->core_mode);
187
188 return retval;
189 }
190
191 static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
192 {
193 struct arm_reg *armv7m_reg = reg->arch_info;
194 struct target *target = armv7m_reg->target;
195 uint32_t value = buf_get_u32(buf, 0, 32);
196
197 if (target->state != TARGET_HALTED)
198 return ERROR_TARGET_NOT_HALTED;
199
200 buf_set_u32(reg->value, 0, 32, value);
201 reg->dirty = 1;
202 reg->valid = 1;
203
204 return ERROR_OK;
205 }
206
207 static int armv7m_read_core_reg(struct target *target, struct reg *r,
208 int num, enum arm_mode mode)
209 {
210 uint32_t reg_value;
211 int retval;
212 struct arm_reg *armv7m_core_reg;
213 struct armv7m_common *armv7m = target_to_armv7m(target);
214
215 assert(num < (int)armv7m->arm.core_cache->num_regs);
216
217 armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
218 retval = armv7m->load_core_reg_u32(target,
219 armv7m_core_reg->num, &reg_value);
220
221 buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
222 armv7m->arm.core_cache->reg_list[num].valid = 1;
223 armv7m->arm.core_cache->reg_list[num].dirty = 0;
224
225 return retval;
226 }
227
228 static int armv7m_write_core_reg(struct target *target, struct reg *r,
229 int num, enum arm_mode mode, uint32_t value)
230 {
231 int retval;
232 uint32_t reg_value;
233 struct arm_reg *armv7m_core_reg;
234 struct armv7m_common *armv7m = target_to_armv7m(target);
235
236 assert(num < (int)armv7m->arm.core_cache->num_regs);
237
238 reg_value = buf_get_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32);
239 armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
240 retval = armv7m->store_core_reg_u32(target,
241 armv7m_core_reg->num,
242 reg_value);
243 if (retval != ERROR_OK) {
244 LOG_ERROR("JTAG failure");
245 armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
246 return ERROR_JTAG_DEVICE_ERROR;
247 }
248
249 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
250 armv7m->arm.core_cache->reg_list[num].valid = 1;
251 armv7m->arm.core_cache->reg_list[num].dirty = 0;
252
253 return ERROR_OK;
254 }
255
256 /**
257 * Returns generic ARM userspace registers to GDB.
258 * GDB doesn't quite understand that most ARMs don't have floating point
259 * hardware, so this also fakes a set of long-obsolete FPA registers that
260 * are not used in EABI based software stacks.
261 */
262 int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
263 int *reg_list_size, enum target_register_class reg_class)
264 {
265 struct armv7m_common *armv7m = target_to_armv7m(target);
266 int i;
267
268 *reg_list_size = 26;
269 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
270
271 /*
272 * GDB register packet format for ARM:
273 * - the first 16 registers are r0..r15
274 * - (obsolete) 8 FPA registers
275 * - (obsolete) FPA status
276 * - CPSR
277 */
278 for (i = 0; i < 16; i++)
279 (*reg_list)[i] = &armv7m->arm.core_cache->reg_list[i];
280
281 for (i = 16; i < 24; i++)
282 (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
283 (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
284
285 #ifdef ARMV7_GDB_HACKS
286 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
287 (*reg_list)[25] = &armv7m_gdb_dummy_cpsr_reg;
288
289 /* ARMV7M is always in thumb mode, try to make GDB understand this
290 * if it does not support this arch */
291 *((char *)armv7m->arm.pc->value) |= 1;
292 #else
293 (*reg_list)[25] = &armv7m->arm.core_cache->reg_list[ARMV7M_xPSR];
294 #endif
295
296 return ERROR_OK;
297 }
298
299 /** Runs a Thumb algorithm in the target. */
300 int armv7m_run_algorithm(struct target *target,
301 int num_mem_params, struct mem_param *mem_params,
302 int num_reg_params, struct reg_param *reg_params,
303 uint32_t entry_point, uint32_t exit_point,
304 int timeout_ms, void *arch_info)
305 {
306 int retval;
307
308 retval = armv7m_start_algorithm(target,
309 num_mem_params, mem_params,
310 num_reg_params, reg_params,
311 entry_point, exit_point,
312 arch_info);
313
314 if (retval == ERROR_OK)
315 retval = armv7m_wait_algorithm(target,
316 num_mem_params, mem_params,
317 num_reg_params, reg_params,
318 exit_point, timeout_ms,
319 arch_info);
320
321 return retval;
322 }
323
324 /** Starts a Thumb algorithm in the target. */
325 int armv7m_start_algorithm(struct target *target,
326 int num_mem_params, struct mem_param *mem_params,
327 int num_reg_params, struct reg_param *reg_params,
328 uint32_t entry_point, uint32_t exit_point,
329 void *arch_info)
330 {
331 struct armv7m_common *armv7m = target_to_armv7m(target);
332 struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
333 enum arm_mode core_mode = armv7m->arm.core_mode;
334 int retval = ERROR_OK;
335
336 /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
337 * at the exit point */
338
339 if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
340 LOG_ERROR("current target isn't an ARMV7M target");
341 return ERROR_TARGET_INVALID;
342 }
343
344 if (target->state != TARGET_HALTED) {
345 LOG_WARNING("target not halted");
346 return ERROR_TARGET_NOT_HALTED;
347 }
348
349 /* refresh core register cache
350 * Not needed if core register cache is always consistent with target process state */
351 for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++) {
352
353 armv7m_algorithm_info->context[i] = buf_get_u32(
354 armv7m->arm.core_cache->reg_list[i].value,
355 0,
356 32);
357 }
358
359 for (int i = 0; i < num_mem_params; i++) {
360 /* TODO: Write only out params */
361 retval = target_write_buffer(target, mem_params[i].address,
362 mem_params[i].size,
363 mem_params[i].value);
364 if (retval != ERROR_OK)
365 return retval;
366 }
367
368 for (int i = 0; i < num_reg_params; i++) {
369 struct reg *reg =
370 register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0);
371 /* uint32_t regvalue; */
372
373 if (!reg) {
374 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
375 return ERROR_COMMAND_SYNTAX_ERROR;
376 }
377
378 if (reg->size != reg_params[i].size) {
379 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
380 reg_params[i].reg_name);
381 return ERROR_COMMAND_SYNTAX_ERROR;
382 }
383
384 /* regvalue = buf_get_u32(reg_params[i].value, 0, 32); */
385 armv7m_set_core_reg(reg, reg_params[i].value);
386 }
387
388 if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
389 armv7m_algorithm_info->core_mode != core_mode) {
390
391 /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */
392 if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) {
393 armv7m_algorithm_info->core_mode = ARM_MODE_THREAD;
394 LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead");
395 }
396
397 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
398 buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
399 0, 1, armv7m_algorithm_info->core_mode);
400 armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
401 armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
402 }
403
404 /* save previous core mode */
405 armv7m_algorithm_info->core_mode = core_mode;
406
407 retval = target_resume(target, 0, entry_point, 1, 1);
408
409 return retval;
410 }
411
412 /** Waits for an algorithm in the target. */
413 int armv7m_wait_algorithm(struct target *target,
414 int num_mem_params, struct mem_param *mem_params,
415 int num_reg_params, struct reg_param *reg_params,
416 uint32_t exit_point, int timeout_ms,
417 void *arch_info)
418 {
419 struct armv7m_common *armv7m = target_to_armv7m(target);
420 struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
421 int retval = ERROR_OK;
422 uint32_t pc;
423
424 /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
425 * at the exit point */
426
427 if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
428 LOG_ERROR("current target isn't an ARMV7M target");
429 return ERROR_TARGET_INVALID;
430 }
431
432 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
433 /* If the target fails to halt due to the breakpoint, force a halt */
434 if (retval != ERROR_OK || target->state != TARGET_HALTED) {
435 retval = target_halt(target);
436 if (retval != ERROR_OK)
437 return retval;
438 retval = target_wait_state(target, TARGET_HALTED, 500);
439 if (retval != ERROR_OK)
440 return retval;
441 return ERROR_TARGET_TIMEOUT;
442 }
443
444 armv7m->load_core_reg_u32(target, 15, &pc);
445 if (exit_point && (pc != exit_point)) {
446 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32,
447 pc,
448 exit_point);
449 return ERROR_TARGET_TIMEOUT;
450 }
451
452 /* Read memory values to mem_params[] */
453 for (int i = 0; i < num_mem_params; i++) {
454 if (mem_params[i].direction != PARAM_OUT) {
455 retval = target_read_buffer(target, mem_params[i].address,
456 mem_params[i].size,
457 mem_params[i].value);
458 if (retval != ERROR_OK)
459 return retval;
460 }
461 }
462
463 /* Copy core register values to reg_params[] */
464 for (int i = 0; i < num_reg_params; i++) {
465 if (reg_params[i].direction != PARAM_OUT) {
466 struct reg *reg = register_get_by_name(armv7m->arm.core_cache,
467 reg_params[i].reg_name,
468 0);
469
470 if (!reg) {
471 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
472 return ERROR_COMMAND_SYNTAX_ERROR;
473 }
474
475 if (reg->size != reg_params[i].size) {
476 LOG_ERROR(
477 "BUG: register '%s' size doesn't match reg_params[i].size",
478 reg_params[i].reg_name);
479 return ERROR_COMMAND_SYNTAX_ERROR;
480 }
481
482 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
483 }
484 }
485
486 for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
487 uint32_t regvalue;
488 regvalue = buf_get_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32);
489 if (regvalue != armv7m_algorithm_info->context[i]) {
490 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
491 armv7m->arm.core_cache->reg_list[i].name,
492 armv7m_algorithm_info->context[i]);
493 buf_set_u32(armv7m->arm.core_cache->reg_list[i].value,
494 0, 32, armv7m_algorithm_info->context[i]);
495 armv7m->arm.core_cache->reg_list[i].valid = 1;
496 armv7m->arm.core_cache->reg_list[i].dirty = 1;
497 }
498 }
499
500 /* restore previous core mode */
501 if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) {
502 LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
503 buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
504 0, 1, armv7m_algorithm_info->core_mode);
505 armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
506 armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
507 }
508
509 armv7m->arm.core_mode = armv7m_algorithm_info->core_mode;
510
511 return retval;
512 }
513
514 /** Logs summary of ARMv7-M state for a halted target. */
515 int armv7m_arch_state(struct target *target)
516 {
517 struct armv7m_common *armv7m = target_to_armv7m(target);
518 struct arm *arm = &armv7m->arm;
519 uint32_t ctrl, sp;
520
521 ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
522 sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
523
524 LOG_USER("target halted due to %s, current mode: %s %s\n"
525 "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s",
526 debug_reason_name(target),
527 arm_mode_name(arm->core_mode),
528 armv7m_exception_string(armv7m->exception_number),
529 buf_get_u32(arm->cpsr->value, 0, 32),
530 buf_get_u32(arm->pc->value, 0, 32),
531 (ctrl & 0x02) ? 'p' : 'm',
532 sp,
533 arm->is_semihosting ? ", semihosting" : "");
534
535 return ERROR_OK;
536 }
537
538 static const struct reg_arch_type armv7m_reg_type = {
539 .get = armv7m_get_core_reg,
540 .set = armv7m_set_core_reg,
541 };
542
543 /** Builds cache of architecturally defined registers. */
544 struct reg_cache *armv7m_build_reg_cache(struct target *target)
545 {
546 struct armv7m_common *armv7m = target_to_armv7m(target);
547 struct arm *arm = &armv7m->arm;
548 int num_regs = ARMV7M_NUM_REGS;
549 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
550 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
551 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
552 struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
553 int i;
554
555 #ifdef ARMV7_GDB_HACKS
556 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg);
557 #endif
558
559 /* Build the process context cache */
560 cache->name = "arm v7m registers";
561 cache->next = NULL;
562 cache->reg_list = reg_list;
563 cache->num_regs = num_regs;
564 (*cache_p) = cache;
565
566 for (i = 0; i < num_regs; i++) {
567 arch_info[i].num = armv7m_regs[i].id;
568 arch_info[i].target = target;
569 arch_info[i].arm = arm;
570
571 reg_list[i].name = armv7m_regs[i].name;
572 reg_list[i].size = armv7m_regs[i].bits;
573 reg_list[i].value = calloc(1, 4);
574 reg_list[i].dirty = 0;
575 reg_list[i].valid = 0;
576 reg_list[i].type = &armv7m_reg_type;
577 reg_list[i].arch_info = &arch_info[i];
578 }
579
580 arm->cpsr = reg_list + ARMV7M_xPSR;
581 arm->pc = reg_list + ARMV7M_PC;
582 arm->core_cache = cache;
583 return cache;
584 }
585
586 static int armv7m_setup_semihosting(struct target *target, int enable)
587 {
588 /* nothing todo for armv7m */
589 return ERROR_OK;
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 struct arm *arm = &armv7m->arm;
596
597 armv7m->common_magic = ARMV7M_COMMON_MAGIC;
598 armv7m->fp_feature = FP_NONE;
599
600 arm->core_type = ARM_MODE_THREAD;
601 arm->arch_info = armv7m;
602 arm->setup_semihosting = armv7m_setup_semihosting;
603
604 arm->read_core_reg = armv7m_read_core_reg;
605 arm->write_core_reg = armv7m_write_core_reg;
606
607 return arm_init_arch_info(target, arm);
608 }
609
610 /** Generates a CRC32 checksum of a memory region. */
611 int armv7m_checksum_memory(struct target *target,
612 uint32_t address, uint32_t count, uint32_t *checksum)
613 {
614 struct working_area *crc_algorithm;
615 struct armv7m_algorithm armv7m_info;
616 struct reg_param reg_params[2];
617 int retval;
618
619 /* see contrib/loaders/checksum/armv7m_crc.s for src */
620
621 static const uint8_t cortex_m3_crc_code[] = {
622 /* main: */
623 0x02, 0x46, /* mov r2, r0 */
624 0x00, 0x20, /* movs r0, #0 */
625 0xC0, 0x43, /* mvns r0, r0 */
626 0x0A, 0x4E, /* ldr r6, CRC32XOR */
627 0x0B, 0x46, /* mov r3, r1 */
628 0x00, 0x24, /* movs r4, #0 */
629 0x0D, 0xE0, /* b ncomp */
630 /* nbyte: */
631 0x11, 0x5D, /* ldrb r1, [r2, r4] */
632 0x09, 0x06, /* lsls r1, r1, #24 */
633 0x48, 0x40, /* eors r0, r0, r1 */
634 0x00, 0x25, /* movs r5, #0 */
635 /* loop: */
636 0x00, 0x28, /* cmp r0, #0 */
637 0x02, 0xDA, /* bge notset */
638 0x40, 0x00, /* lsls r0, r0, #1 */
639 0x70, 0x40, /* eors r0, r0, r6 */
640 0x00, 0xE0, /* b cont */
641 /* notset: */
642 0x40, 0x00, /* lsls r0, r0, #1 */
643 /* cont: */
644 0x01, 0x35, /* adds r5, r5, #1 */
645 0x08, 0x2D, /* cmp r5, #8 */
646 0xF6, 0xD1, /* bne loop */
647 0x01, 0x34, /* adds r4, r4, #1 */
648 /* ncomp: */
649 0x9C, 0x42, /* cmp r4, r3 */
650 0xEF, 0xD1, /* bne nbyte */
651 0x00, 0xBE, /* bkpt #0 */
652 0xB7, 0x1D, 0xC1, 0x04 /* CRC32XOR: .word 0x04c11db7 */
653 };
654
655 retval = target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm);
656 if (retval != ERROR_OK)
657 return retval;
658
659 retval = target_write_buffer(target, crc_algorithm->address,
660 sizeof(cortex_m3_crc_code), (uint8_t *)cortex_m3_crc_code);
661 if (retval != ERROR_OK)
662 goto cleanup;
663
664 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
665 armv7m_info.core_mode = ARM_MODE_THREAD;
666
667 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
668 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
669
670 buf_set_u32(reg_params[0].value, 0, 32, address);
671 buf_set_u32(reg_params[1].value, 0, 32, count);
672
673 int timeout = 20000 * (1 + (count / (1024 * 1024)));
674
675 retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
676 crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6),
677 timeout, &armv7m_info);
678
679 if (retval == ERROR_OK)
680 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
681 else
682 LOG_ERROR("error executing cortex_m crc algorithm");
683
684 destroy_reg_param(&reg_params[0]);
685 destroy_reg_param(&reg_params[1]);
686
687 cleanup:
688 target_free_working_area(target, crc_algorithm);
689
690 return retval;
691 }
692
693 /** Checks whether a memory region is zeroed. */
694 int armv7m_blank_check_memory(struct target *target,
695 uint32_t address, uint32_t count, uint32_t *blank)
696 {
697 struct working_area *erase_check_algorithm;
698 struct reg_param reg_params[3];
699 struct armv7m_algorithm armv7m_info;
700 int retval;
701
702 /* see contrib/loaders/erase_check/armv7m_erase_check.s for src */
703
704 static const uint8_t erase_check_code[] = {
705 /* loop: */
706 0x03, 0x78, /* ldrb r3, [r0] */
707 0x01, 0x30, /* adds r0, #1 */
708 0x1A, 0x40, /* ands r2, r2, r3 */
709 0x01, 0x39, /* subs r1, r1, #1 */
710 0xFA, 0xD1, /* bne loop */
711 0x00, 0xBE /* bkpt #0 */
712 };
713
714 /* make sure we have a working area */
715 if (target_alloc_working_area(target, sizeof(erase_check_code),
716 &erase_check_algorithm) != ERROR_OK)
717 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
718
719 retval = target_write_buffer(target, erase_check_algorithm->address,
720 sizeof(erase_check_code), (uint8_t *)erase_check_code);
721 if (retval != ERROR_OK)
722 return retval;
723
724 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
725 armv7m_info.core_mode = ARM_MODE_THREAD;
726
727 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
728 buf_set_u32(reg_params[0].value, 0, 32, address);
729
730 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
731 buf_set_u32(reg_params[1].value, 0, 32, count);
732
733 init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
734 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
735
736 retval = target_run_algorithm(target,
737 0,
738 NULL,
739 3,
740 reg_params,
741 erase_check_algorithm->address,
742 erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
743 10000,
744 &armv7m_info);
745
746 if (retval == ERROR_OK)
747 *blank = buf_get_u32(reg_params[2].value, 0, 32);
748
749 destroy_reg_param(&reg_params[0]);
750 destroy_reg_param(&reg_params[1]);
751 destroy_reg_param(&reg_params[2]);
752
753 target_free_working_area(target, erase_check_algorithm);
754
755 return retval;
756 }
757
758 int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
759 {
760 struct armv7m_common *armv7m = target_to_armv7m(target);
761 struct reg *r = armv7m->arm.pc;
762 bool result = false;
763
764
765 /* if we halted last time due to a bkpt instruction
766 * then we have to manually step over it, otherwise
767 * the core will break again */
768
769 if (target->debug_reason == DBG_REASON_BREAKPOINT) {
770 uint16_t op;
771 uint32_t pc = buf_get_u32(r->value, 0, 32);
772
773 pc &= ~1;
774 if (target_read_u16(target, pc, &op) == ERROR_OK) {
775 if ((op & 0xFF00) == 0xBE00) {
776 pc = buf_get_u32(r->value, 0, 32) + 2;
777 buf_set_u32(r->value, 0, 32, pc);
778 r->dirty = true;
779 r->valid = true;
780 result = true;
781 LOG_DEBUG("Skipping over BKPT instruction");
782 }
783 }
784 }
785
786 if (inst_found)
787 *inst_found = result;
788
789 return ERROR_OK;
790 }
791
792 const struct command_registration armv7m_command_handlers[] = {
793 {
794 .chain = arm_command_handlers,
795 },
796 {
797 .chain = dap_command_handlers,
798 },
799 COMMAND_REGISTRATION_DONE
800 };

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)