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 ***************************************************************************/
38 #include "breakpoints.h"
40 #include "algorithm.h"
44 #define _DEBUG_INSTRUCTION_EXECUTION_
47 static char *armv7m_exception_strings
[] = {
48 "", "Reset", "NMI", "HardFault",
49 "MemManage", "BusFault", "UsageFault", "RESERVED",
50 "RESERVED", "RESERVED", "RESERVED", "SVCall",
51 "DebugMonitor", "RESERVED", "PendSV", "SysTick"
54 /* PSP is used in some thread modes */
55 const int armv7m_psp_reg_map
[17] = {
56 ARMV7M_R0
, ARMV7M_R1
, ARMV7M_R2
, ARMV7M_R3
,
57 ARMV7M_R4
, ARMV7M_R5
, ARMV7M_R6
, ARMV7M_R7
,
58 ARMV7M_R8
, ARMV7M_R9
, ARMV7M_R10
, ARMV7M_R11
,
59 ARMV7M_R12
, ARMV7M_PSP
, ARMV7M_R14
, ARMV7M_PC
,
63 /* MSP is used in handler and some thread modes */
64 const int armv7m_msp_reg_map
[17] = {
65 ARMV7M_R0
, ARMV7M_R1
, ARMV7M_R2
, ARMV7M_R3
,
66 ARMV7M_R4
, ARMV7M_R5
, ARMV7M_R6
, ARMV7M_R7
,
67 ARMV7M_R8
, ARMV7M_R9
, ARMV7M_R10
, ARMV7M_R11
,
68 ARMV7M_R12
, ARMV7M_MSP
, ARMV7M_R14
, ARMV7M_PC
,
72 #ifdef ARMV7_GDB_HACKS
73 uint8_t armv7m_gdb_dummy_cpsr_value
[] = {0, 0, 0, 0};
75 struct reg armv7m_gdb_dummy_cpsr_reg
= {
76 .name
= "GDB dummy cpsr register",
77 .value
= armv7m_gdb_dummy_cpsr_value
,
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)
131 * Restores target context using the cache of core registers set up
132 * by armv7m_build_reg_cache(), calling optional core-specific hooks.
134 int armv7m_restore_context(struct target
*target
)
137 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
138 struct reg_cache
*cache
= armv7m
->arm
.core_cache
;
142 if (armv7m
->pre_restore_context
)
143 armv7m
->pre_restore_context(target
);
145 for (i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--) {
146 if (cache
->reg_list
[i
].dirty
) {
147 uint32_t value
= buf_get_u32(cache
->reg_list
[i
].value
, 0, 32);
148 armv7m
->arm
.write_core_reg(target
, &cache
->reg_list
[i
], i
, ARM_MODE_ANY
, value
);
155 /* Core state functions */
158 * Maps ISR number (from xPSR) to name.
159 * Note that while names and meanings for the first sixteen are standardized
160 * (with zero not a true exception), external interrupts are only numbered.
161 * They are assigned by vendors, which generally assign different numbers to
162 * peripherals (such as UART0 or a USB peripheral controller).
164 char *armv7m_exception_string(int number
)
166 static char enamebuf
[32];
168 if ((number
< 0) | (number
> 511))
169 return "Invalid exception";
171 return armv7m_exception_strings
[number
];
172 sprintf(enamebuf
, "External Interrupt(%i)", number
- 16);
176 static int armv7m_get_core_reg(struct reg
*reg
)
179 struct arm_reg
*armv7m_reg
= reg
->arch_info
;
180 struct target
*target
= armv7m_reg
->target
;
181 struct arm
*arm
= target_to_arm(target
);
183 if (target
->state
!= TARGET_HALTED
)
184 return ERROR_TARGET_NOT_HALTED
;
186 retval
= arm
->read_core_reg(target
, reg
, armv7m_reg
->num
, arm
->core_mode
);
191 static int armv7m_set_core_reg(struct reg
*reg
, uint8_t *buf
)
193 struct arm_reg
*armv7m_reg
= reg
->arch_info
;
194 struct target
*target
= armv7m_reg
->target
;
195 uint32_t value
= buf_get_u32(buf
, 0, 32);
197 if (target
->state
!= TARGET_HALTED
)
198 return ERROR_TARGET_NOT_HALTED
;
200 buf_set_u32(reg
->value
, 0, 32, value
);
207 static int armv7m_read_core_reg(struct target
*target
, struct reg
*r
,
208 int num
, enum arm_mode mode
)
212 struct arm_reg
*armv7m_core_reg
;
213 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
215 assert(num
< (int)armv7m
->arm
.core_cache
->num_regs
);
217 armv7m_core_reg
= armv7m
->arm
.core_cache
->reg_list
[num
].arch_info
;
218 retval
= armv7m
->load_core_reg_u32(target
,
219 armv7m_core_reg
->num
, ®_value
);
221 buf_set_u32(armv7m
->arm
.core_cache
->reg_list
[num
].value
, 0, 32, reg_value
);
222 armv7m
->arm
.core_cache
->reg_list
[num
].valid
= 1;
223 armv7m
->arm
.core_cache
->reg_list
[num
].dirty
= 0;
228 static int armv7m_write_core_reg(struct target
*target
, struct reg
*r
,
229 int num
, enum arm_mode mode
, uint32_t value
)
233 struct arm_reg
*armv7m_core_reg
;
234 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
236 assert(num
< (int)armv7m
->arm
.core_cache
->num_regs
);
238 reg_value
= buf_get_u32(armv7m
->arm
.core_cache
->reg_list
[num
].value
, 0, 32);
239 armv7m_core_reg
= armv7m
->arm
.core_cache
->reg_list
[num
].arch_info
;
240 retval
= armv7m
->store_core_reg_u32(target
,
241 armv7m_core_reg
->num
,
243 if (retval
!= ERROR_OK
) {
244 LOG_ERROR("JTAG failure");
245 armv7m
->arm
.core_cache
->reg_list
[num
].dirty
= armv7m
->arm
.core_cache
->reg_list
[num
].valid
;
246 return ERROR_JTAG_DEVICE_ERROR
;
249 LOG_DEBUG("write core reg %i value 0x%" PRIx32
"", num
, reg_value
);
250 armv7m
->arm
.core_cache
->reg_list
[num
].valid
= 1;
251 armv7m
->arm
.core_cache
->reg_list
[num
].dirty
= 0;
257 * Returns generic ARM userspace registers to GDB.
258 * GDB doesn't quite understand that most ARMs don't have floating point
259 * hardware, so this also fakes a set of long-obsolete FPA registers that
260 * are not used in EABI based software stacks.
262 int armv7m_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
264 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
268 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
271 * GDB register packet format for ARM:
272 * - the first 16 registers are r0..r15
273 * - (obsolete) 8 FPA registers
274 * - (obsolete) FPA status
277 for (i
= 0; i
< 16; i
++)
278 (*reg_list
)[i
] = &armv7m
->arm
.core_cache
->reg_list
[i
];
280 for (i
= 16; i
< 24; i
++)
281 (*reg_list
)[i
] = &arm_gdb_dummy_fp_reg
;
282 (*reg_list
)[24] = &arm_gdb_dummy_fps_reg
;
284 #ifdef ARMV7_GDB_HACKS
285 /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
286 (*reg_list
)[25] = &armv7m_gdb_dummy_cpsr_reg
;
288 /* ARMV7M is always in thumb mode, try to make GDB understand this
289 * if it does not support this arch */
290 *((char *)armv7m
->arm
.pc
->value
) |= 1;
292 (*reg_list
)[25] = &armv7m
->core_cache
->reg_list
[ARMV7M_xPSR
];
298 /** Runs a Thumb algorithm in the target. */
299 int armv7m_run_algorithm(struct target
*target
,
300 int num_mem_params
, struct mem_param
*mem_params
,
301 int num_reg_params
, struct reg_param
*reg_params
,
302 uint32_t entry_point
, uint32_t exit_point
,
303 int timeout_ms
, void *arch_info
)
307 retval
= armv7m_start_algorithm(target
,
308 num_mem_params
, mem_params
,
309 num_reg_params
, reg_params
,
310 entry_point
, exit_point
,
313 if (retval
== ERROR_OK
)
314 retval
= armv7m_wait_algorithm(target
,
315 num_mem_params
, mem_params
,
316 num_reg_params
, reg_params
,
317 exit_point
, timeout_ms
,
323 /** Starts a Thumb algorithm in the target. */
324 int armv7m_start_algorithm(struct target
*target
,
325 int num_mem_params
, struct mem_param
*mem_params
,
326 int num_reg_params
, struct reg_param
*reg_params
,
327 uint32_t entry_point
, uint32_t exit_point
,
330 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
331 struct armv7m_algorithm
*armv7m_algorithm_info
= arch_info
;
332 enum arm_mode core_mode
= armv7m
->arm
.core_mode
;
333 int retval
= ERROR_OK
;
335 /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
336 * at the exit point */
338 if (armv7m_algorithm_info
->common_magic
!= ARMV7M_COMMON_MAGIC
) {
339 LOG_ERROR("current target isn't an ARMV7M target");
340 return ERROR_TARGET_INVALID
;
343 if (target
->state
!= TARGET_HALTED
) {
344 LOG_WARNING("target not halted");
345 return ERROR_TARGET_NOT_HALTED
;
348 /* refresh core register cache
349 * Not needed if core register cache is always consistent with target process state */
350 for (unsigned i
= 0; i
< ARMV7M_NUM_REGS
; i
++) {
352 armv7m_algorithm_info
->context
[i
] = buf_get_u32(
353 armv7m
->arm
.core_cache
->reg_list
[i
].value
,
358 for (int i
= 0; i
< num_mem_params
; i
++) {
359 /* TODO: Write only out params */
360 retval
= target_write_buffer(target
, mem_params
[i
].address
,
362 mem_params
[i
].value
);
363 if (retval
!= ERROR_OK
)
367 for (int i
= 0; i
< num_reg_params
; i
++) {
369 register_get_by_name(armv7m
->arm
.core_cache
, reg_params
[i
].reg_name
, 0);
370 /* uint32_t regvalue; */
373 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
374 return ERROR_COMMAND_SYNTAX_ERROR
;
377 if (reg
->size
!= reg_params
[i
].size
) {
378 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
379 reg_params
[i
].reg_name
);
380 return ERROR_COMMAND_SYNTAX_ERROR
;
383 /* regvalue = buf_get_u32(reg_params[i].value, 0, 32); */
384 armv7m_set_core_reg(reg
, reg_params
[i
].value
);
387 if (armv7m_algorithm_info
->core_mode
!= ARM_MODE_ANY
) {
388 LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info
->core_mode
);
389 buf_set_u32(armv7m
->arm
.core_cache
->reg_list
[ARMV7M_CONTROL
].value
,
390 0, 1, armv7m_algorithm_info
->core_mode
);
391 armv7m
->arm
.core_cache
->reg_list
[ARMV7M_CONTROL
].dirty
= 1;
392 armv7m
->arm
.core_cache
->reg_list
[ARMV7M_CONTROL
].valid
= 1;
394 armv7m_algorithm_info
->core_mode
= core_mode
;
396 retval
= target_resume(target
, 0, entry_point
, 1, 1);
401 /** Waits for an algorithm in the target. */
402 int armv7m_wait_algorithm(struct target
*target
,
403 int num_mem_params
, struct mem_param
*mem_params
,
404 int num_reg_params
, struct reg_param
*reg_params
,
405 uint32_t exit_point
, int timeout_ms
,
408 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
409 struct armv7m_algorithm
*armv7m_algorithm_info
= arch_info
;
410 int retval
= ERROR_OK
;
413 /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
414 * at the exit point */
416 if (armv7m_algorithm_info
->common_magic
!= ARMV7M_COMMON_MAGIC
) {
417 LOG_ERROR("current target isn't an ARMV7M target");
418 return ERROR_TARGET_INVALID
;
421 retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
);
422 /* If the target fails to halt due to the breakpoint, force a halt */
423 if (retval
!= ERROR_OK
|| target
->state
!= TARGET_HALTED
) {
424 retval
= target_halt(target
);
425 if (retval
!= ERROR_OK
)
427 retval
= target_wait_state(target
, TARGET_HALTED
, 500);
428 if (retval
!= ERROR_OK
)
430 return ERROR_TARGET_TIMEOUT
;
433 armv7m
->load_core_reg_u32(target
, 15, &pc
);
434 if (exit_point
&& (pc
!= exit_point
)) {
435 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32
", expected 0x%" PRIx32
,
438 return ERROR_TARGET_TIMEOUT
;
441 /* Read memory values to mem_params[] */
442 for (int i
= 0; i
< num_mem_params
; i
++) {
443 if (mem_params
[i
].direction
!= PARAM_OUT
) {
444 retval
= target_read_buffer(target
, mem_params
[i
].address
,
446 mem_params
[i
].value
);
447 if (retval
!= ERROR_OK
)
452 /* Copy core register values to reg_params[] */
453 for (int i
= 0; i
< num_reg_params
; i
++) {
454 if (reg_params
[i
].direction
!= PARAM_OUT
) {
455 struct reg
*reg
= register_get_by_name(armv7m
->arm
.core_cache
,
456 reg_params
[i
].reg_name
,
460 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
461 return ERROR_COMMAND_SYNTAX_ERROR
;
464 if (reg
->size
!= reg_params
[i
].size
) {
466 "BUG: register '%s' size doesn't match reg_params[i].size",
467 reg_params
[i
].reg_name
);
468 return ERROR_COMMAND_SYNTAX_ERROR
;
471 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
475 for (int i
= ARMV7M_NUM_REGS
- 1; i
>= 0; i
--) {
477 regvalue
= buf_get_u32(armv7m
->arm
.core_cache
->reg_list
[i
].value
, 0, 32);
478 if (regvalue
!= armv7m_algorithm_info
->context
[i
]) {
479 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
,
480 armv7m
->arm
.core_cache
->reg_list
[i
].name
,
481 armv7m_algorithm_info
->context
[i
]);
482 buf_set_u32(armv7m
->arm
.core_cache
->reg_list
[i
].value
,
483 0, 32, armv7m_algorithm_info
->context
[i
]);
484 armv7m
->arm
.core_cache
->reg_list
[i
].valid
= 1;
485 armv7m
->arm
.core_cache
->reg_list
[i
].dirty
= 1;
489 armv7m
->arm
.core_mode
= armv7m_algorithm_info
->core_mode
;
494 /** Logs summary of ARMv7-M state for a halted target. */
495 int armv7m_arch_state(struct target
*target
)
497 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
498 struct arm
*arm
= &armv7m
->arm
;
501 ctrl
= buf_get_u32(arm
->core_cache
->reg_list
[ARMV7M_CONTROL
].value
, 0, 32);
502 sp
= buf_get_u32(arm
->core_cache
->reg_list
[ARMV7M_R13
].value
, 0, 32);
504 LOG_USER("target halted due to %s, current mode: %s %s\n"
505 "xPSR: %#8.8" PRIx32
" pc: %#8.8" PRIx32
" %csp: %#8.8" PRIx32
"%s",
506 debug_reason_name(target
),
507 arm_mode_name(arm
->core_mode
),
508 armv7m_exception_string(armv7m
->exception_number
),
509 buf_get_u32(arm
->cpsr
->value
, 0, 32),
510 buf_get_u32(arm
->pc
->value
, 0, 32),
511 (ctrl
& 0x02) ? 'p' : 'm',
513 arm
->is_semihosting
? ", semihosting" : "");
518 static const struct reg_arch_type armv7m_reg_type
= {
519 .get
= armv7m_get_core_reg
,
520 .set
= armv7m_set_core_reg
,
523 /** Builds cache of architecturally defined registers. */
524 struct reg_cache
*armv7m_build_reg_cache(struct target
*target
)
526 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
527 struct arm
*arm
= &armv7m
->arm
;
528 int num_regs
= ARMV7M_NUM_REGS
;
529 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
530 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
531 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
532 struct arm_reg
*arch_info
= calloc(num_regs
, sizeof(struct arm_reg
));
535 #ifdef ARMV7_GDB_HACKS
536 register_init_dummy(&armv7m_gdb_dummy_cpsr_reg
);
539 /* Build the process context cache */
540 cache
->name
= "arm v7m registers";
542 cache
->reg_list
= reg_list
;
543 cache
->num_regs
= num_regs
;
546 for (i
= 0; i
< num_regs
; i
++) {
547 arch_info
[i
].num
= armv7m_regs
[i
].id
;
548 arch_info
[i
].target
= target
;
549 arch_info
[i
].arm
= arm
;
551 reg_list
[i
].name
= armv7m_regs
[i
].name
;
552 reg_list
[i
].size
= armv7m_regs
[i
].bits
;
553 reg_list
[i
].value
= calloc(1, 4);
554 reg_list
[i
].dirty
= 0;
555 reg_list
[i
].valid
= 0;
556 reg_list
[i
].type
= &armv7m_reg_type
;
557 reg_list
[i
].arch_info
= &arch_info
[i
];
560 arm
->cpsr
= reg_list
+ ARMV7M_xPSR
;
561 arm
->pc
= reg_list
+ ARMV7M_PC
;
562 arm
->core_cache
= cache
;
566 static int armv7m_setup_semihosting(struct target
*target
, int enable
)
568 /* nothing todo for armv7m */
572 /** Sets up target as a generic ARMv7-M core */
573 int armv7m_init_arch_info(struct target
*target
, struct armv7m_common
*armv7m
)
575 struct arm
*arm
= &armv7m
->arm
;
577 armv7m
->common_magic
= ARMV7M_COMMON_MAGIC
;
578 armv7m
->fp_feature
= FP_NONE
;
580 arm
->core_type
= ARM_MODE_THREAD
;
581 arm
->arch_info
= armv7m
;
582 arm
->setup_semihosting
= armv7m_setup_semihosting
;
584 arm
->read_core_reg
= armv7m_read_core_reg
;
585 arm
->write_core_reg
= armv7m_write_core_reg
;
587 return arm_init_arch_info(target
, arm
);
590 /** Generates a CRC32 checksum of a memory region. */
591 int armv7m_checksum_memory(struct target
*target
,
592 uint32_t address
, uint32_t count
, uint32_t *checksum
)
594 struct working_area
*crc_algorithm
;
595 struct armv7m_algorithm armv7m_info
;
596 struct reg_param reg_params
[2];
599 /* see contrib/loaders/checksum/armv7m_crc.s for src */
601 static const uint8_t cortex_m3_crc_code
[] = {
603 0x02, 0x46, /* mov r2, r0 */
604 0x00, 0x20, /* movs r0, #0 */
605 0xC0, 0x43, /* mvns r0, r0 */
606 0x0A, 0x4E, /* ldr r6, CRC32XOR */
607 0x0B, 0x46, /* mov r3, r1 */
608 0x00, 0x24, /* movs r4, #0 */
609 0x0D, 0xE0, /* b ncomp */
611 0x11, 0x5D, /* ldrb r1, [r2, r4] */
612 0x09, 0x06, /* lsls r1, r1, #24 */
613 0x48, 0x40, /* eors r0, r0, r1 */
614 0x00, 0x25, /* movs r5, #0 */
616 0x00, 0x28, /* cmp r0, #0 */
617 0x02, 0xDA, /* bge notset */
618 0x40, 0x00, /* lsls r0, r0, #1 */
619 0x70, 0x40, /* eors r0, r0, r6 */
620 0x00, 0xE0, /* b cont */
622 0x40, 0x00, /* lsls r0, r0, #1 */
624 0x01, 0x35, /* adds r5, r5, #1 */
625 0x08, 0x2D, /* cmp r5, #8 */
626 0xF6, 0xD1, /* bne loop */
627 0x01, 0x34, /* adds r4, r4, #1 */
629 0x9C, 0x42, /* cmp r4, r3 */
630 0xEF, 0xD1, /* bne nbyte */
631 0x00, 0xBE, /* bkpt #0 */
632 0xB7, 0x1D, 0xC1, 0x04 /* CRC32XOR: .word 0x04c11db7 */
635 retval
= target_alloc_working_area(target
, sizeof(cortex_m3_crc_code
), &crc_algorithm
);
636 if (retval
!= ERROR_OK
)
639 retval
= target_write_buffer(target
, crc_algorithm
->address
,
640 sizeof(cortex_m3_crc_code
), (uint8_t *)cortex_m3_crc_code
);
641 if (retval
!= ERROR_OK
)
644 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
645 armv7m_info
.core_mode
= ARM_MODE_ANY
;
647 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
648 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
650 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
651 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
653 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
655 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
, crc_algorithm
->address
,
656 crc_algorithm
->address
+ (sizeof(cortex_m3_crc_code
) - 6),
657 timeout
, &armv7m_info
);
659 if (retval
== ERROR_OK
)
660 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
662 LOG_ERROR("error executing cortex_m3 crc algorithm");
664 destroy_reg_param(®_params
[0]);
665 destroy_reg_param(®_params
[1]);
668 target_free_working_area(target
, crc_algorithm
);
673 /** Checks whether a memory region is zeroed. */
674 int armv7m_blank_check_memory(struct target
*target
,
675 uint32_t address
, uint32_t count
, uint32_t *blank
)
677 struct working_area
*erase_check_algorithm
;
678 struct reg_param reg_params
[3];
679 struct armv7m_algorithm armv7m_info
;
682 /* see contrib/loaders/erase_check/armv7m_erase_check.s for src */
684 static const uint8_t erase_check_code
[] = {
686 0x03, 0x78, /* ldrb r3, [r0] */
687 0x01, 0x30, /* adds r0, #1 */
688 0x1A, 0x40, /* ands r2, r2, r3 */
689 0x01, 0x39, /* subs r1, r1, #1 */
690 0xFA, 0xD1, /* bne loop */
691 0x00, 0xBE /* bkpt #0 */
694 /* make sure we have a working area */
695 if (target_alloc_working_area(target
, sizeof(erase_check_code
),
696 &erase_check_algorithm
) != ERROR_OK
)
697 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
699 retval
= target_write_buffer(target
, erase_check_algorithm
->address
,
700 sizeof(erase_check_code
), (uint8_t *)erase_check_code
);
701 if (retval
!= ERROR_OK
)
704 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
705 armv7m_info
.core_mode
= ARM_MODE_ANY
;
707 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
708 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
710 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
711 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
713 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
714 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
716 retval
= target_run_algorithm(target
,
721 erase_check_algorithm
->address
,
722 erase_check_algorithm
->address
+ (sizeof(erase_check_code
) - 2),
726 if (retval
== ERROR_OK
)
727 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
729 destroy_reg_param(®_params
[0]);
730 destroy_reg_param(®_params
[1]);
731 destroy_reg_param(®_params
[2]);
733 target_free_working_area(target
, erase_check_algorithm
);
738 int armv7m_maybe_skip_bkpt_inst(struct target
*target
, bool *inst_found
)
740 struct armv7m_common
*armv7m
= target_to_armv7m(target
);
741 struct reg
*r
= armv7m
->arm
.pc
;
745 /* if we halted last time due to a bkpt instruction
746 * then we have to manually step over it, otherwise
747 * the core will break again */
749 if (target
->debug_reason
== DBG_REASON_BREAKPOINT
) {
751 uint32_t pc
= buf_get_u32(r
->value
, 0, 32);
754 if (target_read_u16(target
, pc
, &op
) == ERROR_OK
) {
755 if ((op
& 0xFF00) == 0xBE00) {
756 pc
= buf_get_u32(r
->value
, 0, 32) + 2;
757 buf_set_u32(r
->value
, 0, 32, pc
);
761 LOG_DEBUG("Skipping over BKPT instruction");
767 *inst_found
= result
;
772 const struct command_registration armv7m_command_handlers
[] = {
774 .chain
= arm_command_handlers
,
777 .chain
= dap_command_handlers
,
779 COMMAND_REGISTRATION_DONE
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)