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
)
140 /* get pointers to arch-specific information */
141 armv7m_common_t
*armv7m
= target
->arch_info
;
145 if (armv7m
->pre_restore_context
)
146 armv7m
->pre_restore_context(target
);
148 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
150 if (armv7m
->core_cache
->reg_list
[i
].dirty
)
152 armv7m
->write_core_reg(target
, i
);
156 if (armv7m
->post_restore_context
)
157 armv7m
->post_restore_context(target
);
162 /* Core state functions */
165 * Maps ISR number (from xPSR) to name.
166 * Note that while names and meanings for the first sixteen are standardized
167 * (with zero not a true exception), external interrupts are only numbered.
168 * They are assigned by vendors, which generally assign different numbers to
169 * peripherals (such as UART0 or a USB peripheral controller).
171 char *armv7m_exception_string(int number
)
173 static char enamebuf
[32];
175 if ((number
< 0) | (number
> 511))
176 return "Invalid exception";
178 return armv7m_exception_strings
[number
];
179 sprintf(enamebuf
, "External Interrupt(%i)", number
- 16);
183 static int armv7m_get_core_reg(reg_t
*reg
)
186 armv7m_core_reg_t
*armv7m_reg
= reg
->arch_info
;
187 target_t
*target
= armv7m_reg
->target
;
188 armv7m_common_t
*armv7m_target
= target
->arch_info
;
190 if (target
->state
!= TARGET_HALTED
)
192 return ERROR_TARGET_NOT_HALTED
;
195 retval
= armv7m_target
->read_core_reg(target
, armv7m_reg
->num
);
200 static int armv7m_set_core_reg(reg_t
*reg
, uint8_t *buf
)
202 armv7m_core_reg_t
*armv7m_reg
= reg
->arch_info
;
203 target_t
*target
= armv7m_reg
->target
;
204 uint32_t value
= buf_get_u32(buf
, 0, 32);
206 if (target
->state
!= TARGET_HALTED
)
208 return ERROR_TARGET_NOT_HALTED
;
211 buf_set_u32(reg
->value
, 0, 32, value
);
218 static int armv7m_read_core_reg(struct target_s
*target
, int num
)
222 armv7m_core_reg_t
* armv7m_core_reg
;
224 /* get pointers to arch-specific information */
225 armv7m_common_t
*armv7m
= target
->arch_info
;
227 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
228 return ERROR_INVALID_ARGUMENTS
;
230 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
231 retval
= armv7m
->load_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, ®_value
);
232 buf_set_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32, reg_value
);
233 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
234 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
239 static int armv7m_write_core_reg(struct target_s
*target
, int num
)
243 armv7m_core_reg_t
*armv7m_core_reg
;
245 /* get pointers to arch-specific information */
246 armv7m_common_t
*armv7m
= target
->arch_info
;
248 if ((num
< 0) || (num
>= ARMV7M_NUM_REGS
))
249 return ERROR_INVALID_ARGUMENTS
;
251 reg_value
= buf_get_u32(armv7m
->core_cache
->reg_list
[num
].value
, 0, 32);
252 armv7m_core_reg
= armv7m
->core_cache
->reg_list
[num
].arch_info
;
253 retval
= armv7m
->store_core_reg_u32(target
, armv7m_core_reg
->type
, armv7m_core_reg
->num
, reg_value
);
254 if (retval
!= ERROR_OK
)
256 LOG_ERROR("JTAG failure");
257 armv7m
->core_cache
->reg_list
[num
].dirty
= armv7m
->core_cache
->reg_list
[num
].valid
;
258 return ERROR_JTAG_DEVICE_ERROR
;
260 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", num
, reg_value
);
261 armv7m
->core_cache
->reg_list
[num
].valid
= 1;
262 armv7m
->core_cache
->reg_list
[num
].dirty
= 0;
267 /** Invalidates cache of core registers set up by armv7m_build_reg_cache(). */
268 int armv7m_invalidate_core_regs(target_t
*target
)
270 /* get pointers to arch-specific information */
271 armv7m_common_t
*armv7m
= target
->arch_info
;
274 for (i
= 0; i
< armv7m
->core_cache
->num_regs
; i
++)
276 armv7m
->core_cache
->reg_list
[i
].valid
= 0;
277 armv7m
->core_cache
->reg_list
[i
].dirty
= 0;
284 * Returns generic ARM userspace registers to GDB.
285 * GDB doesn't quite understand that most ARMs don't have floating point
286 * hardware, so this also fakes a set of long-obsolete FPA registers that
287 * are not used in EABI based software stacks.
289 int armv7m_get_gdb_reg_list(target_t
*target
, reg_t
**reg_list
[], int *reg_list_size
)
291 /* get pointers to arch-specific information */
292 armv7m_common_t
*armv7m
= target
->arch_info
;
296 *reg_list
= malloc(sizeof(reg_t
*) * (*reg_list_size
));
299 * GDB register packet format for ARM:
300 * - the first 16 registers are r0..r15
301 * - (obsolete) 8 FPA registers
302 * - (obsolete) FPA status
305 for (i
= 0; i
< 16; i
++)
307 (*reg_list
)[i
] = &armv7m
->core_cache
->reg_list
[i
];
310 for (i
= 16; i
< 24; i
++)
312 (*reg_list
)[i
] = &armv7m_gdb_dummy_fp_reg
;
315 (*reg_list
)[24] = &armv7m_gdb_dummy_fps_reg
;
317 #ifdef ARMV7_GDB_HACKS
318 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
319 (*reg_list
)[25] = &armv7m_gdb_dummy_cpsr_reg
;
321 /* ARMV7M is always in thumb mode, try to make GDB understand this
322 * if it does not support this arch */
323 *((char*)armv7m
->core_cache
->reg_list
[15].value
) |= 1;
325 (*reg_list
)[25] = &armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
];
331 /* run to exit point. return error if exit point was not reached. */
332 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
)
336 /* This code relies on the target specific resume() and poll()->debug_entry()
337 * sequence to write register values to the processor and the read them back */
338 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
343 retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
);
344 /* If the target fails to halt due to the breakpoint, force a halt */
345 if (retval
!= ERROR_OK
|| target
->state
!= TARGET_HALTED
)
347 if ((retval
= target_halt(target
)) != ERROR_OK
)
349 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
353 return ERROR_TARGET_TIMEOUT
;
356 armv7m
->load_core_reg_u32(target
, ARMV7M_REGISTER_CORE_GP
, 15, &pc
);
357 if (pc
!= exit_point
)
359 LOG_DEBUG("failed algoritm halted at 0x%" PRIx32
" ", pc
);
360 return ERROR_TARGET_TIMEOUT
;
366 /** Runs a Thumb algorithm in the target. */
367 int armv7m_run_algorithm(struct target_s
*target
,
368 int num_mem_params
, mem_param_t
*mem_params
,
369 int num_reg_params
, reg_param_t
*reg_params
,
370 uint32_t entry_point
, uint32_t exit_point
,
371 int timeout_ms
, void *arch_info
)
373 /* get pointers to arch-specific information */
374 armv7m_common_t
*armv7m
= target
->arch_info
;
375 armv7m_algorithm_t
*armv7m_algorithm_info
= arch_info
;
376 enum armv7m_mode core_mode
= armv7m
->core_mode
;
377 int retval
= ERROR_OK
;
379 uint32_t context
[ARMV7M_NUM_REGS
];
381 if (armv7m_algorithm_info
->common_magic
!= ARMV7M_COMMON_MAGIC
)
383 LOG_ERROR("current target isn't an ARMV7M target");
384 return ERROR_TARGET_INVALID
;
387 if (target
->state
!= TARGET_HALTED
)
389 LOG_WARNING("target not halted");
390 return ERROR_TARGET_NOT_HALTED
;
393 /* refresh core register cache */
394 /* Not needed if core register cache is always consistent with target process state */
395 for (i
= 0; i
< ARMV7M_NUM_REGS
; i
++)
397 if (!armv7m
->core_cache
->reg_list
[i
].valid
)
398 armv7m
->read_core_reg(target
, i
);
399 context
[i
] = buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
402 for (i
= 0; i
< num_mem_params
; i
++)
404 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
408 for (i
= 0; i
< num_reg_params
; i
++)
410 reg_t
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
411 // uint32_t regvalue;
415 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
419 if (reg
->size
!= reg_params
[i
].size
)
421 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
425 // regvalue = buf_get_u32(reg_params[i].value, 0, 32);
426 armv7m_set_core_reg(reg
, reg_params
[i
].value
);
429 if (armv7m_algorithm_info
->core_mode
!= ARMV7M_MODE_ANY
)
431 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info
->core_mode
);
432 buf_set_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
,
433 0, 1, armv7m_algorithm_info
->core_mode
);
434 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].dirty
= 1;
435 armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].valid
= 1;
438 /* REVISIT speed things up (3% or so in one case) by requiring
439 * algorithms to include a BKPT instruction at each exit point.
440 * This eliminates overheads of adding/removing a breakpoint.
443 /* ARMV7M always runs in Thumb state */
444 if ((retval
= breakpoint_add(target
, exit_point
, 2, BKPT_SOFT
)) != ERROR_OK
)
446 LOG_ERROR("can't add breakpoint to finish algorithm execution");
447 return ERROR_TARGET_FAILURE
;
450 retval
= armv7m_run_and_wait(target
, entry_point
, timeout_ms
, exit_point
, armv7m
);
452 breakpoint_remove(target
, exit_point
);
454 if (retval
!= ERROR_OK
)
459 /* Read memory values to mem_params[] */
460 for (i
= 0; i
< num_mem_params
; i
++)
462 if (mem_params
[i
].direction
!= PARAM_OUT
)
463 if ((retval
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
469 /* Copy core register values to reg_params[] */
470 for (i
= 0; i
< num_reg_params
; i
++)
472 if (reg_params
[i
].direction
!= PARAM_OUT
)
474 reg_t
*reg
= register_get_by_name(armv7m
->core_cache
, reg_params
[i
].reg_name
, 0);
478 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
482 if (reg
->size
!= reg_params
[i
].size
)
484 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
488 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
492 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--)
495 regvalue
= buf_get_u32(armv7m
->core_cache
->reg_list
[i
].value
, 0, 32);
496 if (regvalue
!= context
[i
])
498 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
,
499 armv7m
->core_cache
->reg_list
[i
].name
, context
[i
]);
500 buf_set_u32(armv7m
->core_cache
->reg_list
[i
].value
,
502 armv7m
->core_cache
->reg_list
[i
].valid
= 1;
503 armv7m
->core_cache
->reg_list
[i
].dirty
= 1;
507 armv7m
->core_mode
= core_mode
;
512 /** Logs summary of ARMv7-M state for a halted target. */
513 int armv7m_arch_state(struct target_s
*target
)
515 /* get pointers to arch-specific information */
516 armv7m_common_t
*armv7m
= target
->arch_info
;
519 ctrl
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
, 0, 32);
520 sp
= buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_R13
].value
, 0, 32);
522 LOG_USER("target halted due to %s, current mode: %s %s\n"
523 "xPSR: %#8.8" PRIx32
" pc: %#8.8" PRIx32
" %csp: %#8.8" PRIx32
,
524 Jim_Nvp_value2name_simple(nvp_target_debug_reason
,
525 target
->debug_reason
)->name
,
526 armv7m_mode_strings
[armv7m
->core_mode
],
527 armv7m_exception_string(armv7m
->exception_number
),
528 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
].value
, 0, 32),
529 buf_get_u32(armv7m
->core_cache
->reg_list
[ARMV7M_PC
].value
, 0, 32),
530 (ctrl
& 0x02) ? 'p' : 'm',
536 /** Builds cache of architecturally defined registers. */
537 reg_cache_t
*armv7m_build_reg_cache(target_t
*target
)
539 /* get pointers to arch-specific information */
540 armv7m_common_t
*armv7m
= target
->arch_info
;
542 int num_regs
= ARMV7M_NUM_REGS
;
543 reg_cache_t
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
544 reg_cache_t
*cache
= malloc(sizeof(reg_cache_t
));
545 reg_t
*reg_list
= calloc(num_regs
, sizeof(reg_t
));
546 armv7m_core_reg_t
*arch_info
= calloc(num_regs
, sizeof(armv7m_core_reg_t
));
549 if (armv7m_core_reg_arch_type
== -1)
551 armv7m_core_reg_arch_type
= register_reg_arch_type(armv7m_get_core_reg
, armv7m_set_core_reg
);
554 register_init_dummy(&armv7m_gdb_dummy_fps_reg
);
555 #ifdef ARMV7_GDB_HACKS
556 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg
);
558 register_init_dummy(&armv7m_gdb_dummy_fp_reg
);
560 /* Build the process context cache */
561 cache
->name
= "arm v7m registers";
563 cache
->reg_list
= reg_list
;
564 cache
->num_regs
= num_regs
;
566 armv7m
->core_cache
= cache
;
568 for (i
= 0; i
< num_regs
; i
++)
570 arch_info
[i
].num
= armv7m_regs
[i
].id
;
571 arch_info
[i
].target
= target
;
572 arch_info
[i
].armv7m_common
= armv7m
;
573 reg_list
[i
].name
= armv7m_regs
[i
].name
;
574 reg_list
[i
].size
= armv7m_regs
[i
].bits
;
575 reg_list
[i
].value
= calloc(1, 4);
576 reg_list
[i
].dirty
= 0;
577 reg_list
[i
].valid
= 0;
578 reg_list
[i
].bitfield_desc
= NULL
;
579 reg_list
[i
].num_bitfields
= 0;
580 reg_list
[i
].arch_type
= armv7m_core_reg_arch_type
;
581 reg_list
[i
].arch_info
= &arch_info
[i
];
587 /** Sets up target as a generic ARMv7-M core */
588 int armv7m_init_arch_info(target_t
*target
, armv7m_common_t
*armv7m
)
590 /* register arch-specific functions */
592 target
->arch_info
= armv7m
;
593 armv7m
->read_core_reg
= armv7m_read_core_reg
;
594 armv7m
->write_core_reg
= armv7m_write_core_reg
;
599 /** Generates a CRC32 checksum of a memory region. */
600 int armv7m_checksum_memory(struct target_s
*target
,
601 uint32_t address
, uint32_t count
, uint32_t* checksum
)
603 working_area_t
*crc_algorithm
;
604 armv7m_algorithm_t armv7m_info
;
605 reg_param_t reg_params
[2];
608 static const uint16_t cortex_m3_crc_code
[] = {
609 0x4602, /* mov r2, r0 */
610 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
611 0x460B, /* mov r3, r1 */
612 0xF04F, 0x0400, /* mov r4, #0 */
613 0xE013, /* b ncomp */
615 0x5D11, /* ldrb r1, [r2, r4] */
616 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
617 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
619 0xF04F, 0x0500, /* mov r5, #0 */
621 0x2800, /* cmp r0, #0 */
622 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
623 0xF105, 0x0501, /* add r5, r5, #1 */
624 0x4630, /* mov r0, r6 */
626 0xEA86, 0x0007, /* eor r0, r6, r7 */
627 0x2D08, /* cmp r5, #8 */
628 0xD1F4, /* bne loop */
630 0xF104, 0x0401, /* add r4, r4, #1 */
632 0x429C, /* cmp r4, r3 */
633 0xD1E9, /* bne nbyte */
636 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
641 if (target_alloc_working_area(target
, sizeof(cortex_m3_crc_code
), &crc_algorithm
) != ERROR_OK
)
643 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
646 /* convert flash writing code into a buffer in target endianness */
647 for (i
= 0; i
< (sizeof(cortex_m3_crc_code
)/sizeof(uint16_t)); i
++)
648 if ((retval
= target_write_u16(target
, crc_algorithm
->address
+ i
*sizeof(uint16_t), cortex_m3_crc_code
[i
])) != ERROR_OK
)
653 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
654 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
656 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
657 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
659 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
660 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
662 if ((retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
663 crc_algorithm
->address
, crc_algorithm
->address
+ (sizeof(cortex_m3_crc_code
)-6), 20000, &armv7m_info
)) != ERROR_OK
)
665 LOG_ERROR("error executing cortex_m3 crc algorithm");
666 destroy_reg_param(®_params
[0]);
667 destroy_reg_param(®_params
[1]);
668 target_free_working_area(target
, crc_algorithm
);
672 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
674 destroy_reg_param(®_params
[0]);
675 destroy_reg_param(®_params
[1]);
677 target_free_working_area(target
, crc_algorithm
);
682 /** Checks whether a memory region is zeroed. */
683 int armv7m_blank_check_memory(struct target_s
*target
,
684 uint32_t address
, uint32_t count
, uint32_t* blank
)
686 working_area_t
*erase_check_algorithm
;
687 reg_param_t reg_params
[3];
688 armv7m_algorithm_t armv7m_info
;
692 static const uint16_t erase_check_code
[] =
695 0xF810, 0x3B01, /* ldrb r3, [r0], #1 */
696 0xEA02, 0x0203, /* and r2, r2, r3 */
697 0x3901, /* subs r1, r1, #1 */
698 0xD1F9, /* bne loop */
703 /* make sure we have a working area */
704 if (target_alloc_working_area(target
, sizeof(erase_check_code
), &erase_check_algorithm
) != ERROR_OK
)
706 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
709 /* convert flash writing code into a buffer in target endianness */
710 for (i
= 0; i
< (sizeof(erase_check_code
)/sizeof(uint16_t)); i
++)
711 target_write_u16(target
, erase_check_algorithm
->address
+ i
*sizeof(uint16_t), erase_check_code
[i
]);
713 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
714 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
716 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
717 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
719 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
720 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
722 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
723 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
725 if ((retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
726 erase_check_algorithm
->address
, erase_check_algorithm
->address
+ (sizeof(erase_check_code
)-2), 10000, &armv7m_info
)) != ERROR_OK
)
728 destroy_reg_param(®_params
[0]);
729 destroy_reg_param(®_params
[1]);
730 destroy_reg_param(®_params
[2]);
731 target_free_working_area(target
, erase_check_algorithm
);
735 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
737 destroy_reg_param(®_params
[0]);
738 destroy_reg_param(®_params
[1]);
739 destroy_reg_param(®_params
[2]);
741 target_free_working_area(target
, erase_check_algorithm
);
747 * Return the debug ap baseaddress in hexadecimal;
748 * no extra output to simplify script processing
750 static int handle_dap_baseaddr_command(struct command_context_s
*cmd_ctx
,
751 char *cmd
, char **args
, int argc
)
753 target_t
*target
= get_current_target(cmd_ctx
);
754 armv7m_common_t
*armv7m
= target
->arch_info
;
755 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
756 uint32_t apsel
, apselsave
, baseaddr
;
759 apselsave
= swjdp
->apsel
;
762 apsel
= swjdp
->apsel
;
765 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
768 return ERROR_COMMAND_SYNTAX_ERROR
;
771 if (apselsave
!= apsel
)
772 dap_ap_select(swjdp
, apsel
);
774 dap_ap_read_reg_u32(swjdp
, 0xF8, &baseaddr
);
775 retval
= swjdp_transaction_endcheck(swjdp
);
776 command_print(cmd_ctx
, "0x%8.8" PRIx32
"", baseaddr
);
778 if (apselsave
!= apsel
)
779 dap_ap_select(swjdp
, apselsave
);
785 * Return the debug ap id in hexadecimal;
786 * no extra output to simplify script processing
788 static int handle_dap_apid_command(struct command_context_s
*cmd_ctx
,
789 char *cmd
, char **args
, int argc
)
791 target_t
*target
= get_current_target(cmd_ctx
);
792 armv7m_common_t
*armv7m
= target
->arch_info
;
793 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
795 return dap_apid_command(cmd_ctx
, swjdp
, args
, argc
);
798 static int handle_dap_apsel_command(struct command_context_s
*cmd_ctx
,
799 char *cmd
, char **args
, int argc
)
801 target_t
*target
= get_current_target(cmd_ctx
);
802 armv7m_common_t
*armv7m
= target
->arch_info
;
803 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
805 return dap_apsel_command(cmd_ctx
, swjdp
, args
, argc
);
808 static int handle_dap_memaccess_command(struct command_context_s
*cmd_ctx
,
809 char *cmd
, char **args
, int argc
)
811 target_t
*target
= get_current_target(cmd_ctx
);
812 armv7m_common_t
*armv7m
= target
->arch_info
;
813 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
815 return dap_memaccess_command(cmd_ctx
, swjdp
, args
, argc
);
819 static int handle_dap_info_command(struct command_context_s
*cmd_ctx
,
820 char *cmd
, char **args
, int argc
)
822 target_t
*target
= get_current_target(cmd_ctx
);
823 armv7m_common_t
*armv7m
= target
->arch_info
;
824 swjdp_common_t
*swjdp
= &armv7m
->swjdp_info
;
829 apsel
= swjdp
->apsel
;
832 COMMAND_PARSE_NUMBER(u32
, args
[0], apsel
);
835 return ERROR_COMMAND_SYNTAX_ERROR
;
838 return dap_info_command(cmd_ctx
, swjdp
, apsel
);
841 /** Registers commands used to access DAP resources. */
842 int armv7m_register_commands(struct command_context_s
*cmd_ctx
)
844 command_t
*arm_adi_v5_dap_cmd
;
846 arm_adi_v5_dap_cmd
= register_command(cmd_ctx
, NULL
, "dap",
848 "cortex dap specific commands");
850 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "info",
851 handle_dap_info_command
, COMMAND_EXEC
,
852 "Displays dap info for ap [num],"
853 "default currently selected AP");
854 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apsel",
855 handle_dap_apsel_command
, COMMAND_EXEC
,
856 "Select a different AP [num] (default 0)");
857 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "apid",
858 handle_dap_apid_command
, COMMAND_EXEC
,
859 "Displays id reg from AP [num], "
860 "default currently selected AP");
861 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "baseaddr",
862 handle_dap_baseaddr_command
, COMMAND_EXEC
,
863 "Displays debug base address from AP [num],"
864 "default currently selected AP");
865 register_command(cmd_ctx
, arm_adi_v5_dap_cmd
, "memaccess",
866 handle_dap_memaccess_command
, COMMAND_EXEC
,
867 "set/get number of extra tck for mem-ap "
868 "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)