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

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)