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

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)