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 static uint8_t armv7m_gdb_dummy_fp_value
[12] = {
61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 static reg_t armv7m_gdb_dummy_fp_reg
=
66 "GDB dummy floating-point register", armv7m_gdb_dummy_fp_value
, 0, 1, 96, NULL
, 0, NULL
, 0
69 static uint8_t armv7m_gdb_dummy_fps_value
[] = {0, 0, 0, 0};
71 static reg_t armv7m_gdb_dummy_fps_reg
=
73 "GDB dummy floating-point status register", armv7m_gdb_dummy_fps_value
, 0, 1, 32, NULL
, 0, NULL
, 0
76 #ifdef ARMV7_GDB_HACKS
77 uint8_t armv7m_gdb_dummy_cpsr_value
[] = {0, 0, 0, 0};
79 reg_t armv7m_gdb_dummy_cpsr_reg
=
81 "GDB dummy cpsr register", armv7m_gdb_dummy_cpsr_value
, 0, 1, 32, NULL
, 0, NULL
, 0
86 * These registers are not memory-mapped. The ARMv7-M profile includes
87 * memory mapped registers too, such as for the NVIC (interrupt controller)
88 * and SysTick (timer) modules; those can mostly be treated as peripherals.
90 * The ARMv6-M profile is almost identical in this respect, except that it
91 * doesn't include basepri or faultmask registers.
98 { ARMV7M_R0
, "r0", 32 },
99 { ARMV7M_R1
, "r1", 32 },
100 { ARMV7M_R2
, "r2", 32 },
101 { ARMV7M_R3
, "r3", 32 },
103 { ARMV7M_R4
, "r4", 32 },
104 { ARMV7M_R5
, "r5", 32 },
105 { ARMV7M_R6
, "r6", 32 },
106 { ARMV7M_R7
, "r7", 32 },
108 { ARMV7M_R8
, "r8", 32 },
109 { ARMV7M_R9
, "r9", 32 },
110 { ARMV7M_R10
, "r10", 32 },
111 { ARMV7M_R11
, "r11", 32 },
113 { ARMV7M_R12
, "r12", 32 },
114 { ARMV7M_R13
, "sp", 32 },
115 { ARMV7M_R14
, "lr", 32 },
116 { ARMV7M_PC
, "pc", 32 },
118 { ARMV7M_xPSR
, "xPSR", 32 },
119 { ARMV7M_MSP
, "msp", 32 },
120 { ARMV7M_PSP
, "psp", 32 },
122 { ARMV7M_PRIMASK
, "primask", 1 },
123 { ARMV7M_BASEPRI
, "basepri", 8 },
124 { ARMV7M_FAULTMASK
, "faultmask", 1 },
125 { ARMV7M_CONTROL
, "control", 2 },
128 #define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
130 static int armv7m_core_reg_arch_type
= -1;
133 * Restores target context using the cache of core registers set up
134 * by armv7m_build_reg_cache(), calling optional core-specific hooks.
136 int armv7m_restore_context(target_t
*target
)
139 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
143 if (armv7m
->pre_restore_context
)
144 armv7m
->pre_restore_context(target
);
146 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
148 if (armv7m
->core_cache
->reg_list
[i
].dirty
)
150 armv7m
->write_core_reg(target
, i
);
154 if (armv7m
->post_restore_context
)
155 armv7m
->post_restore_context(target
);
160 /* Core state functions */
163 * Maps ISR number (from xPSR) to name.
164 * Note that while names and meanings for the first sixteen are standardized
165 * (with zero not a true exception), external interrupts are only numbered.
166 * They are assigned by vendors, which generally assign different numbers to
167 * peripherals (such as UART0 or a USB peripheral controller).
169 char *armv7m_exception_string(int number
)
171 static char enamebuf
[32];
173 if ((number
< 0) | (number
> 511))
174 return "Invalid exception";
176 return armv7m_exception_strings
[number
];
177 sprintf(enamebuf
, "External Interrupt(%i)", number
- 16);
181 static int armv7m_get_core_reg(reg_t
*reg
)
184 armv7m_core_reg_t
*armv7m_reg
= reg
->arch_info
;
185 target_t
*target
= armv7m_reg
->target
;
186 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
188 if (target
->state
!= TARGET_HALTED
)
190 return ERROR_TARGET_NOT_HALTED
;
193 retval
= armv7m
->read_core_reg(target
, armv7m_reg
->num
);
198 static int armv7m_set_core_reg(reg_t
*reg
, uint8_t *buf
)
200 armv7m_core_reg_t
*armv7m_reg
= reg
->arch_info
;
201 target_t
*target
= armv7m_reg
->target
;
202 uint32_t value
= buf_get_u32(buf
, 0, 32);
204 if (target
->state
!= TARGET_HALTED
)
206 return ERROR_TARGET_NOT_HALTED
;
209 buf_set_u32(reg
->value
, 0, 32, value
);
216 static int armv7m_read_core_reg(struct target_s
*target
, int num
)
220 armv7m_core_reg_t
* armv7m_core_reg
;
221 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
223 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
224 return ERROR_INVALID_ARGUMENTS
;
226 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
227 retval
= armv7m
->load_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, ®_value
);
228 buf_set_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32, reg_value
);
229 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
230 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
235 static int armv7m_write_core_reg(struct target_s
*target
, int num
)
239 armv7m_core_reg_t
*armv7m_core_reg
;
240 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
242 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
243 return ERROR_INVALID_ARGUMENTS
;
245 reg_value
= buf_get_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32);
246 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
247 retval
= armv7m
->store_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, reg_value
);
248 if (retval
!= ERROR_OK
)
250 LOG_ERROR("JTAG failure");
251 armv7m
->core_cache
->reg_list
[num
].dirty
= armv7m
->core_cache
->reg_list
[num
].valid
;
252 return ERROR_JTAG_DEVICE_ERROR
;
254 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", num
, reg_value
);
255 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
256 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
261 /** Invalidates cache of core registers set up by armv7m_build_reg_cache(). */
262 int armv7m_invalidate_core_regs(target_t
*target
)
264 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
267 for (i
= 0; i
< armv7m
->core_cache
->num_regs
; i
++)
269 armv7m
->core_cache
->reg_list
[i
].valid
= 0;
270 armv7m
->core_cache
->reg_list
[i
].dirty
= 0;
277 * Returns generic ARM userspace registers to GDB.
278 * GDB doesn't quite understand that most ARMs don't have floating point
279 * hardware, so this also fakes a set of long-obsolete FPA registers that
280 * are not used in EABI based software stacks.
282 int armv7m_get_gdb_reg_list(target_t
*target
, reg_t
**reg_list
[], int *reg_list_size
)
284 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
288 *reg_list
= malloc(sizeof(reg_t
*) * (*reg_list_size
));
291 * GDB register packet format for ARM:
292 * - the first 16 registers are r0..r15
293 * - (obsolete) 8 FPA registers
294 * - (obsolete) FPA status
297 for (i
= 0; i
< 16; i
++)
299 (*reg_list
)[i
] = &armv7m
->core_cache
->reg_list
[i
];
302 for (i
= 16; i
< 24; i
++)
304 (*reg_list
)[i
] = &armv7m_gdb_dummy_fp_reg
;
307 (*reg_list
)[24] = &armv7m_gdb_dummy_fps_reg
;
309 #ifdef ARMV7_GDB_HACKS
310 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
311 (*reg_list
)[25] = &armv7m_gdb_dummy_cpsr_reg
;
313 /* ARMV7M is always in thumb mode, try to make GDB understand this
314 * if it does not support this arch */
315 *((char*)armv7m
->core_cache
->reg_list
[15].value
) |= 1;
317 (*reg_list
)[25] = &armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
];
323 /* run to exit point. return error if exit point was not reached. */
324 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
)
328 /* This code relies on the target specific resume() and poll()->debug_entry()
329 * sequence to write register values to the processor and the read them back */
330 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
335 retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
);
336 /* If the target fails to halt due to the breakpoint, force a halt */
337 if (retval
!= ERROR_OK
|| target
->state
!= TARGET_HALTED
)
339 if ((retval
= target_halt(target
)) != ERROR_OK
)
341 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
345 return ERROR_TARGET_TIMEOUT
;
348 armv7m
->load_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 15, &pc
);
349 if (pc
!= exit_point
)
351 LOG_DEBUG("failed algoritm halted at 0x%" PRIx32
" ", pc
);
352 return ERROR_TARGET_TIMEOUT
;
358 /** Runs a Thumb algorithm in the target. */
359 int armv7m_run_algorithm(struct target_s
*target
,
360 int num_mem_params
, mem_param_t
*mem_params
,
361 int num_reg_params
, reg_param_t
*reg_params
,
362 uint32_t entry_point
, uint32_t exit_point
,
363 int timeout_ms
, void *arch_info
)
365 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
366 armv7m_algorithm_t
*armv7m_algorithm_info
= arch_info
;
367 enum armv7m_mode core_mode
= armv7m
->core_mode
;
368 int retval
= ERROR_OK
;
370 uint32_t context
[ARMV7M_NUM_REGS
];
372 if (armv7m_algorithm_info
->common_magic
!= ARMV7M_COMMON_MAGIC
)
374 LOG_ERROR("current target isn't an ARMV7M target");
375 return ERROR_TARGET_INVALID
;
378 if (target
->state
!= TARGET_HALTED
)
380 LOG_WARNING("target not halted");
381 return ERROR_TARGET_NOT_HALTED
;
384 /* refresh core register cache */
385 /* Not needed if core register cache is always consistent with target process state */
386 for (i
= 0; i
< ARMV7M_NUM_REGS
; i
++)
388 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
389 armv7m
->read_core_reg(target
, i
);
390 context
[i
] = buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
393 for (i
= 0; i
< num_mem_params
; i
++)
395 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
399 for (i
= 0; i
< num_reg_params
; i
++)
401 reg_t
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
402 // uint32_t regvalue;
406 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
410 if (reg
->size
!= reg_params
[i
].size
)
412 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
416 // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
417 armv7m_set_core_reg(reg
, reg_params
[i
].value
);
420 if (armv7m_algorithm_info
->core_mode
!= ARMV7M_MODE_ANY
)
422 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info
->core_mode
);
423 buf_set_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
,
424 0, 1, armv7m_algorithm_info
->core_mode
);
425 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].dirty
= 1;
426 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].valid
= 1;
429 /* REVISIT speed things up (3% or so in one case) by requiring
430 * algorithms to include a BKPT instruction at each exit point.
431 * This eliminates overheads of adding/removing a breakpoint.
434 /* ARMV7M always runs in Thumb state */
435 if ((retval
= breakpoint_add(target
, exit_point
, 2, BKPT_SOFT
)) != ERROR_OK
)
437 LOG_ERROR("can't add breakpoint to finish algorithm execution");
438 return ERROR_TARGET_FAILURE
;
441 retval
= armv7m_run_and_wait(target
, entry_point
, timeout_ms
, exit_point
, armv7m
);
443 breakpoint_remove(target
, exit_point
);
445 if (retval
!= ERROR_OK
)
450 /* Read memory values to mem_params[] */
451 for (i
= 0; i
< num_mem_params
; i
++)
453 if (mem_params
[i
].direction
!= PARAM_OUT
)
454 if ((retval
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
460 /* Copy core register values to reg_params[] */
461 for (i
= 0; i
< num_reg_params
; i
++)
463 if (reg_params
[i
].direction
!= PARAM_OUT
)
465 reg_t
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
469 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
473 if (reg
->size
!= reg_params
[i
].size
)
475 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
479 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
483 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
486 regvalue
= buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
487 if (regvalue
!= context
[i
])
489 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
,
490 armv7m
->core_cache
->reg_list
[i
].name
, context
[i
]);
491 buf_set_u32(armv7m
->core_cache
->reg_list
[i
].value
,
493 armv7m
->core_cache
->reg_list
[i
].valid
= 1;
494 armv7m
->core_cache
->reg_list
[i
].dirty
= 1;
498 armv7m
->core_mode
= core_mode
;
503 /** Logs summary of ARMv7-M state for a halted target. */
504 int armv7m_arch_state(struct target_s
*target
)
506 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
509 ctrl
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
, 0, 32);
510 sp
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_R13
].value
, 0, 32);
512 LOG_USER("target halted due to %s, current mode: %s %s\n"
513 "xPSR: %#8.8" PRIx32
" pc: %#8.8" PRIx32
" %csp: %#8.8" PRIx32
,
514 Jim_Nvp_value2name_simple(nvp_target_debug_reason
,
515 target
->debug_reason
)->name
,
516 armv7m_mode_strings
[armv7m
->core_mode
],
517 armv7m_exception_string(armv7m
->exception_number
),
518 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32),
519 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_PC
].value
, 0, 32),
520 (ctrl
& 0x02) ? 'p' : 'm',
526 /** Builds cache of architecturally defined registers. */
527 reg_cache_t
*armv7m_build_reg_cache(target_t
*target
)
529 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
530 int num_regs
= ARMV7M_NUM_REGS
;
531 reg_cache_t
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
532 reg_cache_t
*cache
= malloc(sizeof(reg_cache_t
));
533 reg_t
*reg_list
= calloc(num_regs
, sizeof(reg_t
));
534 armv7m_core_reg_t
*arch_info
= calloc(num_regs
, sizeof(armv7m_core_reg_t
));
537 if (armv7m_core_reg_arch_type
== -1)
539 armv7m_core_reg_arch_type
= register_reg_arch_type(armv7m_get_core_reg
, armv7m_set_core_reg
);
542 register_init_dummy(&armv7m_gdb_dummy_fps_reg
);
543 #ifdef ARMV7_GDB_HACKS
544 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg
);
546 register_init_dummy(&armv7m_gdb_dummy_fp_reg
);
548 /* Build the process context cache */
549 cache
->name
= "arm v7m registers";
551 cache
->reg_list
= reg_list
;
552 cache
->num_regs
= num_regs
;
554 armv7m
->core_cache
= cache
;
556 for (i
= 0; i
< num_regs
; i
++)
558 arch_info
[i
].num
= armv7m_regs
[i
].id
;
559 arch_info
[i
].target
= target
;
560 arch_info
[i
].armv7m_common
= armv7m
;
561 reg_list
[i
].name
= armv7m_regs
[i
].name
;
562 reg_list
[i
].size
= armv7m_regs
[i
].bits
;
563 reg_list
[i
].value
= calloc(1, 4);
564 reg_list
[i
].dirty
= 0;
565 reg_list
[i
].valid
= 0;
566 reg_list
[i
].bitfield_desc
= NULL
;
567 reg_list
[i
].num_bitfields
= 0;
568 reg_list
[i
].arch_type
= armv7m_core_reg_arch_type
;
569 reg_list
[i
].arch_info
= &arch_info
[i
];
575 /** Sets up target as a generic ARMv7-M core */
576 int armv7m_init_arch_info(target_t
*target
, armv7m_common_t
*armv7m
)
578 /* register arch-specific functions */
580 target
->arch_info
= armv7m
;
581 armv7m
->read_core_reg
= armv7m_read_core_reg
;
582 armv7m
->write_core_reg
= armv7m_write_core_reg
;
587 /** Generates a CRC32 checksum of a memory region. */
588 int armv7m_checksum_memory(struct target_s
*target
,
589 uint32_t address
, uint32_t count
, uint32_t* checksum
)
591 working_area_t
*crc_algorithm
;
592 armv7m_algorithm_t armv7m_info
;
593 reg_param_t reg_params
[2];
596 static const uint16_t cortex_m3_crc_code
[] = {
597 0x4602, /* mov r2, r0 */
598 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
599 0x460B, /* mov r3, r1 */
600 0xF04F, 0x0400, /* mov r4, #0 */
601 0xE013, /* b ncomp */
603 0x5D11, /* ldrb r1, [r2, r4] */
604 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
605 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
607 0xF04F, 0x0500, /* mov r5, #0 */
609 0x2800, /* cmp r0, #0 */
610 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
611 0xF105, 0x0501, /* add r5, r5, #1 */
612 0x4630, /* mov r0, r6 */
614 0xEA86, 0x0007, /* eor r0, r6, r7 */
615 0x2D08, /* cmp r5, #8 */
616 0xD1F4, /* bne loop */
618 0xF104, 0x0401, /* add r4, r4, #1 */
620 0x429C, /* cmp r4, r3 */
621 0xD1E9, /* bne nbyte */
624 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
629 if (target_alloc_working_area(target
, sizeof(cortex_m3_crc_code
), &crc_algorithm
) != ERROR_OK
)
631 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
634 /* convert flash writing code into a buffer in target endianness */
635 for (i
= 0; i
< (sizeof(cortex_m3_crc_code
)/sizeof(uint16_t)); i
++)
636 if ((retval
= target_write_u16(target
, crc_algorithm
->address
+ i
*sizeof(uint16_t), cortex_m3_crc_code
[i
])) != ERROR_OK
)
641 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
642 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
644 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
645 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
647 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
648 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
650 if ((retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
651 crc_algorithm
->address
, crc_algorithm
->address
+ (sizeof(cortex_m3_crc_code
)-6), 20000, &armv7m_info
)) != ERROR_OK
)
653 LOG_ERROR("error executing cortex_m3 crc algorithm");
654 destroy_reg_param(®_params
[0]);
655 destroy_reg_param(®_params
[1]);
656 target_free_working_area(target
, crc_algorithm
);
660 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
662 destroy_reg_param(®_params
[0]);
663 destroy_reg_param(®_params
[1]);
665 target_free_working_area(target
, crc_algorithm
);
670 /** Checks whether a memory region is zeroed. */
671 int armv7m_blank_check_memory(struct target_s
*target
,
672 uint32_t address
, uint32_t count
, uint32_t* blank
)
674 working_area_t
*erase_check_algorithm
;
675 reg_param_t reg_params
[3];
676 armv7m_algorithm_t armv7m_info
;
680 static const uint16_t erase_check_code
[] =
683 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
684 0xEA02, 0x0203, /* and r2, r2, r3 */
685 0x3901, /* subs r1, r1, #1 */
686 0xD1F9, /* bne loop */
691 /* make sure we have a working area */
692 if (target_alloc_working_area(target
, sizeof(erase_check_code
), &erase_check_algorithm
) != ERROR_OK
)
694 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
697 /* convert flash writing code into a buffer in target endianness */
698 for (i
= 0; i
< (sizeof(erase_check_code
)/sizeof(uint16_t)); i
++)
699 target_write_u16(target
, erase_check_algorithm
->address
+ i
*sizeof(uint16_t), erase_check_code
[i
]);
701 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
702 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
704 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
705 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
707 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
708 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
710 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
711 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
713 if ((retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
714 erase_check_algorithm
->address
, erase_check_algorithm
->address
+ (sizeof(erase_check_code
)-2), 10000, &armv7m_info
)) != ERROR_OK
)
716 destroy_reg_param(®_params
[0]);
717 destroy_reg_param(®_params
[1]);
718 destroy_reg_param(®_params
[2]);
719 target_free_working_area(target
, erase_check_algorithm
);
723 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
725 destroy_reg_param(®_params
[0]);
726 destroy_reg_param(®_params
[1]);
727 destroy_reg_param(®_params
[2]);
729 target_free_working_area(target
, erase_check_algorithm
);
734 /*--------------------------------------------------------------------------*/
737 * Only stuff below this line should need to verify that its target
738 * is an ARMv7-M node.
740 * FIXME yet none of it _does_ verify target types yet!
745 * Return the debug ap baseaddress in hexadecimal;
746 * no extra output to simplify script processing
748 COMMAND_HANDLER(handle_dap_baseaddr_command
)
750 target_t
*target
= get_current_target(cmd_ctx
);
751 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
752 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
753 uint32_t apsel
, apselsave
, baseaddr
;
756 apselsave
= swjdp
->apsel
;
759 apsel
= swjdp
->apsel
;
762 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
765 return ERROR_COMMAND_SYNTAX_ERROR
;
768 if (apselsave
!= apsel
)
769 dap_ap_select(swjdp
, apsel
);
771 dap_ap_read_reg_u32(swjdp
, 0xF8, &baseaddr
);
772 retval
= swjdp_transaction_endcheck(swjdp
);
773 command_print(cmd_ctx
, "0x%8.8" PRIx32
"", baseaddr
);
775 if (apselsave
!= apsel
)
776 dap_ap_select(swjdp
, apselsave
);
782 * Return the debug ap id in hexadecimal;
783 * no extra output to simplify script processing
785 COMMAND_HANDLER(handle_dap_apid_command
)
787 target_t
*target
= get_current_target(cmd_ctx
);
788 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
789 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
791 return CALL_COMMAND_HANDLER(dap_apid_command
, swjdp
);
794 COMMAND_HANDLER(handle_dap_apsel_command
)
796 target_t
*target
= get_current_target(cmd_ctx
);
797 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
798 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
800 return CALL_COMMAND_HANDLER(dap_apsel_command
, swjdp
);
803 COMMAND_HANDLER(handle_dap_memaccess_command
)
805 target_t
*target
= get_current_target(cmd_ctx
);
806 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
807 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
809 return CALL_COMMAND_HANDLER(dap_memaccess_command
, swjdp
);
813 COMMAND_HANDLER(handle_dap_info_command
)
815 target_t
*target
= get_current_target(cmd_ctx
);
816 struct armv7m_common_s
*armv7m
= target_to_armv7m(target
);
817 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
822 apsel
= swjdp
->apsel
;
825 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
828 return ERROR_COMMAND_SYNTAX_ERROR
;
831 return dap_info_command(cmd_ctx
, swjdp
, apsel
);
834 /** Registers commands used to access DAP resources. */
835 int armv7m_register_commands(struct command_context_s
*cmd_ctx
)
837 command_t
*arm_adi_v5_dap_cmd
;
839 arm_adi_v5_dap_cmd
= register_command(cmd_ctx
, NULL
, "dap",
841 "cortex dap specific commands");
843 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "info",
844 handle_dap_info_command
, COMMAND_EXEC
,
845 "Displays dap info for ap [num],"
846 "default currently selected AP");
847 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apsel",
848 handle_dap_apsel_command
, COMMAND_EXEC
,
849 "Select a different AP [num] (default 0)");
850 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apid",
851 handle_dap_apid_command
, COMMAND_EXEC
,
852 "Displays id reg from AP [num], "
853 "default currently selected AP");
854 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "baseaddr",
855 handle_dap_baseaddr_command
, COMMAND_EXEC
,
856 "Displays debug base address from AP [num],"
857 "default currently selected AP");
858 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "memaccess",
859 handle_dap_memaccess_command
, COMMAND_EXEC
,
860 "set/get number of extra tck for mem-ap "
861 "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)