- armv7m control register now set as dirty when switching context
[openocd.git] / src / target / armv7m.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2006 by Magnus Lundin *
6 * lundin@mlu.mine.nu *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "replacements.h"
28
29 #include "armv7m.h"
30 #include "register.h"
31 #include "target.h"
32 #include "log.h"
33 #include "jtag.h"
34 #include "arm_jtag.h"
35
36 #include <stdlib.h>
37 #include <string.h>
38
39 #if 0
40 #define _DEBUG_INSTRUCTION_EXECUTION_
41 #endif
42
43 char* armv7m_mode_strings[] =
44 {
45 "Handler", "Thread"
46 };
47
48 char* armv7m_state_strings[] =
49 {
50 "Thumb", "Debug"
51 };
52
53 char* armv7m_exception_strings[] =
54 {
55 "", "Reset", "NMI", "HardFault", "MemManage", "BusFault", "UsageFault", "RESERVED", "RESERVED", "RESERVED", "RESERVED",
56 "SVCall", "DebugMonitor", "RESERVED", "PendSV", "SysTick"
57 };
58
59 char* armv7m_core_reg_list[] =
60 {
61 /* Registers accessed through core debug */
62 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
63 "sp", "lr", "pc",
64 "xPSR", "msp", "psp",
65 /* Registers accessed through MSR instructions */
66 /* "apsr", "iapsr", "ipsr", "epsr", */
67 "primask", "basepri", "faultmask", "control"
68 };
69
70 char* armv7m_core_dbgreg_list[] =
71 {
72 /* Registers accessed through core debug */
73 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
74 "sp", "lr", "pc",
75 "xPSR", "msp", "psp",
76 /* Registers accessed through MSR instructions */
77 /* "dbg_apsr", "iapsr", "ipsr", "epsr", */
78 "primask", "basepri", "faultmask", "dbg_control"
79 };
80
81 u8 armv7m_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
82
83 reg_t armv7m_gdb_dummy_fp_reg =
84 {
85 "GDB dummy floating-point register", armv7m_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
86 };
87
88 armv7m_core_reg_t armv7m_core_reg_list_arch_info[] =
89 {
90 /* CORE_GP are accesible using the core debug registers */
91 {0, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
92 {1, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
93 {2, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
94 {3, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
95 {4, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
96 {5, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
97 {6, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
98 {7, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
99 {8, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
100 {9, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
101 {10, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
102 {11, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
103 {12, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
104 {13, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
105 {14, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
106 {15, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
107
108 {16, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* xPSR */
109 {17, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* MSP */
110 {18, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* PSP */
111
112 /* CORE_SP are accesible using MSR and MRS instructions */
113 #if 0
114 {0x00, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* APSR */
115 {0x01, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IAPSR */
116 {0x05, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* IPSR */
117 {0x06, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* EPSR */
118 #endif
119
120 {0x10, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* PRIMASK */
121 {0x11, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* BASEPRI */
122 {0x13, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* FAULTMASK */
123 {0x14, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL} /* CONTROL */
124 };
125
126 int armv7m_core_reg_arch_type = -1;
127
128 /* Keep different contexts for the process being debugged and debug algorithms */
129 enum armv7m_runcontext armv7m_get_context(target_t *target)
130 {
131 /* get pointers to arch-specific information */
132 armv7m_common_t *armv7m = target->arch_info;
133
134 if (armv7m->process_context == armv7m->core_cache)
135 return ARMV7M_PROCESS_CONTEXT;
136 if (armv7m->debug_context == armv7m->core_cache)
137 return ARMV7M_DEBUG_CONTEXT;
138
139 ERROR("Invalid runcontext");
140 exit(-1);
141 }
142
143 int armv7m_use_context(target_t *target, enum armv7m_runcontext new_ctx)
144 {
145 int i;
146 /* get pointers to arch-specific information */
147 armv7m_common_t *armv7m = target->arch_info;
148
149 if ((target->state != TARGET_HALTED) && (target->state != TARGET_RESET))
150 {
151 WARNING("target not halted, switch context ");
152 return ERROR_TARGET_NOT_HALTED;
153 }
154
155 if (new_ctx == armv7m_get_context(target))
156 return ERROR_OK;
157
158 switch (new_ctx)
159 {
160 case ARMV7M_PROCESS_CONTEXT:
161 armv7m->core_cache = armv7m->process_context;
162 break;
163 case ARMV7M_DEBUG_CONTEXT:
164 armv7m->core_cache = armv7m->debug_context;
165 break;
166 default:
167 ERROR("Invalid runcontext");
168 exit(-1);
169 }
170 /* Mark registers in new context as dirty to force reload when run */
171
172 for (i = 0; i < armv7m->core_cache->num_regs; i++)
173 {
174 armv7m->core_cache->reg_list[i].dirty = 1;
175 }
176
177 return ERROR_OK;
178 }
179
180 int armv7m_restore_context(target_t *target)
181 {
182 int i;
183
184 /* get pointers to arch-specific information */
185 armv7m_common_t *armv7m = target->arch_info;
186
187 DEBUG(" ");
188
189 if (armv7m->pre_restore_context)
190 armv7m->pre_restore_context(target);
191
192 for (i = ARMV7NUMCOREREGS-1; i >= 0; i--)
193 {
194 if (armv7m->core_cache->reg_list[i].dirty)
195 {
196 armv7m->write_core_reg(target, i);
197 }
198 }
199
200 if (armv7m->post_restore_context)
201 armv7m->post_restore_context(target);
202
203 return ERROR_OK;
204 }
205
206 /* Core state functions */
207 char *armv7m_exception_string(int number)
208 {
209 static char enamebuf[32];
210
211 if ((number < 0) | (number > 511))
212 return "Invalid exception";
213 if (number < 16)
214 return armv7m_exception_strings[number];
215 sprintf(enamebuf, "External Interrupt(%i)", number - 16);
216 return enamebuf;
217 }
218
219 int armv7m_get_core_reg(reg_t *reg)
220 {
221 int retval;
222 armv7m_core_reg_t *armv7m_reg = reg->arch_info;
223 target_t *target = armv7m_reg->target;
224 armv7m_common_t *armv7m_target = target->arch_info;
225
226 if (target->state != TARGET_HALTED)
227 {
228 return ERROR_TARGET_NOT_HALTED;
229 }
230
231 retval = armv7m_target->read_core_reg(target, armv7m_reg->num);
232
233 return retval;
234 }
235
236 int armv7m_set_core_reg(reg_t *reg, u8 *buf)
237 {
238 armv7m_core_reg_t *armv7m_reg = reg->arch_info;
239 target_t *target = armv7m_reg->target;
240 u32 value = buf_get_u32(buf, 0, 32);
241
242 if (target->state != TARGET_HALTED)
243 {
244 return ERROR_TARGET_NOT_HALTED;
245 }
246
247 buf_set_u32(reg->value, 0, 32, value);
248 reg->dirty = 1;
249 reg->valid = 1;
250
251 return ERROR_OK;
252 }
253
254 int armv7m_read_core_reg(struct target_s *target, int num)
255 {
256 u32 reg_value;
257 int retval;
258 armv7m_core_reg_t * armv7m_core_reg;
259
260 /* get pointers to arch-specific information */
261 armv7m_common_t *armv7m = target->arch_info;
262
263 if ((num < 0) || (num >= ARMV7NUMCOREREGS))
264 return ERROR_INVALID_ARGUMENTS;
265
266 armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
267 retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, &reg_value);
268 buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
269 armv7m->core_cache->reg_list[num].valid = 1;
270 armv7m->core_cache->reg_list[num].dirty = 0;
271
272 return ERROR_OK;
273 }
274
275 int armv7m_write_core_reg(struct target_s *target, int num)
276 {
277 int retval;
278 u32 reg_value;
279 armv7m_core_reg_t *armv7m_core_reg;
280
281 /* get pointers to arch-specific information */
282 armv7m_common_t *armv7m = target->arch_info;
283
284 if ((num < 0) || (num >= ARMV7NUMCOREREGS))
285 return ERROR_INVALID_ARGUMENTS;
286
287 reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
288 armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
289 retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value);
290 if (retval != ERROR_OK)
291 {
292 ERROR("JTAG failure");
293 armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
294 return ERROR_JTAG_DEVICE_ERROR;
295 }
296 DEBUG("write core reg %i value 0x%x", num , reg_value);
297 armv7m->core_cache->reg_list[num].valid = 1;
298 armv7m->core_cache->reg_list[num].dirty = 0;
299
300 return ERROR_OK;
301 }
302
303 int armv7m_invalidate_core_regs(target_t *target)
304 {
305 /* get pointers to arch-specific information */
306 armv7m_common_t *armv7m = target->arch_info;
307 int i;
308
309 for (i = 0; i < armv7m->core_cache->num_regs; i++)
310 {
311 armv7m->core_cache->reg_list[i].valid = 0;
312 armv7m->core_cache->reg_list[i].dirty = 0;
313 }
314
315 return ERROR_OK;
316 }
317
318 int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
319 {
320 /* get pointers to arch-specific information */
321 armv7m_common_t *armv7m = target->arch_info;
322 int i;
323
324 *reg_list_size = 26;
325 *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
326
327 /* TODOLATER correct list of registers, names ? */
328 for (i = 0; i < *reg_list_size; i++)
329 {
330 if (i < ARMV7NUMCOREREGS)
331 (*reg_list)[i] = &armv7m->process_context->reg_list[i];
332 else
333 (*reg_list)[i] = &armv7m_gdb_dummy_fp_reg;
334 }
335 /* ARMV7M is always in thumb mode, try to make GDB understand this if it does not support this arch */
336 armv7m->process_context->reg_list[15].value[0] |= 1;
337 (*reg_list)[25] = &armv7m->process_context->reg_list[ARMV7M_xPSR];
338 return ERROR_OK;
339 }
340
341 int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
342 {
343 /* get pointers to arch-specific information */
344 armv7m_common_t *armv7m = target->arch_info;
345 armv7m_algorithm_t *armv7m_algorithm_info = arch_info;
346 int retval = ERROR_OK;
347 u32 pc;
348 int i;
349
350 if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
351 {
352 ERROR("current target isn't an ARMV7M target");
353 return ERROR_TARGET_INVALID;
354 }
355
356 if (target->state != TARGET_HALTED)
357 {
358 WARNING("target not halted");
359 return ERROR_TARGET_NOT_HALTED;
360 }
361
362 /* refresh core register cache */
363 /* Not needed if core register cache is always consistent with target process state */
364 armv7m_use_context(target, ARMV7M_DEBUG_CONTEXT);
365
366 for (i = 0; i < num_mem_params; i++)
367 {
368 target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
369 }
370
371 for (i = 0; i < num_reg_params; i++)
372 {
373 reg_t *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
374 u32 regvalue;
375
376 if (!reg)
377 {
378 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
379 exit(-1);
380 }
381
382 if (reg->size != reg_params[i].size)
383 {
384 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
385 exit(-1);
386 }
387
388 regvalue = buf_get_u32(reg_params[i].value, 0, 32);
389 armv7m_set_core_reg(reg, reg_params[i].value);
390 }
391
392 /* ARMV7M always runs in Thumb state */
393 if ((retval = breakpoint_add(target, exit_point, 2, BKPT_SOFT)) != ERROR_OK)
394 {
395 ERROR("can't add breakpoint to finish algorithm execution");
396 return ERROR_TARGET_FAILURE;
397 }
398
399 /* This code relies on the target specific resume() and poll()->debug_entry()
400 sequence to write register values to the processor and the read them back */
401 target->type->resume(target, 0, entry_point, 1, 1);
402 target->type->poll(target);
403
404 while (target->state != TARGET_HALTED)
405 {
406 usleep(5000);
407 target->type->poll(target);
408 if ((timeout_ms -= 5) <= 0)
409 {
410 ERROR("timeout waiting for algorithm to complete, trying to halt target");
411 target->type->halt(target);
412 timeout_ms = 1000;
413 while (target->state != TARGET_HALTED)
414 {
415 usleep(10000);
416 target->type->poll(target);
417 if ((timeout_ms -= 10) <= 0)
418 {
419 ERROR("target didn't reenter debug state, exiting");
420 exit(-1);
421 }
422 }
423 armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
424 DEBUG("failed algoritm halted at 0x%x ", pc);
425 retval = ERROR_TARGET_TIMEOUT;
426 }
427 }
428
429 breakpoint_remove(target, exit_point);
430
431 /* Read memory values to mem_params[] */
432 for (i = 0; i < num_mem_params; i++)
433 {
434 if (mem_params[i].direction != PARAM_OUT)
435 target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value);
436 }
437
438 /* Copy core register values to reg_params[] */
439 for (i = 0; i < num_reg_params; i++)
440 {
441 if (reg_params[i].direction != PARAM_OUT)
442 {
443 reg_t *reg = register_get_by_name(armv7m->debug_context, reg_params[i].reg_name, 0);
444
445 if (!reg)
446 {
447 ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
448 exit(-1);
449 }
450
451 if (reg->size != reg_params[i].size)
452 {
453 ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
454 exit(-1);
455 }
456
457 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
458 }
459 }
460
461 return retval;
462 }
463
464 int armv7m_arch_state(struct target_s *target)
465 {
466 /* get pointers to arch-specific information */
467 armv7m_common_t *armv7m = target->arch_info;
468
469 USER("target halted in %s state due to %s, current mode: %s %s\nxPSR: 0x%8.8x pc: 0x%8.8x",
470 armv7m_state_strings[armv7m->core_state],
471 target_debug_reason_strings[target->debug_reason],
472 armv7m_mode_strings[armv7m->core_mode],
473 armv7m_exception_string(armv7m->exception_number),
474 buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
475 buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32));
476
477 return ERROR_OK;
478 }
479
480 reg_cache_t *armv7m_build_reg_cache(target_t *target)
481 {
482 /* get pointers to arch-specific information */
483 armv7m_common_t *armv7m = target->arch_info;
484
485 int num_regs = ARMV7NUMCOREREGS;
486 reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
487 reg_cache_t *cache = malloc(sizeof(reg_cache_t));
488 reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
489 armv7m_core_reg_t *arch_info = malloc(sizeof(armv7m_core_reg_t) * num_regs);
490 int i;
491
492 if (armv7m_core_reg_arch_type == -1)
493 armv7m_core_reg_arch_type = register_reg_arch_type(armv7m_get_core_reg, armv7m_set_core_reg);
494
495 /* Build the process context cache */
496 cache->name = "arm v7m registers";
497 cache->next = NULL;
498 cache->reg_list = reg_list;
499 cache->num_regs = num_regs;
500 (*cache_p) = cache;
501 armv7m->core_cache = cache;
502 armv7m->process_context = cache;
503
504 for (i = 0; i < num_regs; i++)
505 {
506 arch_info[i] = armv7m_core_reg_list_arch_info[i];
507 arch_info[i].target = target;
508 arch_info[i].armv7m_common = armv7m;
509 reg_list[i].name = armv7m_core_reg_list[i];
510 reg_list[i].size = 32;
511 reg_list[i].value = calloc(1, 4);
512 reg_list[i].dirty = 0;
513 reg_list[i].valid = 0;
514 reg_list[i].bitfield_desc = NULL;
515 reg_list[i].num_bitfields = 0;
516 reg_list[i].arch_type = armv7m_core_reg_arch_type;
517 reg_list[i].arch_info = &arch_info[i];
518 }
519
520 /* Build the debug context cache*/
521 cache = malloc(sizeof(reg_cache_t));
522 reg_list = malloc(sizeof(reg_t) * num_regs);
523
524 cache->name = "arm v7m debug registers";
525 cache->next = NULL;
526 cache->reg_list = reg_list;
527 cache->num_regs = num_regs;
528 armv7m->debug_context = cache;
529 armv7m->process_context->next = cache;
530
531 for (i = 0; i < num_regs; i++)
532 {
533 reg_list[i].name = armv7m_core_dbgreg_list[i];
534 reg_list[i].size = 32;
535 reg_list[i].value = calloc(1, 4);
536 reg_list[i].dirty = 0;
537 reg_list[i].valid = 0;
538 reg_list[i].bitfield_desc = NULL;
539 reg_list[i].num_bitfields = 0;
540 reg_list[i].arch_type = armv7m_core_reg_arch_type;
541 reg_list[i].arch_info = &arch_info[i];
542 }
543
544 return cache;
545 }
546
547 int armv7m_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
548 {
549 armv7m_build_reg_cache(target);
550
551 return ERROR_OK;
552 }
553
554 int armv7m_init_arch_info(target_t *target, armv7m_common_t *armv7m)
555 {
556 /* register arch-specific functions */
557
558 target->arch_info = armv7m;
559 armv7m->core_state = ARMV7M_STATE_THUMB;
560 armv7m->read_core_reg = armv7m_read_core_reg;
561 armv7m->write_core_reg = armv7m_write_core_reg;
562
563 return ERROR_OK;
564 }
565
566 int armv7m_register_commands(struct command_context_s *cmd_ctx)
567 {
568 return ERROR_OK;
569 }
570
571 int armv7m_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
572 {
573 working_area_t *crc_algorithm;
574 armv7m_algorithm_t armv7m_info;
575 reg_param_t reg_params[2];
576 int retval;
577
578 u16 cortex_m3_crc_code[] = {
579 0x4602, /* mov r2, r0 */
580 0xF04F, 0x30FF, /* mov r0, #0xffffffff */
581 0x460B, /* mov r3, r1 */
582 0xF04F, 0x0400, /* mov r4, #0 */
583 0xE013, /* b ncomp */
584 /* nbyte: */
585 0x5D11, /* ldrb r1, [r2, r4] */
586 0xF8DF, 0x7028, /* ldr r7, CRC32XOR */
587 0xEA80, 0x6001, /* eor r0, r0, r1, asl #24 */
588
589 0xF04F, 0x0500, /* mov r5, #0 */
590 /* loop: */
591 0x2800, /* cmp r0, #0 */
592 0xEA4F, 0x0640, /* mov r6, r0, asl #1 */
593 0xF105, 0x0501, /* add r5, r5, #1 */
594 0x4630, /* mov r0, r6 */
595 0xBFB8, /* it lt */
596 0xEA86, 0x0007, /* eor r0, r6, r7 */
597 0x2D08, /* cmp r5, #8 */
598 0xD1F4, /* bne loop */
599
600 0xF104, 0x0401, /* add r4, r4, #1 */
601 /* ncomp: */
602 0x429C, /* cmp r4, r3 */
603 0xD1E9, /* bne nbyte */
604 /* end: */
605 0xE7FE, /* b end */
606 0x1DB7, 0x04C1 /* CRC32XOR: .word 0x04C11DB7 */
607 };
608
609 int i;
610
611 if (target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm) != ERROR_OK)
612 {
613 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
614 }
615
616 /* convert flash writing code into a buffer in target endianness */
617 for (i = 0; i < (sizeof(cortex_m3_crc_code)/sizeof(u16)); i++)
618 target_write_u16(target, crc_algorithm->address + i*sizeof(u16), cortex_m3_crc_code[i]);
619
620 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
621 armv7m_info.core_mode = ARMV7M_MODE_ANY;
622 armv7m_info.core_state = ARMV7M_STATE_THUMB;
623
624 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
625 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
626
627 buf_set_u32(reg_params[0].value, 0, 32, address);
628 buf_set_u32(reg_params[1].value, 0, 32, count);
629
630 if ((retval = target->type->run_algorithm(target, 0, NULL, 2, reg_params,
631 crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code)-6), 20000, &armv7m_info)) != ERROR_OK)
632 {
633 ERROR("error executing cortex_m3 crc algorithm");
634 destroy_reg_param(&reg_params[0]);
635 destroy_reg_param(&reg_params[1]);
636 target_free_working_area(target, crc_algorithm);
637 return retval;
638 }
639
640 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
641
642 destroy_reg_param(&reg_params[0]);
643 destroy_reg_param(&reg_params[1]);
644
645 target_free_working_area(target, crc_algorithm);
646
647 return ERROR_OK;
648 }
649

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)