1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2006 by Magnus Lundin *
8 * Copyright (C) 2008 by Spencer Oliver *
9 * spen@spen-soft.co.uk *
11 * Copyright (C) 2007,2008 Øyvind Harboe *
12 * oyvind.harboe@zylin.com *
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. *
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. *
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. *
29 * ARMv7-M Architecture, Application Level Reference Manual *
30 * ARM DDI 0405C (September 2008) *
32 ***************************************************************************/
39 #define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
43 #define _DEBUG_INSTRUCTION_EXECUTION_
46 /** Maps from enum armv7m_mode (except ARMV7M_MODE_ANY) to name. */
47 char *armv7m_mode_strings
[] =
49 "Thread", "Thread (User)", "Handler",
52 static char *armv7m_exception_strings
[] =
54 "", "Reset", "NMI", "HardFault",
55 "MemManage", "BusFault", "UsageFault", "RESERVED",
56 "RESERVED", "RESERVED", "RESERVED", "SVCall",
57 "DebugMonitor", "RESERVED", "PendSV", "SysTick"
60 /* FIXME these dummies are IDENTICAL to the armv4_5, arm11, and armv7a
61 * ones... except for naming/scoping
63 static uint8_t armv7m_gdb_dummy_fp_value
[12];
65 static struct reg armv7m_gdb_dummy_fp_reg
=
67 .name
= "GDB dummy floating-point register",
68 .value
= armv7m_gdb_dummy_fp_value
,
76 static uint8_t armv7m_gdb_dummy_fps_value
[4];
78 static struct reg armv7m_gdb_dummy_fps_reg
=
80 .name
= "GDB dummy floating-point status register",
81 .value
= armv7m_gdb_dummy_fps_value
,
89 #ifdef ARMV7_GDB_HACKS
90 uint8_t armv7m_gdb_dummy_cpsr_value
[] = {0, 0, 0, 0};
92 struct reg armv7m_gdb_dummy_cpsr_reg
=
94 .name
= "GDB dummy cpsr register",
95 .value
= armv7m_gdb_dummy_cpsr_value
,
105 * These registers are not memory-mapped. The ARMv7-M profile includes
106 * memory mapped registers too, such as for the NVIC (interrupt controller)
107 * and SysTick (timer) modules; those can mostly be treated as peripherals.
109 * The ARMv6-M profile is almost identical in this respect, except that it
110 * doesn't include basepri or faultmask registers.
112 static const struct {
117 { ARMV7M_R0
, "r0", 32 },
118 { ARMV7M_R1
, "r1", 32 },
119 { ARMV7M_R2
, "r2", 32 },
120 { ARMV7M_R3
, "r3", 32 },
122 { ARMV7M_R4
, "r4", 32 },
123 { ARMV7M_R5
, "r5", 32 },
124 { ARMV7M_R6
, "r6", 32 },
125 { ARMV7M_R7
, "r7", 32 },
127 { ARMV7M_R8
, "r8", 32 },
128 { ARMV7M_R9
, "r9", 32 },
129 { ARMV7M_R10
, "r10", 32 },
130 { ARMV7M_R11
, "r11", 32 },
132 { ARMV7M_R12
, "r12", 32 },
133 { ARMV7M_R13
, "sp", 32 },
134 { ARMV7M_R14
, "lr", 32 },
135 { ARMV7M_PC
, "pc", 32 },
137 { ARMV7M_xPSR
, "xPSR", 32 },
138 { ARMV7M_MSP
, "msp", 32 },
139 { ARMV7M_PSP
, "psp", 32 },
141 { ARMV7M_PRIMASK
, "primask", 1 },
142 { ARMV7M_BASEPRI
, "basepri", 8 },
143 { ARMV7M_FAULTMASK
, "faultmask", 1 },
144 { ARMV7M_CONTROL
, "control", 2 },
147 #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
149 static int armv7m_core_reg_arch_type
= -1;
152 * Restores target context using the cache of core registers set up
153 * by armv7m_build_reg_cache(), calling optional core-specific hooks.
155 int armv7m_restore_context(struct target
*target
)
158 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
162 if (armv7m
->pre_restore_context
)
163 armv7m
->pre_restore_context(target
);
165 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
167 if (armv7m
->core_cache
->reg_list
[i
].dirty
)
169 armv7m
->write_core_reg(target
, i
);
173 if (armv7m
->post_restore_context
)
174 armv7m
->post_restore_context(target
);
179 /* Core state functions */
182 * Maps ISR number (from xPSR) to name.
183 * Note that while names and meanings for the first sixteen are standardized
184 * (with zero not a true exception), external interrupts are only numbered.
185 * They are assigned by vendors, which generally assign different numbers to
186 * peripherals (such as UART0 or a USB peripheral controller).
188 char *armv7m_exception_string(int number
)
190 static char enamebuf
[32];
192 if ((number
< 0) | (number
> 511))
193 return "Invalid exception";
195 return armv7m_exception_strings
[number
];
196 sprintf(enamebuf
, "External Interrupt(%i)", number
- 16);
200 static int armv7m_get_core_reg(struct reg
*reg
)
203 struct armv7m_core_reg
*armv7m_reg
= reg
->arch_info
;
204 struct target
*target
= armv7m_reg
->target
;
205 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
207 if (target
->state
!= TARGET_HALTED
)
209 return ERROR_TARGET_NOT_HALTED
;
212 retval
= armv7m
->read_core_reg(target
, armv7m_reg
->num
);
217 static int armv7m_set_core_reg(struct reg
*reg
, uint8_t *buf
)
219 struct armv7m_core_reg
*armv7m_reg
= reg
->arch_info
;
220 struct target
*target
= armv7m_reg
->target
;
221 uint32_t value
= buf_get_u32(buf
, 0, 32);
223 if (target
->state
!= TARGET_HALTED
)
225 return ERROR_TARGET_NOT_HALTED
;
228 buf_set_u32(reg
->value
, 0, 32, value
);
235 static int armv7m_read_core_reg(struct target
*target
, int num
)
239 struct armv7m_core_reg
* armv7m_core_reg
;
240 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
242 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
243 return ERROR_INVALID_ARGUMENTS
;
245 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
246 retval
= armv7m
->load_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, ®_value
);
247 buf_set_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32, reg_value
);
248 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
249 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
254 static int armv7m_write_core_reg(struct target
*target
, int num
)
258 struct armv7m_core_reg
*armv7m_core_reg
;
259 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
261 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
262 return ERROR_INVALID_ARGUMENTS
;
264 reg_value
= buf_get_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32);
265 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
266 retval
= armv7m
->store_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, reg_value
);
267 if (retval
!= ERROR_OK
)
269 LOG_ERROR("JTAG failure");
270 armv7m
->core_cache
->reg_list
[num
].dirty
= armv7m
->core_cache
->reg_list
[num
].valid
;
271 return ERROR_JTAG_DEVICE_ERROR
;
273 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", num
, reg_value
);
274 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
275 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
280 /** Invalidates cache of core registers set up by armv7m_build_reg_cache(). */
281 int armv7m_invalidate_core_regs(struct target
*target
)
283 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
286 for (i
= 0; i
< armv7m
->core_cache
->num_regs
; i
++)
288 armv7m
->core_cache
->reg_list
[i
].valid
= 0;
289 armv7m
->core_cache
->reg_list
[i
].dirty
= 0;
296 * Returns generic ARM userspace registers to GDB.
297 * GDB doesn't quite understand that most ARMs don't have floating point
298 * hardware, so this also fakes a set of long-obsolete FPA registers that
299 * are not used in EABI based software stacks.
301 int armv7m_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
303 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
307 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
310 * GDB register packet format for ARM:
311 * - the first 16 registers are r0..r15
312 * - (obsolete) 8 FPA registers
313 * - (obsolete) FPA status
316 for (i
= 0; i
< 16; i
++)
318 (*reg_list
)[i
] = &armv7m
->core_cache
->reg_list
[i
];
321 for (i
= 16; i
< 24; i
++)
323 (*reg_list
)[i
] = &armv7m_gdb_dummy_fp_reg
;
326 (*reg_list
)[24] = &armv7m_gdb_dummy_fps_reg
;
328 #ifdef ARMV7_GDB_HACKS
329 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
330 (*reg_list
)[25] = &armv7m_gdb_dummy_cpsr_reg
;
332 /* ARMV7M is always in thumb mode, try to make GDB understand this
333 * if it does not support this arch */
334 *((char*)armv7m
->core_cache
->reg_list
[15].value
) |= 1;
336 (*reg_list
)[25] = &armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
];
342 /* run to exit point. return error if exit point was not reached. */
343 static int armv7m_run_and_wait(struct target
*target
, uint32_t entry_point
, int timeout_ms
, uint32_t exit_point
, struct armv7m_common
*armv7m
)
347 /* This code relies on the target specific resume() and poll()->debug_entry()
348 * sequence to write register values to the processor and the read them back */
349 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
354 retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
);
355 /* If the target fails to halt due to the breakpoint, force a halt */
356 if (retval
!= ERROR_OK
|| target
->state
!= TARGET_HALTED
)
358 if ((retval
= target_halt(target
)) != ERROR_OK
)
360 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
364 return ERROR_TARGET_TIMEOUT
;
367 armv7m
->load_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 15, &pc
);
368 if (pc
!= exit_point
)
370 LOG_DEBUG("failed algoritm halted at 0x%" PRIx32
" ", pc
);
371 return ERROR_TARGET_TIMEOUT
;
377 /** Runs a Thumb algorithm in the target. */
378 int armv7m_run_algorithm(struct target
*target
,
379 int num_mem_params
, struct mem_param
*mem_params
,
380 int num_reg_params
, struct reg_param
*reg_params
,
381 uint32_t entry_point
, uint32_t exit_point
,
382 int timeout_ms
, void *arch_info
)
384 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
385 struct armv7m_algorithm
*armv7m_algorithm_info
= arch_info
;
386 enum armv7m_mode core_mode
= armv7m
->core_mode
;
387 int retval
= ERROR_OK
;
389 uint32_t context
[ARMV7M_NUM_REGS
];
391 if (armv7m_algorithm_info
->common_magic
!= ARMV7M_COMMON_MAGIC
)
393 LOG_ERROR("current target isn't an ARMV7M target");
394 return ERROR_TARGET_INVALID
;
397 if (target
->state
!= TARGET_HALTED
)
399 LOG_WARNING("target not halted");
400 return ERROR_TARGET_NOT_HALTED
;
403 /* refresh core register cache */
404 /* Not needed if core register cache is always consistent with target process state */
405 for (i
= 0; i
< ARMV7M_NUM_REGS
; i
++)
407 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
408 armv7m
->read_core_reg(target
, i
);
409 context
[i
] = buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
412 for (i
= 0; i
< num_mem_params
; i
++)
414 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
418 for (i
= 0; i
< num_reg_params
; i
++)
420 struct reg
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
421 // uint32_t regvalue;
425 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
429 if (reg
->size
!= reg_params
[i
].size
)
431 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
435 // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
436 armv7m_set_core_reg(reg
, reg_params
[i
].value
);
439 if (armv7m_algorithm_info
->core_mode
!= ARMV7M_MODE_ANY
)
441 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info
->core_mode
);
442 buf_set_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
,
443 0, 1, armv7m_algorithm_info
->core_mode
);
444 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].dirty
= 1;
445 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].valid
= 1;
448 /* REVISIT speed things up (3% or so in one case) by requiring
449 * algorithms to include a BKPT instruction at each exit point.
450 * This eliminates overheads of adding/removing a breakpoint.
453 /* ARMV7M always runs in Thumb state */
454 if ((retval
= breakpoint_add(target
, exit_point
, 2, BKPT_SOFT
)) != ERROR_OK
)
456 LOG_ERROR("can't add breakpoint to finish algorithm execution");
457 return ERROR_TARGET_FAILURE
;
460 retval
= armv7m_run_and_wait(target
, entry_point
, timeout_ms
, exit_point
, armv7m
);
462 breakpoint_remove(target
, exit_point
);
464 if (retval
!= ERROR_OK
)
469 /* Read memory values to mem_params[] */
470 for (i
= 0; i
< num_mem_params
; i
++)
472 if (mem_params
[i
].direction
!= PARAM_OUT
)
473 if ((retval
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
479 /* Copy core register values to reg_params[] */
480 for (i
= 0; i
< num_reg_params
; i
++)
482 if (reg_params
[i
].direction
!= PARAM_OUT
)
484 struct reg
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
488 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
492 if (reg
->size
!= reg_params
[i
].size
)
494 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
498 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
502 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
505 regvalue
= buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
506 if (regvalue
!= context
[i
])
508 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
,
509 armv7m
->core_cache
->reg_list
[i
].name
, context
[i
]);
510 buf_set_u32(armv7m
->core_cache
->reg_list
[i
].value
,
512 armv7m
->core_cache
->reg_list
[i
].valid
= 1;
513 armv7m
->core_cache
->reg_list
[i
].dirty
= 1;
517 armv7m
->core_mode
= core_mode
;
522 /** Logs summary of ARMv7-M state for a halted target. */
523 int armv7m_arch_state(struct target
*target
)
525 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
528 ctrl
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
, 0, 32);
529 sp
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_R13
].value
, 0, 32);
531 LOG_USER("target halted due to %s, current mode: %s %s\n"
532 "xPSR: %#8.8" PRIx32
" pc: %#8.8" PRIx32
" %csp: %#8.8" PRIx32
,
533 Jim_Nvp_value2name_simple(nvp_target_debug_reason
,
534 target
->debug_reason
)->name
,
535 armv7m_mode_strings
[armv7m
->core_mode
],
536 armv7m_exception_string(armv7m
->exception_number
),
537 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32),
538 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_PC
].value
, 0, 32),
539 (ctrl
& 0x02) ? 'p' : 'm',
545 /** Builds cache of architecturally defined registers. */
546 struct reg_cache
*armv7m_build_reg_cache(struct target
*target
)
548 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
549 int num_regs
= ARMV7M_NUM_REGS
;
550 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
551 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
552 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
553 struct armv7m_core_reg
*arch_info
= calloc(num_regs
, sizeof(struct armv7m_core_reg
));
556 if (armv7m_core_reg_arch_type
== -1)
558 armv7m_core_reg_arch_type
= register_reg_arch_type(armv7m_get_core_reg
, armv7m_set_core_reg
);
561 register_init_dummy(&armv7m_gdb_dummy_fps_reg
);
562 #ifdef ARMV7_GDB_HACKS
563 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg
);
565 register_init_dummy(&armv7m_gdb_dummy_fp_reg
);
567 /* Build the process context cache */
568 cache
->name
= "arm v7m registers";
570 cache
->reg_list
= reg_list
;
571 cache
->num_regs
= num_regs
;
573 armv7m
->core_cache
= cache
;
575 for (i
= 0; i
< num_regs
; i
++)
577 arch_info
[i
].num
= armv7m_regs
[i
].id
;
578 arch_info
[i
].target
= target
;
579 arch_info
[i
].armv7m_common
= armv7m
;
580 reg_list
[i
].name
= armv7m_regs
[i
].name
;
581 reg_list
[i
].size
= armv7m_regs
[i
].bits
;
582 reg_list
[i
].value
= calloc(1, 4);
583 reg_list
[i
].dirty
= 0;
584 reg_list
[i
].valid
= 0;
585 reg_list
[i
].arch_type
= armv7m_core_reg_arch_type
;
586 reg_list
[i
].arch_info
= &arch_info
[i
];
592 /** Sets up target as a generic ARMv7-M core */
593 int armv7m_init_arch_info(struct target
*target
, struct armv7m_common
*armv7m
)
595 /* register arch-specific functions */
597 target
->arch_info
= armv7m
;
598 armv7m
->read_core_reg
= armv7m_read_core_reg
;
599 armv7m
->write_core_reg
= armv7m_write_core_reg
;
604 /** Generates a CRC32 checksum of a memory region. */
605 int armv7m_checksum_memory(struct target
*target
,
606 uint32_t address
, uint32_t count
, uint32_t* checksum
)
608 struct working_area
*crc_algorithm
;
609 struct armv7m_algorithm armv7m_info
;
610 struct reg_param reg_params
[2];
613 static const uint16_t cortex_m3_crc_code
[] = {
614 0x4602, /* mov r2, r0 */
615 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
616 0x460B, /* mov r3, r1 */
617 0xF04F, 0x0400, /* mov r4, #0 */
618 0xE013, /* b ncomp */
620 0x5D11, /* ldrb r1, [r2, r4] */
621 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
622 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
624 0xF04F, 0x0500, /* mov r5, #0 */
626 0x2800, /* cmp r0, #0 */
627 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
628 0xF105, 0x0501, /* add r5, r5, #1 */
629 0x4630, /* mov r0, r6 */
631 0xEA86, 0x0007, /* eor r0, r6, r7 */
632 0x2D08, /* cmp r5, #8 */
633 0xD1F4, /* bne loop */
635 0xF104, 0x0401, /* add r4, r4, #1 */
637 0x429C, /* cmp r4, r3 */
638 0xD1E9, /* bne nbyte */
641 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
646 if (target_alloc_working_area(target
, sizeof(cortex_m3_crc_code
), &crc_algorithm
) != ERROR_OK
)
648 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
651 /* convert flash writing code into a buffer in target endianness */
652 for (i
= 0; i
< (sizeof(cortex_m3_crc_code
)/sizeof(uint16_t)); i
++)
653 if ((retval
= target_write_u16(target
, crc_algorithm
->address
+ i
*sizeof(uint16_t), cortex_m3_crc_code
[i
])) != ERROR_OK
)
658 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
659 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
661 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
662 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
664 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
665 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
667 if ((retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
668 crc_algorithm
->address
, crc_algorithm
->address
+ (sizeof(cortex_m3_crc_code
)-6), 20000, &armv7m_info
)) != ERROR_OK
)
670 LOG_ERROR("error executing cortex_m3 crc algorithm");
671 destroy_reg_param(®_params
[0]);
672 destroy_reg_param(®_params
[1]);
673 target_free_working_area(target
, crc_algorithm
);
677 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
679 destroy_reg_param(®_params
[0]);
680 destroy_reg_param(®_params
[1]);
682 target_free_working_area(target
, crc_algorithm
);
687 /** Checks whether a memory region is zeroed. */
688 int armv7m_blank_check_memory(struct target
*target
,
689 uint32_t address
, uint32_t count
, uint32_t* blank
)
691 struct working_area
*erase_check_algorithm
;
692 struct reg_param reg_params
[3];
693 struct armv7m_algorithm armv7m_info
;
697 static const uint16_t erase_check_code
[] =
700 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
701 0xEA02, 0x0203, /* and r2, r2, r3 */
702 0x3901, /* subs r1, r1, #1 */
703 0xD1F9, /* bne loop */
708 /* make sure we have a working area */
709 if (target_alloc_working_area(target
, sizeof(erase_check_code
), &erase_check_algorithm
) != ERROR_OK
)
711 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
714 /* convert flash writing code into a buffer in target endianness */
715 for (i
= 0; i
< (sizeof(erase_check_code
)/sizeof(uint16_t)); i
++)
716 target_write_u16(target
, erase_check_algorithm
->address
+ i
*sizeof(uint16_t), erase_check_code
[i
]);
718 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
719 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
721 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
722 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
724 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
725 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
727 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
728 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
730 if ((retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
731 erase_check_algorithm
->address
, erase_check_algorithm
->address
+ (sizeof(erase_check_code
)-2), 10000, &armv7m_info
)) != ERROR_OK
)
733 destroy_reg_param(®_params
[0]);
734 destroy_reg_param(®_params
[1]);
735 destroy_reg_param(®_params
[2]);
736 target_free_working_area(target
, erase_check_algorithm
);
740 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
742 destroy_reg_param(®_params
[0]);
743 destroy_reg_param(®_params
[1]);
744 destroy_reg_param(®_params
[2]);
746 target_free_working_area(target
, erase_check_algorithm
);
751 /*--------------------------------------------------------------------------*/
754 * Only stuff below this line should need to verify that its target
755 * is an ARMv7-M node.
757 * FIXME yet none of it _does_ verify target types yet!
762 * Return the debug ap baseaddress in hexadecimal;
763 * no extra output to simplify script processing
765 COMMAND_HANDLER(handle_dap_baseaddr_command
)
767 struct target
*target
= get_current_target(cmd_ctx
);
768 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
769 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
770 uint32_t apsel
, apselsave
, baseaddr
;
773 apselsave
= swjdp
->apsel
;
776 apsel
= swjdp
->apsel
;
779 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
782 return ERROR_COMMAND_SYNTAX_ERROR
;
785 if (apselsave
!= apsel
)
786 dap_ap_select(swjdp
, apsel
);
788 dap_ap_read_reg_u32(swjdp
, 0xF8, &baseaddr
);
789 retval
= swjdp_transaction_endcheck(swjdp
);
790 command_print(cmd_ctx
, "0x%8.8" PRIx32
"", baseaddr
);
792 if (apselsave
!= apsel
)
793 dap_ap_select(swjdp
, apselsave
);
799 * Return the debug ap id in hexadecimal;
800 * no extra output to simplify script processing
802 COMMAND_HANDLER(handle_dap_apid_command
)
804 struct target
*target
= get_current_target(cmd_ctx
);
805 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
806 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
808 return CALL_COMMAND_HANDLER(dap_apid_command
, swjdp
);
811 COMMAND_HANDLER(handle_dap_apsel_command
)
813 struct target
*target
= get_current_target(cmd_ctx
);
814 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
815 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
817 return CALL_COMMAND_HANDLER(dap_apsel_command
, swjdp
);
820 COMMAND_HANDLER(handle_dap_memaccess_command
)
822 struct target
*target
= get_current_target(cmd_ctx
);
823 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
824 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
826 return CALL_COMMAND_HANDLER(dap_memaccess_command
, swjdp
);
830 COMMAND_HANDLER(handle_dap_info_command
)
832 struct target
*target
= get_current_target(cmd_ctx
);
833 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
834 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
839 apsel
= swjdp
->apsel
;
842 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
845 return ERROR_COMMAND_SYNTAX_ERROR
;
848 return dap_info_command(cmd_ctx
, swjdp
, apsel
);
851 /** Registers commands used to access DAP resources. */
852 int armv7m_register_commands(struct command_context
*cmd_ctx
)
854 struct command
*arm_adi_v5_dap_cmd
;
856 arm_adi_v5_dap_cmd
= register_command(cmd_ctx
, NULL
, "dap",
858 "cortex dap specific commands");
860 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "info",
861 handle_dap_info_command
, COMMAND_EXEC
,
862 "Displays dap info for ap [num],"
863 "default currently selected AP");
864 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apsel",
865 handle_dap_apsel_command
, COMMAND_EXEC
,
866 "Select a different AP [num] (default 0)");
867 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apid",
868 handle_dap_apid_command
, COMMAND_EXEC
,
869 "Displays id reg from AP [num], "
870 "default currently selected AP");
871 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "baseaddr",
872 handle_dap_baseaddr_command
, COMMAND_EXEC
,
873 "Displays debug base address from AP [num],"
874 "default currently selected AP");
875 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "memaccess",
876 handle_dap_memaccess_command
, COMMAND_EXEC
,
877 "set/get number of extra tck for mem-ap "
878 "memory bus access [0-255]");
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)