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"
39 #include "algorithm.h"
42 #define ARRAY_SIZE(x) ((int)(sizeof(x)/sizeof((x)[0])))
46 #define _DEBUG_INSTRUCTION_EXECUTION_
49 /** Maps from enum armv7m_mode (except ARMV7M_MODE_ANY) to name. */
50 char *armv7m_mode_strings
[] =
52 "Thread", "Thread (User)", "Handler",
55 static char *armv7m_exception_strings
[] =
57 "", "Reset", "NMI", "HardFault",
58 "MemManage", "BusFault", "UsageFault", "RESERVED",
59 "RESERVED", "RESERVED", "RESERVED", "SVCall",
60 "DebugMonitor", "RESERVED", "PendSV", "SysTick"
63 /* FIXME these dummies are IDENTICAL to the armv4_5, arm11, and armv7a
64 * ones... except for naming/scoping
66 static uint8_t armv7m_gdb_dummy_fp_value
[12];
68 static struct reg armv7m_gdb_dummy_fp_reg
=
70 .name
= "GDB dummy floating-point register",
71 .value
= armv7m_gdb_dummy_fp_value
,
79 static uint8_t armv7m_gdb_dummy_fps_value
[4];
81 static struct reg armv7m_gdb_dummy_fps_reg
=
83 .name
= "GDB dummy floating-point status register",
84 .value
= armv7m_gdb_dummy_fps_value
,
92 #ifdef ARMV7_GDB_HACKS
93 uint8_t armv7m_gdb_dummy_cpsr_value
[] = {0, 0, 0, 0};
95 struct reg armv7m_gdb_dummy_cpsr_reg
=
97 .name
= "GDB dummy cpsr register",
98 .value
= armv7m_gdb_dummy_cpsr_value
,
108 * These registers are not memory-mapped. The ARMv7-M profile includes
109 * memory mapped registers too, such as for the NVIC (interrupt controller)
110 * and SysTick (timer) modules; those can mostly be treated as peripherals.
112 * The ARMv6-M profile is almost identical in this respect, except that it
113 * doesn't include basepri or faultmask registers.
115 static const struct {
120 { ARMV7M_R0
, "r0", 32 },
121 { ARMV7M_R1
, "r1", 32 },
122 { ARMV7M_R2
, "r2", 32 },
123 { ARMV7M_R3
, "r3", 32 },
125 { ARMV7M_R4
, "r4", 32 },
126 { ARMV7M_R5
, "r5", 32 },
127 { ARMV7M_R6
, "r6", 32 },
128 { ARMV7M_R7
, "r7", 32 },
130 { ARMV7M_R8
, "r8", 32 },
131 { ARMV7M_R9
, "r9", 32 },
132 { ARMV7M_R10
, "r10", 32 },
133 { ARMV7M_R11
, "r11", 32 },
135 { ARMV7M_R12
, "r12", 32 },
136 { ARMV7M_R13
, "sp", 32 },
137 { ARMV7M_R14
, "lr", 32 },
138 { ARMV7M_PC
, "pc", 32 },
140 { ARMV7M_xPSR
, "xPSR", 32 },
141 { ARMV7M_MSP
, "msp", 32 },
142 { ARMV7M_PSP
, "psp", 32 },
144 { ARMV7M_PRIMASK
, "primask", 1 },
145 { ARMV7M_BASEPRI
, "basepri", 8 },
146 { ARMV7M_FAULTMASK
, "faultmask", 1 },
147 { ARMV7M_CONTROL
, "control", 2 },
150 #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
152 static int armv7m_core_reg_arch_type
= -1;
155 * Restores target context using the cache of core registers set up
156 * by armv7m_build_reg_cache(), calling optional core-specific hooks.
158 int armv7m_restore_context(struct target
*target
)
161 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
165 if (armv7m
->pre_restore_context
)
166 armv7m
->pre_restore_context(target
);
168 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
170 if (armv7m
->core_cache
->reg_list
[i
].dirty
)
172 armv7m
->write_core_reg(target
, i
);
176 if (armv7m
->post_restore_context
)
177 armv7m
->post_restore_context(target
);
182 /* Core state functions */
185 * Maps ISR number (from xPSR) to name.
186 * Note that while names and meanings for the first sixteen are standardized
187 * (with zero not a true exception), external interrupts are only numbered.
188 * They are assigned by vendors, which generally assign different numbers to
189 * peripherals (such as UART0 or a USB peripheral controller).
191 char *armv7m_exception_string(int number
)
193 static char enamebuf
[32];
195 if ((number
< 0) | (number
> 511))
196 return "Invalid exception";
198 return armv7m_exception_strings
[number
];
199 sprintf(enamebuf
, "External Interrupt(%i)", number
- 16);
203 static int armv7m_get_core_reg(struct reg
*reg
)
206 struct armv7m_core_reg
*armv7m_reg
= reg
->arch_info
;
207 struct target
*target
= armv7m_reg
->target
;
208 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
210 if (target
->state
!= TARGET_HALTED
)
212 return ERROR_TARGET_NOT_HALTED
;
215 retval
= armv7m
->read_core_reg(target
, armv7m_reg
->num
);
220 static int armv7m_set_core_reg(struct reg
*reg
, uint8_t *buf
)
222 struct armv7m_core_reg
*armv7m_reg
= reg
->arch_info
;
223 struct target
*target
= armv7m_reg
->target
;
224 uint32_t value
= buf_get_u32(buf
, 0, 32);
226 if (target
->state
!= TARGET_HALTED
)
228 return ERROR_TARGET_NOT_HALTED
;
231 buf_set_u32(reg
->value
, 0, 32, value
);
238 static int armv7m_read_core_reg(struct target
*target
, int num
)
242 struct armv7m_core_reg
* armv7m_core_reg
;
243 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
245 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
246 return ERROR_INVALID_ARGUMENTS
;
248 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
249 retval
= armv7m
->load_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, ®_value
);
250 buf_set_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32, reg_value
);
251 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
252 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
257 static int armv7m_write_core_reg(struct target
*target
, int num
)
261 struct armv7m_core_reg
*armv7m_core_reg
;
262 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
264 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
265 return ERROR_INVALID_ARGUMENTS
;
267 reg_value
= buf_get_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32);
268 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
269 retval
= armv7m
->store_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, reg_value
);
270 if (retval
!= ERROR_OK
)
272 LOG_ERROR("JTAG failure");
273 armv7m
->core_cache
->reg_list
[num
].dirty
= armv7m
->core_cache
->reg_list
[num
].valid
;
274 return ERROR_JTAG_DEVICE_ERROR
;
276 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", num
, reg_value
);
277 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
278 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
283 /** Invalidates cache of core registers set up by armv7m_build_reg_cache(). */
284 int armv7m_invalidate_core_regs(struct target
*target
)
286 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
289 for (i
= 0; i
< armv7m
->core_cache
->num_regs
; i
++)
291 armv7m
->core_cache
->reg_list
[i
].valid
= 0;
292 armv7m
->core_cache
->reg_list
[i
].dirty
= 0;
299 * Returns generic ARM userspace registers to GDB.
300 * GDB doesn't quite understand that most ARMs don't have floating point
301 * hardware, so this also fakes a set of long-obsolete FPA registers that
302 * are not used in EABI based software stacks.
304 int armv7m_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
306 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
310 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
313 * GDB register packet format for ARM:
314 * - the first 16 registers are r0..r15
315 * - (obsolete) 8 FPA registers
316 * - (obsolete) FPA status
319 for (i
= 0; i
< 16; i
++)
321 (*reg_list
)[i
] = &armv7m
->core_cache
->reg_list
[i
];
324 for (i
= 16; i
< 24; i
++)
326 (*reg_list
)[i
] = &armv7m_gdb_dummy_fp_reg
;
329 (*reg_list
)[24] = &armv7m_gdb_dummy_fps_reg
;
331 #ifdef ARMV7_GDB_HACKS
332 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
333 (*reg_list
)[25] = &armv7m_gdb_dummy_cpsr_reg
;
335 /* ARMV7M is always in thumb mode, try to make GDB understand this
336 * if it does not support this arch */
337 *((char*)armv7m
->core_cache
->reg_list
[15].value
) |= 1;
339 (*reg_list
)[25] = &armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
];
345 /* run to exit point. return error if exit point was not reached. */
346 static int armv7m_run_and_wait(struct target
*target
, uint32_t entry_point
, int timeout_ms
, uint32_t exit_point
, struct armv7m_common
*armv7m
)
350 /* This code relies on the target specific resume() and poll()->debug_entry()
351 * sequence to write register values to the processor and the read them back */
352 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
357 retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
);
358 /* If the target fails to halt due to the breakpoint, force a halt */
359 if (retval
!= ERROR_OK
|| target
->state
!= TARGET_HALTED
)
361 if ((retval
= target_halt(target
)) != ERROR_OK
)
363 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
367 return ERROR_TARGET_TIMEOUT
;
370 armv7m
->load_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 15, &pc
);
371 if (pc
!= exit_point
)
373 LOG_DEBUG("failed algoritm halted at 0x%" PRIx32
" ", pc
);
374 return ERROR_TARGET_TIMEOUT
;
380 /** Runs a Thumb algorithm in the target. */
381 int armv7m_run_algorithm(struct target
*target
,
382 int num_mem_params
, struct mem_param
*mem_params
,
383 int num_reg_params
, struct reg_param
*reg_params
,
384 uint32_t entry_point
, uint32_t exit_point
,
385 int timeout_ms
, void *arch_info
)
387 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
388 struct armv7m_algorithm
*armv7m_algorithm_info
= arch_info
;
389 enum armv7m_mode core_mode
= armv7m
->core_mode
;
390 int retval
= ERROR_OK
;
392 uint32_t context
[ARMV7M_NUM_REGS
];
394 if (armv7m_algorithm_info
->common_magic
!= ARMV7M_COMMON_MAGIC
)
396 LOG_ERROR("current target isn't an ARMV7M target");
397 return ERROR_TARGET_INVALID
;
400 if (target
->state
!= TARGET_HALTED
)
402 LOG_WARNING("target not halted");
403 return ERROR_TARGET_NOT_HALTED
;
406 /* refresh core register cache */
407 /* Not needed if core register cache is always consistent with target process state */
408 for (i
= 0; i
< ARMV7M_NUM_REGS
; i
++)
410 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
411 armv7m
->read_core_reg(target
, i
);
412 context
[i
] = buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
415 for (i
= 0; i
< num_mem_params
; i
++)
417 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
421 for (i
= 0; i
< num_reg_params
; i
++)
423 struct reg
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
424 // uint32_t regvalue;
428 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
432 if (reg
->size
!= reg_params
[i
].size
)
434 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
438 // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
439 armv7m_set_core_reg(reg
, reg_params
[i
].value
);
442 if (armv7m_algorithm_info
->core_mode
!= ARMV7M_MODE_ANY
)
444 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info
->core_mode
);
445 buf_set_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
,
446 0, 1, armv7m_algorithm_info
->core_mode
);
447 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].dirty
= 1;
448 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].valid
= 1;
451 /* REVISIT speed things up (3% or so in one case) by requiring
452 * algorithms to include a BKPT instruction at each exit point.
453 * This eliminates overheads of adding/removing a breakpoint.
456 /* ARMV7M always runs in Thumb state */
457 if ((retval
= breakpoint_add(target
, exit_point
, 2, BKPT_SOFT
)) != ERROR_OK
)
459 LOG_ERROR("can't add breakpoint to finish algorithm execution");
460 return ERROR_TARGET_FAILURE
;
463 retval
= armv7m_run_and_wait(target
, entry_point
, timeout_ms
, exit_point
, armv7m
);
465 breakpoint_remove(target
, exit_point
);
467 if (retval
!= ERROR_OK
)
472 /* Read memory values to mem_params[] */
473 for (i
= 0; i
< num_mem_params
; i
++)
475 if (mem_params
[i
].direction
!= PARAM_OUT
)
476 if ((retval
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
482 /* Copy core register values to reg_params[] */
483 for (i
= 0; i
< num_reg_params
; i
++)
485 if (reg_params
[i
].direction
!= PARAM_OUT
)
487 struct reg
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
491 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
495 if (reg
->size
!= reg_params
[i
].size
)
497 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
501 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
505 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
508 regvalue
= buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
509 if (regvalue
!= context
[i
])
511 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
,
512 armv7m
->core_cache
->reg_list
[i
].name
, context
[i
]);
513 buf_set_u32(armv7m
->core_cache
->reg_list
[i
].value
,
515 armv7m
->core_cache
->reg_list
[i
].valid
= 1;
516 armv7m
->core_cache
->reg_list
[i
].dirty
= 1;
520 armv7m
->core_mode
= core_mode
;
525 /** Logs summary of ARMv7-M state for a halted target. */
526 int armv7m_arch_state(struct target
*target
)
528 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
531 ctrl
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
, 0, 32);
532 sp
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_R13
].value
, 0, 32);
534 LOG_USER("target halted due to %s, current mode: %s %s\n"
535 "xPSR: %#8.8" PRIx32
" pc: %#8.8" PRIx32
" %csp: %#8.8" PRIx32
,
536 Jim_Nvp_value2name_simple(nvp_target_debug_reason
,
537 target
->debug_reason
)->name
,
538 armv7m_mode_strings
[armv7m
->core_mode
],
539 armv7m_exception_string(armv7m
->exception_number
),
540 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32),
541 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_PC
].value
, 0, 32),
542 (ctrl
& 0x02) ? 'p' : 'm',
548 /** Builds cache of architecturally defined registers. */
549 struct reg_cache
*armv7m_build_reg_cache(struct target
*target
)
551 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
552 int num_regs
= ARMV7M_NUM_REGS
;
553 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
554 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
555 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
556 struct armv7m_core_reg
*arch_info
= calloc(num_regs
, sizeof(struct armv7m_core_reg
));
559 if (armv7m_core_reg_arch_type
== -1)
561 armv7m_core_reg_arch_type
= register_reg_arch_type(armv7m_get_core_reg
, armv7m_set_core_reg
);
564 register_init_dummy(&armv7m_gdb_dummy_fps_reg
);
565 #ifdef ARMV7_GDB_HACKS
566 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg
);
568 register_init_dummy(&armv7m_gdb_dummy_fp_reg
);
570 /* Build the process context cache */
571 cache
->name
= "arm v7m registers";
573 cache
->reg_list
= reg_list
;
574 cache
->num_regs
= num_regs
;
576 armv7m
->core_cache
= cache
;
578 for (i
= 0; i
< num_regs
; i
++)
580 arch_info
[i
].num
= armv7m_regs
[i
].id
;
581 arch_info
[i
].target
= target
;
582 arch_info
[i
].armv7m_common
= armv7m
;
583 reg_list
[i
].name
= armv7m_regs
[i
].name
;
584 reg_list
[i
].size
= armv7m_regs
[i
].bits
;
585 reg_list
[i
].value
= calloc(1, 4);
586 reg_list
[i
].dirty
= 0;
587 reg_list
[i
].valid
= 0;
588 reg_list
[i
].arch_type
= armv7m_core_reg_arch_type
;
589 reg_list
[i
].arch_info
= &arch_info
[i
];
595 /** Sets up target as a generic ARMv7-M core */
596 int armv7m_init_arch_info(struct target
*target
, struct armv7m_common
*armv7m
)
598 /* register arch-specific functions */
600 target
->arch_info
= armv7m
;
601 armv7m
->read_core_reg
= armv7m_read_core_reg
;
602 armv7m
->write_core_reg
= armv7m_write_core_reg
;
607 /** Generates a CRC32 checksum of a memory region. */
608 int armv7m_checksum_memory(struct target
*target
,
609 uint32_t address
, uint32_t count
, uint32_t* checksum
)
611 struct working_area
*crc_algorithm
;
612 struct armv7m_algorithm armv7m_info
;
613 struct reg_param reg_params
[2];
616 static const uint16_t cortex_m3_crc_code
[] = {
617 0x4602, /* mov r2, r0 */
618 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
619 0x460B, /* mov r3, r1 */
620 0xF04F, 0x0400, /* mov r4, #0 */
621 0xE013, /* b ncomp */
623 0x5D11, /* ldrb r1, [r2, r4] */
624 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
625 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
627 0xF04F, 0x0500, /* mov r5, #0 */
629 0x2800, /* cmp r0, #0 */
630 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
631 0xF105, 0x0501, /* add r5, r5, #1 */
632 0x4630, /* mov r0, r6 */
634 0xEA86, 0x0007, /* eor r0, r6, r7 */
635 0x2D08, /* cmp r5, #8 */
636 0xD1F4, /* bne loop */
638 0xF104, 0x0401, /* add r4, r4, #1 */
640 0x429C, /* cmp r4, r3 */
641 0xD1E9, /* bne nbyte */
644 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
649 if (target_alloc_working_area(target
, sizeof(cortex_m3_crc_code
), &crc_algorithm
) != ERROR_OK
)
651 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
654 /* convert flash writing code into a buffer in target endianness */
655 for (i
= 0; i
< (sizeof(cortex_m3_crc_code
)/sizeof(uint16_t)); i
++)
656 if ((retval
= target_write_u16(target
, crc_algorithm
->address
+ i
*sizeof(uint16_t), cortex_m3_crc_code
[i
])) != ERROR_OK
)
661 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
662 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
664 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
665 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
667 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
668 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
670 if ((retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
671 crc_algorithm
->address
, crc_algorithm
->address
+ (sizeof(cortex_m3_crc_code
)-6), 20000, &armv7m_info
)) != ERROR_OK
)
673 LOG_ERROR("error executing cortex_m3 crc algorithm");
674 destroy_reg_param(®_params
[0]);
675 destroy_reg_param(®_params
[1]);
676 target_free_working_area(target
, crc_algorithm
);
680 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
682 destroy_reg_param(®_params
[0]);
683 destroy_reg_param(®_params
[1]);
685 target_free_working_area(target
, crc_algorithm
);
690 /** Checks whether a memory region is zeroed. */
691 int armv7m_blank_check_memory(struct target
*target
,
692 uint32_t address
, uint32_t count
, uint32_t* blank
)
694 struct working_area
*erase_check_algorithm
;
695 struct reg_param reg_params
[3];
696 struct armv7m_algorithm armv7m_info
;
700 static const uint16_t erase_check_code
[] =
703 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
704 0xEA02, 0x0203, /* and r2, r2, r3 */
705 0x3901, /* subs r1, r1, #1 */
706 0xD1F9, /* bne loop */
711 /* make sure we have a working area */
712 if (target_alloc_working_area(target
, sizeof(erase_check_code
), &erase_check_algorithm
) != ERROR_OK
)
714 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
717 /* convert flash writing code into a buffer in target endianness */
718 for (i
= 0; i
< (sizeof(erase_check_code
)/sizeof(uint16_t)); i
++)
719 target_write_u16(target
, erase_check_algorithm
->address
+ i
*sizeof(uint16_t), erase_check_code
[i
]);
721 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
722 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
724 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
725 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
727 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
728 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
730 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
731 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
733 if ((retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
734 erase_check_algorithm
->address
, erase_check_algorithm
->address
+ (sizeof(erase_check_code
)-2), 10000, &armv7m_info
)) != ERROR_OK
)
736 destroy_reg_param(®_params
[0]);
737 destroy_reg_param(®_params
[1]);
738 destroy_reg_param(®_params
[2]);
739 target_free_working_area(target
, erase_check_algorithm
);
743 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
745 destroy_reg_param(®_params
[0]);
746 destroy_reg_param(®_params
[1]);
747 destroy_reg_param(®_params
[2]);
749 target_free_working_area(target
, erase_check_algorithm
);
754 /*--------------------------------------------------------------------------*/
757 * Only stuff below this line should need to verify that its target
758 * is an ARMv7-M node.
760 * FIXME yet none of it _does_ verify target types yet!
765 * Return the debug ap baseaddress in hexadecimal;
766 * no extra output to simplify script processing
768 COMMAND_HANDLER(handle_dap_baseaddr_command
)
770 struct target
*target
= get_current_target(cmd_ctx
);
771 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
772 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
773 uint32_t apsel
, apselsave
, baseaddr
;
776 apselsave
= swjdp
->apsel
;
779 apsel
= swjdp
->apsel
;
782 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
785 return ERROR_COMMAND_SYNTAX_ERROR
;
788 if (apselsave
!= apsel
)
789 dap_ap_select(swjdp
, apsel
);
791 dap_ap_read_reg_u32(swjdp
, 0xF8, &baseaddr
);
792 retval
= swjdp_transaction_endcheck(swjdp
);
793 command_print(cmd_ctx
, "0x%8.8" PRIx32
"", baseaddr
);
795 if (apselsave
!= apsel
)
796 dap_ap_select(swjdp
, apselsave
);
802 * Return the debug ap id in hexadecimal;
803 * no extra output to simplify script processing
805 COMMAND_HANDLER(handle_dap_apid_command
)
807 struct target
*target
= get_current_target(cmd_ctx
);
808 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
809 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
811 return CALL_COMMAND_HANDLER(dap_apid_command
, swjdp
);
814 COMMAND_HANDLER(handle_dap_apsel_command
)
816 struct target
*target
= get_current_target(cmd_ctx
);
817 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
818 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
820 return CALL_COMMAND_HANDLER(dap_apsel_command
, swjdp
);
823 COMMAND_HANDLER(handle_dap_memaccess_command
)
825 struct target
*target
= get_current_target(cmd_ctx
);
826 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
827 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
829 return CALL_COMMAND_HANDLER(dap_memaccess_command
, swjdp
);
833 COMMAND_HANDLER(handle_dap_info_command
)
835 struct target
*target
= get_current_target(cmd_ctx
);
836 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
837 struct swjdp_common
*swjdp
= &armv7m
->swjdp_info
;
842 apsel
= swjdp
->apsel
;
845 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
848 return ERROR_COMMAND_SYNTAX_ERROR
;
851 return dap_info_command(cmd_ctx
, swjdp
, apsel
);
854 /** Registers commands used to access DAP resources. */
855 int armv7m_register_commands(struct command_context
*cmd_ctx
)
857 struct command
*arm_adi_v5_dap_cmd
;
859 arm_adi_v5_dap_cmd
= register_command(cmd_ctx
, NULL
, "dap",
861 "cortex dap specific commands");
863 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "info",
864 handle_dap_info_command
, COMMAND_EXEC
,
865 "Displays dap info for ap [num],"
866 "default currently selected AP");
867 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apsel",
868 handle_dap_apsel_command
, COMMAND_EXEC
,
869 "Select a different AP [num] (default 0)");
870 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apid",
871 handle_dap_apid_command
, COMMAND_EXEC
,
872 "Displays id reg from AP [num], "
873 "default currently selected AP");
874 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "baseaddr",
875 handle_dap_baseaddr_command
, COMMAND_EXEC
,
876 "Displays debug base address from AP [num],"
877 "default currently selected AP");
878 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "memaccess",
879 handle_dap_memaccess_command
, COMMAND_EXEC
,
880 "set/get number of extra tck for mem-ap "
881 "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)