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

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)