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 ***************************************************************************/
37 #include "breakpoints.h"
40 #include "algorithm.h"
43 #define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
47 #define _DEBUG_INSTRUCTION_EXECUTION_
50 /** Maps from enum armv7m_mode (except ARMV7M_MODE_ANY) to name. */
51 char *armv7m_mode_strings
[] =
53 "Thread", "Thread (User)", "Handler",
56 static char *armv7m_exception_strings
[] =
58 "", "Reset", "NMI", "HardFault",
59 "MemManage", "BusFault", "UsageFault", "RESERVED",
60 "RESERVED", "RESERVED", "RESERVED", "SVCall",
61 "DebugMonitor", "RESERVED", "PendSV", "SysTick"
64 /* FIXME these dummies are IDENTICAL to the armv4_5, arm11, and armv7a
65 * ones... except for naming/scoping
67 static uint8_t armv7m_gdb_dummy_fp_value
[12];
69 static struct reg armv7m_gdb_dummy_fp_reg
=
71 .name
= "GDB dummy floating-point register",
72 .value
= armv7m_gdb_dummy_fp_value
,
80 static uint8_t armv7m_gdb_dummy_fps_value
[4];
82 static struct reg armv7m_gdb_dummy_fps_reg
=
84 .name
= "GDB dummy floating-point status register",
85 .value
= armv7m_gdb_dummy_fps_value
,
93 #ifdef ARMV7_GDB_HACKS
94 uint8_t armv7m_gdb_dummy_cpsr_value
[] = {0, 0, 0, 0};
96 struct reg armv7m_gdb_dummy_cpsr_reg
=
98 .name
= "GDB dummy cpsr register",
99 .value
= armv7m_gdb_dummy_cpsr_value
,
109 * These registers are not memory-mapped. The ARMv7-M profile includes
110 * memory mapped registers too, such as for the NVIC (interrupt controller)
111 * and SysTick (timer) modules; those can mostly be treated as peripherals.
113 * The ARMv6-M profile is almost identical in this respect, except that it
114 * doesn't include basepri or faultmask registers.
116 static const struct {
121 { ARMV7M_R0
, "r0", 32 },
122 { ARMV7M_R1
, "r1", 32 },
123 { ARMV7M_R2
, "r2", 32 },
124 { ARMV7M_R3
, "r3", 32 },
126 { ARMV7M_R4
, "r4", 32 },
127 { ARMV7M_R5
, "r5", 32 },
128 { ARMV7M_R6
, "r6", 32 },
129 { ARMV7M_R7
, "r7", 32 },
131 { ARMV7M_R8
, "r8", 32 },
132 { ARMV7M_R9
, "r9", 32 },
133 { ARMV7M_R10
, "r10", 32 },
134 { ARMV7M_R11
, "r11", 32 },
136 { ARMV7M_R12
, "r12", 32 },
137 { ARMV7M_R13
, "sp", 32 },
138 { ARMV7M_R14
, "lr", 32 },
139 { ARMV7M_PC
, "pc", 32 },
141 { ARMV7M_xPSR
, "xPSR", 32 },
142 { ARMV7M_MSP
, "msp", 32 },
143 { ARMV7M_PSP
, "psp", 32 },
145 { ARMV7M_PRIMASK
, "primask", 1 },
146 { ARMV7M_BASEPRI
, "basepri", 8 },
147 { ARMV7M_FAULTMASK
, "faultmask", 1 },
148 { ARMV7M_CONTROL
, "control", 2 },
151 #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
153 static int armv7m_core_reg_arch_type
= -1;
156 * Restores target context using the cache of core registers set up
157 * by armv7m_build_reg_cache(), calling optional core-specific hooks.
159 int armv7m_restore_context(struct target
*target
)
162 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
166 if (armv7m
->pre_restore_context
)
167 armv7m
->pre_restore_context(target
);
169 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
171 if (armv7m
->core_cache
->reg_list
[i
].dirty
)
173 armv7m
->write_core_reg(target
, i
);
177 if (armv7m
->post_restore_context
)
178 armv7m
->post_restore_context(target
);
183 /* Core state functions */
186 * Maps ISR number (from xPSR) to name.
187 * Note that while names and meanings for the first sixteen are standardized
188 * (with zero not a true exception), external interrupts are only numbered.
189 * They are assigned by vendors, which generally assign different numbers to
190 * peripherals (such as UART0 or a USB peripheral controller).
192 char *armv7m_exception_string(int number
)
194 static char enamebuf
[32];
196 if ((number
< 0) | (number
> 511))
197 return "Invalid exception";
199 return armv7m_exception_strings
[number
];
200 sprintf(enamebuf
, "External Interrupt(%i)", number
- 16);
204 static int armv7m_get_core_reg(struct reg
*reg
)
207 struct armv7m_core_reg
*armv7m_reg
= reg
->arch_info
;
208 struct target
*target
= armv7m_reg
->target
;
209 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
211 if (target
->state
!= TARGET_HALTED
)
213 return ERROR_TARGET_NOT_HALTED
;
216 retval
= armv7m
->read_core_reg(target
, armv7m_reg
->num
);
221 static int armv7m_set_core_reg(struct reg
*reg
, uint8_t *buf
)
223 struct armv7m_core_reg
*armv7m_reg
= reg
->arch_info
;
224 struct target
*target
= armv7m_reg
->target
;
225 uint32_t value
= buf_get_u32(buf
, 0, 32);
227 if (target
->state
!= TARGET_HALTED
)
229 return ERROR_TARGET_NOT_HALTED
;
232 buf_set_u32(reg
->value
, 0, 32, value
);
239 static int armv7m_read_core_reg(struct target
*target
, unsigned num
)
243 struct armv7m_core_reg
* armv7m_core_reg
;
244 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
246 if (num
>= ARMV7M_NUM_REGS
)
247 return ERROR_INVALID_ARGUMENTS
;
249 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
250 retval
= armv7m
->load_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, ®_value
);
251 buf_set_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32, reg_value
);
252 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
253 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
258 static int armv7m_write_core_reg(struct target
*target
, unsigned num
)
262 struct armv7m_core_reg
*armv7m_core_reg
;
263 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
265 if (num
>= ARMV7M_NUM_REGS
)
266 return ERROR_INVALID_ARGUMENTS
;
268 reg_value
= buf_get_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32);
269 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
270 retval
= armv7m
->store_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, reg_value
);
271 if (retval
!= ERROR_OK
)
273 LOG_ERROR("JTAG failure");
274 armv7m
->core_cache
->reg_list
[num
].dirty
= armv7m
->core_cache
->reg_list
[num
].valid
;
275 return ERROR_JTAG_DEVICE_ERROR
;
277 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", num
, reg_value
);
278 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
279 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
284 /** Invalidates cache of core registers set up by armv7m_build_reg_cache(). */
285 int armv7m_invalidate_core_regs(struct target
*target
)
287 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
290 for (i
= 0; i
< armv7m
->core_cache
->num_regs
; i
++)
292 armv7m
->core_cache
->reg_list
[i
].valid
= 0;
293 armv7m
->core_cache
->reg_list
[i
].dirty
= 0;
300 * Returns generic ARM userspace registers to GDB.
301 * GDB doesn't quite understand that most ARMs don't have floating point
302 * hardware, so this also fakes a set of long-obsolete FPA registers that
303 * are not used in EABI based software stacks.
305 int armv7m_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
307 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
311 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
314 * GDB register packet format for ARM:
315 * - the first 16 registers are r0..r15
316 * - (obsolete) 8 FPA registers
317 * - (obsolete) FPA status
320 for (i
= 0; i
< 16; i
++)
322 (*reg_list
)[i
] = &armv7m
->core_cache
->reg_list
[i
];
325 for (i
= 16; i
< 24; i
++)
327 (*reg_list
)[i
] = &armv7m_gdb_dummy_fp_reg
;
330 (*reg_list
)[24] = &armv7m_gdb_dummy_fps_reg
;
332 #ifdef ARMV7_GDB_HACKS
333 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
334 (*reg_list
)[25] = &armv7m_gdb_dummy_cpsr_reg
;
336 /* ARMV7M is always in thumb mode, try to make GDB understand this
337 * if it does not support this arch */
338 *((char*)armv7m
->core_cache
->reg_list
[15].value
) |= 1;
340 (*reg_list
)[25] = &armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
];
346 /* run to exit point. return error if exit point was not reached. */
347 static int armv7m_run_and_wait(struct target
*target
, uint32_t entry_point
, int timeout_ms
, uint32_t exit_point
, struct armv7m_common
*armv7m
)
351 /* This code relies on the target specific resume() and poll()->debug_entry()
352 * sequence to write register values to the processor and the read them back */
353 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
358 retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
);
359 /* If the target fails to halt due to the breakpoint, force a halt */
360 if (retval
!= ERROR_OK
|| target
->state
!= TARGET_HALTED
)
362 if ((retval
= target_halt(target
)) != ERROR_OK
)
364 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
368 return ERROR_TARGET_TIMEOUT
;
371 armv7m
->load_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 15, &pc
);
372 if (pc
!= exit_point
)
374 LOG_DEBUG("failed algoritm halted at 0x%" PRIx32
" ", pc
);
375 return ERROR_TARGET_TIMEOUT
;
381 /** Runs a Thumb algorithm in the target. */
382 int armv7m_run_algorithm(struct target
*target
,
383 int num_mem_params
, struct mem_param
*mem_params
,
384 int num_reg_params
, struct reg_param
*reg_params
,
385 uint32_t entry_point
, uint32_t exit_point
,
386 int timeout_ms
, void *arch_info
)
388 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
389 struct armv7m_algorithm
*armv7m_algorithm_info
= arch_info
;
390 enum armv7m_mode core_mode
= armv7m
->core_mode
;
391 int retval
= ERROR_OK
;
393 uint32_t context
[ARMV7M_NUM_REGS
];
395 if (armv7m_algorithm_info
->common_magic
!= ARMV7M_COMMON_MAGIC
)
397 LOG_ERROR("current target isn't an ARMV7M target");
398 return ERROR_TARGET_INVALID
;
401 if (target
->state
!= TARGET_HALTED
)
403 LOG_WARNING("target not halted");
404 return ERROR_TARGET_NOT_HALTED
;
407 /* refresh core register cache */
408 /* Not needed if core register cache is always consistent with target process state */
409 for (i
= 0; i
< ARMV7M_NUM_REGS
; i
++)
411 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
412 armv7m
->read_core_reg(target
, i
);
413 context
[i
] = buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
416 for (i
= 0; i
< num_mem_params
; i
++)
418 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
422 for (i
= 0; i
< num_reg_params
; i
++)
424 struct reg
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
425 // uint32_t regvalue;
429 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
433 if (reg
->size
!= reg_params
[i
].size
)
435 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
439 // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
440 armv7m_set_core_reg(reg
, reg_params
[i
].value
);
443 if (armv7m_algorithm_info
->core_mode
!= ARMV7M_MODE_ANY
)
445 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info
->core_mode
);
446 buf_set_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
,
447 0, 1, armv7m_algorithm_info
->core_mode
);
448 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].dirty
= 1;
449 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].valid
= 1;
452 /* REVISIT speed things up (3% or so in one case) by requiring
453 * algorithms to include a BKPT instruction at each exit point.
454 * This eliminates overheads of adding/removing a breakpoint.
457 /* ARMV7M always runs in Thumb state */
458 if ((retval
= breakpoint_add(target
, exit_point
, 2, BKPT_SOFT
)) != ERROR_OK
)
460 LOG_ERROR("can't add breakpoint to finish algorithm execution");
461 return ERROR_TARGET_FAILURE
;
464 retval
= armv7m_run_and_wait(target
, entry_point
, timeout_ms
, exit_point
, armv7m
);
466 breakpoint_remove(target
, exit_point
);
468 if (retval
!= ERROR_OK
)
473 /* Read memory values to mem_params[] */
474 for (i
= 0; i
< num_mem_params
; i
++)
476 if (mem_params
[i
].direction
!= PARAM_OUT
)
477 if ((retval
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
483 /* Copy core register values to reg_params[] */
484 for (i
= 0; i
< num_reg_params
; i
++)
486 if (reg_params
[i
].direction
!= PARAM_OUT
)
488 struct reg
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
492 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
496 if (reg
->size
!= reg_params
[i
].size
)
498 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
502 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
506 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
509 regvalue
= buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
510 if (regvalue
!= context
[i
])
512 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
,
513 armv7m
->core_cache
->reg_list
[i
].name
, context
[i
]);
514 buf_set_u32(armv7m
->core_cache
->reg_list
[i
].value
,
516 armv7m
->core_cache
->reg_list
[i
].valid
= 1;
517 armv7m
->core_cache
->reg_list
[i
].dirty
= 1;
521 armv7m
->core_mode
= core_mode
;
526 /** Logs summary of ARMv7-M state for a halted target. */
527 int armv7m_arch_state(struct target
*target
)
529 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
532 ctrl
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
, 0, 32);
533 sp
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_R13
].value
, 0, 32);
535 LOG_USER("target halted due to %s, current mode: %s %s\n"
536 "xPSR: %#8.8" PRIx32
" pc: %#8.8" PRIx32
" %csp: %#8.8" PRIx32
,
537 Jim_Nvp_value2name_simple(nvp_target_debug_reason
,
538 target
->debug_reason
)->name
,
539 armv7m_mode_strings
[armv7m
->core_mode
],
540 armv7m_exception_string(armv7m
->exception_number
),
541 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32),
542 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_PC
].value
, 0, 32),
543 (ctrl
& 0x02) ? 'p' : 'm',
549 /** Builds cache of architecturally defined registers. */
550 struct reg_cache
*armv7m_build_reg_cache(struct target
*target
)
552 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
553 int num_regs
= ARMV7M_NUM_REGS
;
554 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
555 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
556 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
557 struct armv7m_core_reg
*arch_info
= calloc(num_regs
, sizeof(struct armv7m_core_reg
));
560 if (armv7m_core_reg_arch_type
== -1)
562 armv7m_core_reg_arch_type
= register_reg_arch_type(armv7m_get_core_reg
, armv7m_set_core_reg
);
565 register_init_dummy(&armv7m_gdb_dummy_fps_reg
);
566 #ifdef ARMV7_GDB_HACKS
567 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg
);
569 register_init_dummy(&armv7m_gdb_dummy_fp_reg
);
571 /* Build the process context cache */
572 cache
->name
= "arm v7m registers";
574 cache
->reg_list
= reg_list
;
575 cache
->num_regs
= num_regs
;
577 armv7m
->core_cache
= cache
;
579 for (i
= 0; i
< num_regs
; i
++)
581 arch_info
[i
].num
= armv7m_regs
[i
].id
;
582 arch_info
[i
].target
= target
;
583 arch_info
[i
].armv7m_common
= armv7m
;
584 reg_list
[i
].name
= armv7m_regs
[i
].name
;
585 reg_list
[i
].size
= armv7m_regs
[i
].bits
;
586 reg_list
[i
].value
= calloc(1, 4);
587 reg_list
[i
].dirty
= 0;
588 reg_list
[i
].valid
= 0;
589 reg_list
[i
].arch_type
= armv7m_core_reg_arch_type
;
590 reg_list
[i
].arch_info
= &arch_info
[i
];
596 /** Sets up target as a generic ARMv7-M core */
597 int armv7m_init_arch_info(struct target
*target
, struct armv7m_common
*armv7m
)
599 /* register arch-specific functions */
601 target
->arch_info
= armv7m
;
602 armv7m
->read_core_reg
= armv7m_read_core_reg
;
603 armv7m
->write_core_reg
= armv7m_write_core_reg
;
608 /** Generates a CRC32 checksum of a memory region. */
609 int armv7m_checksum_memory(struct target
*target
,
610 uint32_t address
, uint32_t count
, uint32_t* checksum
)
612 struct working_area
*crc_algorithm
;
613 struct armv7m_algorithm armv7m_info
;
614 struct reg_param reg_params
[2];
617 static const uint16_t cortex_m3_crc_code
[] = {
618 0x4602, /* mov r2, r0 */
619 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
620 0x460B, /* mov r3, r1 */
621 0xF04F, 0x0400, /* mov r4, #0 */
622 0xE013, /* b ncomp */
624 0x5D11, /* ldrb r1, [r2, r4] */
625 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
626 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
628 0xF04F, 0x0500, /* mov r5, #0 */
630 0x2800, /* cmp r0, #0 */
631 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
632 0xF105, 0x0501, /* add r5, r5, #1 */
633 0x4630, /* mov r0, r6 */
635 0xEA86, 0x0007, /* eor r0, r6, r7 */
636 0x2D08, /* cmp r5, #8 */
637 0xD1F4, /* bne loop */
639 0xF104, 0x0401, /* add r4, r4, #1 */
641 0x429C, /* cmp r4, r3 */
642 0xD1E9, /* bne nbyte */
645 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
650 if (target_alloc_working_area(target
, sizeof(cortex_m3_crc_code
), &crc_algorithm
) != ERROR_OK
)
652 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
655 /* convert flash writing code into a buffer in target endianness */
656 for (i
= 0; i
< (sizeof(cortex_m3_crc_code
)/sizeof(uint16_t)); i
++)
657 if ((retval
= target_write_u16(target
, crc_algorithm
->address
+ i
*sizeof(uint16_t), cortex_m3_crc_code
[i
])) != ERROR_OK
)
662 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
663 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
665 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
666 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
668 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
669 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
671 if ((retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
672 crc_algorithm
->address
, crc_algorithm
->address
+ (sizeof(cortex_m3_crc_code
)-6), 20000, &armv7m_info
)) != ERROR_OK
)
674 LOG_ERROR("error executing cortex_m3 crc algorithm");
675 destroy_reg_param(®_params
[0]);
676 destroy_reg_param(®_params
[1]);
677 target_free_working_area(target
, crc_algorithm
);
681 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
683 destroy_reg_param(®_params
[0]);
684 destroy_reg_param(®_params
[1]);
686 target_free_working_area(target
, crc_algorithm
);
691 /** Checks whether a memory region is zeroed. */
692 int armv7m_blank_check_memory(struct target
*target
,
693 uint32_t address
, uint32_t count
, uint32_t* blank
)
695 struct working_area
*erase_check_algorithm
;
696 struct reg_param reg_params
[3];
697 struct armv7m_algorithm armv7m_info
;
701 static const uint16_t erase_check_code
[] =
704 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
705 0xEA02, 0x0203, /* and r2, r2, r3 */
706 0x3901, /* subs r1, r1, #1 */
707 0xD1F9, /* bne loop */
712 /* make sure we have a working area */
713 if (target_alloc_working_area(target
, sizeof(erase_check_code
), &erase_check_algorithm
) != ERROR_OK
)
715 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
718 /* convert flash writing code into a buffer in target endianness */
719 for (i
= 0; i
< (sizeof(erase_check_code
)/sizeof(uint16_t)); i
++)
720 target_write_u16(target
, erase_check_algorithm
->address
+ i
*sizeof(uint16_t), erase_check_code
[i
]);
722 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
723 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
725 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
726 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
728 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
729 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
731 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
732 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
734 if ((retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
735 erase_check_algorithm
->address
, erase_check_algorithm
->address
+ (sizeof(erase_check_code
)-2), 10000, &armv7m_info
)) != ERROR_OK
)
737 destroy_reg_param(®_params
[0]);
738 destroy_reg_param(®_params
[1]);
739 destroy_reg_param(®_params
[2]);
740 target_free_working_area(target
, erase_check_algorithm
);
744 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
746 destroy_reg_param(®_params
[0]);
747 destroy_reg_param(®_params
[1]);
748 destroy_reg_param(®_params
[2]);
750 target_free_working_area(target
, erase_check_algorithm
);
755 /*--------------------------------------------------------------------------*/
758 * Only stuff below this line should need to verify that its target
759 * is an ARMv7-M node.
761 * FIXME yet none of it _does_ verify target types yet!
766 * Return the debug ap baseaddress in hexadecimal;
767 * no extra output to simplify script processing
769 COMMAND_HANDLER(handle_dap_baseaddr_command
)
771 struct target
*target
= get_current_target(cmd_ctx
);
772 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
773 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
774 uint32_t apsel
, apselsave
, baseaddr
;
777 apselsave
= swjdp
->apsel
;
780 apsel
= swjdp
->apsel
;
783 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
786 return ERROR_COMMAND_SYNTAX_ERROR
;
789 if (apselsave
!= apsel
)
790 dap_ap_select(swjdp
, apsel
);
792 dap_ap_read_reg_u32(swjdp
, 0xF8, &baseaddr
);
793 retval
= swjdp_transaction_endcheck(swjdp
);
794 command_print(cmd_ctx
, "0x%8.8" PRIx32
"", baseaddr
);
796 if (apselsave
!= apsel
)
797 dap_ap_select(swjdp
, apselsave
);
803 * Return the debug ap id in hexadecimal;
804 * no extra output to simplify script processing
806 COMMAND_HANDLER(handle_dap_apid_command
)
808 struct target
*target
= get_current_target(cmd_ctx
);
809 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
810 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
812 return CALL_COMMAND_HANDLER(dap_apid_command
, swjdp
);
815 COMMAND_HANDLER(handle_dap_apsel_command
)
817 struct target
*target
= get_current_target(cmd_ctx
);
818 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
819 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
821 return CALL_COMMAND_HANDLER(dap_apsel_command
, swjdp
);
824 COMMAND_HANDLER(handle_dap_memaccess_command
)
826 struct target
*target
= get_current_target(cmd_ctx
);
827 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
828 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
830 return CALL_COMMAND_HANDLER(dap_memaccess_command
, swjdp
);
834 COMMAND_HANDLER(handle_dap_info_command
)
836 struct target
*target
= get_current_target(cmd_ctx
);
837 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
838 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
843 apsel
= swjdp
->apsel
;
846 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
849 return ERROR_COMMAND_SYNTAX_ERROR
;
852 return dap_info_command(cmd_ctx
, swjdp
, apsel
);
855 /** Registers commands used to access DAP resources. */
856 int armv7m_register_commands(struct command_context
*cmd_ctx
)
858 struct command
*arm_adi_v5_dap_cmd
;
860 arm_adi_v5_dap_cmd
= register_command(cmd_ctx
, NULL
, "dap",
862 "cortex dap specific commands");
864 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "info",
865 handle_dap_info_command
, COMMAND_EXEC
,
866 "Displays dap info for ap [num],"
867 "default currently selected AP");
868 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apsel",
869 handle_dap_apsel_command
, COMMAND_EXEC
,
870 "Select a different AP [num] (default 0)");
871 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apid",
872 handle_dap_apid_command
, COMMAND_EXEC
,
873 "Displays id reg from AP [num], "
874 "default currently selected AP");
875 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "baseaddr",
876 handle_dap_baseaddr_command
, COMMAND_EXEC
,
877 "Displays debug base address from AP [num],"
878 "default currently selected AP");
879 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "memaccess",
880 handle_dap_memaccess_command
, COMMAND_EXEC
,
881 "set/get number of extra tck for mem-ap "
882 "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)