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

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)