65ea6e859193058e863d979f9bc9ddc3366d5590
[openocd.git] / src / target / mips32.c
1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
4 * *
5 * Copyright (C) 2008 by David T.L. Wong *
6 * *
7 * Copyright (C) 2007,2008 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
24 ***************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include "mips32.h"
30 #include "breakpoints.h"
31 #include "algorithm.h"
32 #include "register.h"
33
34 static char* mips32_core_reg_list[] =
35 {
36 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
37 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
38 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
39 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra",
40 "status", "lo", "hi", "badvaddr", "cause", "pc"
41 };
42
43 static const char *mips_isa_strings[] =
44 {
45 "MIPS32", "MIPS16e"
46 };
47
48 static struct mips32_core_reg mips32_core_reg_list_arch_info[MIPS32NUMCOREREGS] =
49 {
50 {0, NULL, NULL},
51 {1, NULL, NULL},
52 {2, NULL, NULL},
53 {3, NULL, NULL},
54 {4, NULL, NULL},
55 {5, NULL, NULL},
56 {6, NULL, NULL},
57 {7, NULL, NULL},
58 {8, NULL, NULL},
59 {9, NULL, NULL},
60 {10, NULL, NULL},
61 {11, NULL, NULL},
62 {12, NULL, NULL},
63 {13, NULL, NULL},
64 {14, NULL, NULL},
65 {15, NULL, NULL},
66 {16, NULL, NULL},
67 {17, NULL, NULL},
68 {18, NULL, NULL},
69 {19, NULL, NULL},
70 {20, NULL, NULL},
71 {21, NULL, NULL},
72 {22, NULL, NULL},
73 {23, NULL, NULL},
74 {24, NULL, NULL},
75 {25, NULL, NULL},
76 {26, NULL, NULL},
77 {27, NULL, NULL},
78 {28, NULL, NULL},
79 {29, NULL, NULL},
80 {30, NULL, NULL},
81 {31, NULL, NULL},
82
83 {32, NULL, NULL},
84 {33, NULL, NULL},
85 {34, NULL, NULL},
86 {35, NULL, NULL},
87 {36, NULL, NULL},
88 {37, NULL, NULL},
89 };
90
91 /* number of mips dummy fp regs fp0 - fp31 + fsr and fir
92 * we also add 18 unknown registers to handle gdb requests */
93
94 #define MIPS32NUMFPREGS 34 + 18
95
96 static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
97
98 static struct reg mips32_gdb_dummy_fp_reg =
99 {
100 .name = "GDB dummy floating-point register",
101 .value = mips32_gdb_dummy_fp_value,
102 .dirty = 0,
103 .valid = 1,
104 .size = 32,
105 .arch_info = NULL,
106 };
107
108 static int mips32_get_core_reg(struct reg *reg)
109 {
110 int retval;
111 struct mips32_core_reg *mips32_reg = reg->arch_info;
112 struct target *target = mips32_reg->target;
113 struct mips32_common *mips32_target = target_to_mips32(target);
114
115 if (target->state != TARGET_HALTED)
116 {
117 return ERROR_TARGET_NOT_HALTED;
118 }
119
120 retval = mips32_target->read_core_reg(target, mips32_reg->num);
121
122 return retval;
123 }
124
125 static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
126 {
127 struct mips32_core_reg *mips32_reg = reg->arch_info;
128 struct target *target = mips32_reg->target;
129 uint32_t value = buf_get_u32(buf, 0, 32);
130
131 if (target->state != TARGET_HALTED)
132 {
133 return ERROR_TARGET_NOT_HALTED;
134 }
135
136 buf_set_u32(reg->value, 0, 32, value);
137 reg->dirty = 1;
138 reg->valid = 1;
139
140 return ERROR_OK;
141 }
142
143 static int mips32_read_core_reg(struct target *target, int num)
144 {
145 uint32_t reg_value;
146
147 /* get pointers to arch-specific information */
148 struct mips32_common *mips32 = target_to_mips32(target);
149
150 if ((num < 0) || (num >= MIPS32NUMCOREREGS))
151 return ERROR_INVALID_ARGUMENTS;
152
153 reg_value = mips32->core_regs[num];
154 buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
155 mips32->core_cache->reg_list[num].valid = 1;
156 mips32->core_cache->reg_list[num].dirty = 0;
157
158 return ERROR_OK;
159 }
160
161 static int mips32_write_core_reg(struct target *target, int num)
162 {
163 uint32_t reg_value;
164
165 /* get pointers to arch-specific information */
166 struct mips32_common *mips32 = target_to_mips32(target);
167
168 if ((num < 0) || (num >= MIPS32NUMCOREREGS))
169 return ERROR_INVALID_ARGUMENTS;
170
171 reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
172 mips32->core_regs[num] = reg_value;
173 LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num , reg_value);
174 mips32->core_cache->reg_list[num].valid = 1;
175 mips32->core_cache->reg_list[num].dirty = 0;
176
177 return ERROR_OK;
178 }
179
180 int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
181 {
182 /* get pointers to arch-specific information */
183 struct mips32_common *mips32 = target_to_mips32(target);
184 int i;
185
186 /* include floating point registers */
187 *reg_list_size = MIPS32NUMCOREREGS + MIPS32NUMFPREGS;
188 *reg_list = malloc(sizeof(struct reg*) * (*reg_list_size));
189
190 for (i = 0; i < MIPS32NUMCOREREGS; i++)
191 {
192 (*reg_list)[i] = &mips32->core_cache->reg_list[i];
193 }
194
195 /* add dummy floating points regs */
196 for (i = MIPS32NUMCOREREGS; i < (MIPS32NUMCOREREGS + MIPS32NUMFPREGS); i++)
197 {
198 (*reg_list)[i] = &mips32_gdb_dummy_fp_reg;
199 }
200
201 return ERROR_OK;
202 }
203
204 int mips32_save_context(struct target *target)
205 {
206 int i;
207
208 /* get pointers to arch-specific information */
209 struct mips32_common *mips32 = target_to_mips32(target);
210 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
211
212 /* read core registers */
213 mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
214
215 for (i = 0; i < MIPS32NUMCOREREGS; i++)
216 {
217 if (!mips32->core_cache->reg_list[i].valid)
218 {
219 mips32->read_core_reg(target, i);
220 }
221 }
222
223 return ERROR_OK;
224 }
225
226 int mips32_restore_context(struct target *target)
227 {
228 int i;
229
230 /* get pointers to arch-specific information */
231 struct mips32_common *mips32 = target_to_mips32(target);
232 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
233
234 for (i = 0; i < MIPS32NUMCOREREGS; i++)
235 {
236 if (mips32->core_cache->reg_list[i].dirty)
237 {
238 mips32->write_core_reg(target, i);
239 }
240 }
241
242 /* write core regs */
243 mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
244
245 return ERROR_OK;
246 }
247
248 int mips32_arch_state(struct target *target)
249 {
250 struct mips32_common *mips32 = target_to_mips32(target);
251
252 LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
253 mips_isa_strings[mips32->isa_mode],
254 debug_reason_name(target),
255 buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
256
257 return ERROR_OK;
258 }
259
260 static const struct reg_arch_type mips32_reg_type = {
261 .get = mips32_get_core_reg,
262 .set = mips32_set_core_reg,
263 };
264
265 struct reg_cache *mips32_build_reg_cache(struct target *target)
266 {
267 /* get pointers to arch-specific information */
268 struct mips32_common *mips32 = target_to_mips32(target);
269
270 int num_regs = MIPS32NUMCOREREGS;
271 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
272 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
273 struct reg *reg_list = malloc(sizeof(struct reg) * num_regs);
274 struct mips32_core_reg *arch_info = malloc(sizeof(struct mips32_core_reg) * num_regs);
275 int i;
276
277 register_init_dummy(&mips32_gdb_dummy_fp_reg);
278
279 /* Build the process context cache */
280 cache->name = "mips32 registers";
281 cache->next = NULL;
282 cache->reg_list = reg_list;
283 cache->num_regs = num_regs;
284 (*cache_p) = cache;
285 mips32->core_cache = cache;
286
287 for (i = 0; i < num_regs; i++)
288 {
289 arch_info[i] = mips32_core_reg_list_arch_info[i];
290 arch_info[i].target = target;
291 arch_info[i].mips32_common = mips32;
292 reg_list[i].name = mips32_core_reg_list[i];
293 reg_list[i].size = 32;
294 reg_list[i].value = calloc(1, 4);
295 reg_list[i].dirty = 0;
296 reg_list[i].valid = 0;
297 reg_list[i].type = &mips32_reg_type;
298 reg_list[i].arch_info = &arch_info[i];
299 }
300
301 return cache;
302 }
303
304 int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, struct jtag_tap *tap)
305 {
306 target->arch_info = mips32;
307 mips32->common_magic = MIPS32_COMMON_MAGIC;
308 mips32->fast_data_area = NULL;
309
310 /* has breakpoint/watchpint unit been scanned */
311 mips32->bp_scanned = 0;
312 mips32->data_break_list = NULL;
313
314 mips32->ejtag_info.tap = tap;
315 mips32->read_core_reg = mips32_read_core_reg;
316 mips32->write_core_reg = mips32_write_core_reg;
317
318 return ERROR_OK;
319 }
320
321 /* run to exit point. return error if exit point was not reached. */
322 static int mips32_run_and_wait(struct target *target, uint32_t entry_point,
323 int timeout_ms, uint32_t exit_point, struct mips32_common *mips32)
324 {
325 uint32_t pc;
326 int retval;
327 /* This code relies on the target specific resume() and poll()->debug_entry()
328 * sequence to write register values to the processor and the read them back */
329 if ((retval = target_resume(target, 0, entry_point, 0, 1)) != ERROR_OK)
330 {
331 return retval;
332 }
333
334 retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
335 /* If the target fails to halt due to the breakpoint, force a halt */
336 if (retval != ERROR_OK || target->state != TARGET_HALTED)
337 {
338 if ((retval = target_halt(target)) != ERROR_OK)
339 return retval;
340 if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK)
341 {
342 return retval;
343 }
344 return ERROR_TARGET_TIMEOUT;
345 }
346
347 pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
348 if (exit_point && (pc != exit_point))
349 {
350 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
351 return ERROR_TARGET_TIMEOUT;
352 }
353
354 return ERROR_OK;
355 }
356
357 int mips32_run_algorithm(struct target *target, int num_mem_params,
358 struct mem_param *mem_params, int num_reg_params,
359 struct reg_param *reg_params, uint32_t entry_point,
360 uint32_t exit_point, int timeout_ms, void *arch_info)
361 {
362 struct mips32_common *mips32 = target_to_mips32(target);
363 struct mips32_algorithm *mips32_algorithm_info = arch_info;
364 enum mips32_isa_mode isa_mode = mips32->isa_mode;
365
366 uint32_t context[MIPS32NUMCOREREGS];
367 int i;
368 int retval = ERROR_OK;
369
370 LOG_DEBUG("Running algorithm");
371
372 /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
373 * at the exit point */
374
375 if (mips32->common_magic != MIPS32_COMMON_MAGIC)
376 {
377 LOG_ERROR("current target isn't a MIPS32 target");
378 return ERROR_TARGET_INVALID;
379 }
380
381 if (target->state != TARGET_HALTED)
382 {
383 LOG_WARNING("target not halted");
384 return ERROR_TARGET_NOT_HALTED;
385 }
386
387 /* refresh core register cache */
388 for (i = 0; i < MIPS32NUMCOREREGS; i++)
389 {
390 if (!mips32->core_cache->reg_list[i].valid)
391 mips32->read_core_reg(target, i);
392 context[i] = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
393 }
394
395 for (i = 0; i < num_mem_params; i++)
396 {
397 if ((retval = target_write_buffer(target, mem_params[i].address,
398 mem_params[i].size, mem_params[i].value)) != ERROR_OK)
399 {
400 return retval;
401 }
402 }
403
404 for (i = 0; i < num_reg_params; i++)
405 {
406 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
407
408 if (!reg)
409 {
410 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
411 return ERROR_INVALID_ARGUMENTS;
412 }
413
414 if (reg->size != reg_params[i].size)
415 {
416 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
417 reg_params[i].reg_name);
418 return ERROR_INVALID_ARGUMENTS;
419 }
420
421 mips32_set_core_reg(reg, reg_params[i].value);
422 }
423
424 mips32->isa_mode = mips32_algorithm_info->isa_mode;
425
426 retval = mips32_run_and_wait(target, entry_point, timeout_ms, exit_point, mips32);
427
428 if (retval != ERROR_OK)
429 return retval;
430
431 for (i = 0; i < num_mem_params; i++)
432 {
433 if (mem_params[i].direction != PARAM_OUT)
434 {
435 if ((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size,
436 mem_params[i].value)) != ERROR_OK)
437 {
438 return retval;
439 }
440 }
441 }
442
443 for (i = 0; i < num_reg_params; i++)
444 {
445 if (reg_params[i].direction != PARAM_OUT)
446 {
447 struct reg *reg = register_get_by_name(mips32->core_cache, reg_params[i].reg_name, 0);
448 if (!reg)
449 {
450 LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
451 return ERROR_INVALID_ARGUMENTS;
452 }
453
454 if (reg->size != reg_params[i].size)
455 {
456 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
457 reg_params[i].reg_name);
458 return ERROR_INVALID_ARGUMENTS;
459 }
460
461 buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
462 }
463 }
464
465 /* restore everything we saved before */
466 for (i = 0; i < MIPS32NUMCOREREGS; i++)
467 {
468 uint32_t regvalue;
469 regvalue = buf_get_u32(mips32->core_cache->reg_list[i].value, 0, 32);
470 if (regvalue != context[i])
471 {
472 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
473 mips32->core_cache->reg_list[i].name, context[i]);
474 buf_set_u32(mips32->core_cache->reg_list[i].value,
475 0, 32, context[i]);
476 mips32->core_cache->reg_list[i].valid = 1;
477 mips32->core_cache->reg_list[i].dirty = 1;
478 }
479 }
480
481 mips32->isa_mode = isa_mode;
482
483 return ERROR_OK;
484 }
485
486 int mips32_examine(struct target *target)
487 {
488 struct mips32_common *mips32 = target_to_mips32(target);
489
490 if (!target_was_examined(target))
491 {
492 target_set_examined(target);
493
494 /* we will configure later */
495 mips32->bp_scanned = 0;
496 mips32->num_inst_bpoints = 0;
497 mips32->num_data_bpoints = 0;
498 mips32->num_inst_bpoints_avail = 0;
499 mips32->num_data_bpoints_avail = 0;
500 }
501
502 return ERROR_OK;
503 }
504
505 int mips32_configure_break_unit(struct target *target)
506 {
507 /* get pointers to arch-specific information */
508 struct mips32_common *mips32 = target_to_mips32(target);
509 int retval;
510 uint32_t dcr, bpinfo;
511 int i;
512
513 if (mips32->bp_scanned)
514 return ERROR_OK;
515
516 /* get info about breakpoint support */
517 if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
518 return retval;
519
520 if (dcr & EJTAG_DCR_IB)
521 {
522 /* get number of inst breakpoints */
523 if ((retval = target_read_u32(target, EJTAG_IBS, &bpinfo)) != ERROR_OK)
524 return retval;
525
526 mips32->num_inst_bpoints = (bpinfo >> 24) & 0x0F;
527 mips32->num_inst_bpoints_avail = mips32->num_inst_bpoints;
528 mips32->inst_break_list = calloc(mips32->num_inst_bpoints, sizeof(struct mips32_comparator));
529 for (i = 0; i < mips32->num_inst_bpoints; i++)
530 {
531 mips32->inst_break_list[i].reg_address = EJTAG_IBA1 + (0x100 * i);
532 }
533
534 /* clear IBIS reg */
535 if ((retval = target_write_u32(target, EJTAG_IBS, 0)) != ERROR_OK)
536 return retval;
537 }
538
539 if (dcr & EJTAG_DCR_DB)
540 {
541 /* get number of data breakpoints */
542 if ((retval = target_read_u32(target, EJTAG_DBS, &bpinfo)) != ERROR_OK)
543 return retval;
544
545 mips32->num_data_bpoints = (bpinfo >> 24) & 0x0F;
546 mips32->num_data_bpoints_avail = mips32->num_data_bpoints;
547 mips32->data_break_list = calloc(mips32->num_data_bpoints, sizeof(struct mips32_comparator));
548 for (i = 0; i < mips32->num_data_bpoints; i++)
549 {
550 mips32->data_break_list[i].reg_address = EJTAG_DBA1 + (0x100 * i);
551 }
552
553 /* clear DBIS reg */
554 if ((retval = target_write_u32(target, EJTAG_DBS, 0)) != ERROR_OK)
555 return retval;
556 }
557
558 /* check if target endianness settings matches debug control register */
559 if ( ( (dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_LITTLE_ENDIAN) ) ||
560 ( !(dcr & EJTAG_DCR_ENM) && (target->endianness == TARGET_BIG_ENDIAN) ) )
561 {
562 LOG_WARNING("DCR endianness settings does not match target settings");
563 }
564
565 LOG_DEBUG("DCR 0x%" PRIx32 " numinst %i numdata %i", dcr, mips32->num_inst_bpoints,
566 mips32->num_data_bpoints);
567
568 mips32->bp_scanned = 1;
569
570 return ERROR_OK;
571 }
572
573 int mips32_enable_interrupts(struct target *target, int enable)
574 {
575 int retval;
576 int update = 0;
577 uint32_t dcr;
578
579 /* read debug control register */
580 if ((retval = target_read_u32(target, EJTAG_DCR, &dcr)) != ERROR_OK)
581 return retval;
582
583 if (enable)
584 {
585 if (!(dcr & EJTAG_DCR_INTE))
586 {
587 /* enable interrupts */
588 dcr |= EJTAG_DCR_INTE;
589 update = 1;
590 }
591 }
592 else
593 {
594 if (dcr & EJTAG_DCR_INTE)
595 {
596 /* disable interrupts */
597 dcr &= ~EJTAG_DCR_INTE;
598 update = 1;
599 }
600 }
601
602 if (update)
603 {
604 if ((retval = target_write_u32(target, EJTAG_DCR, dcr)) != ERROR_OK)
605 return retval;
606 }
607
608 return ERROR_OK;
609 }
610
611 int mips32_checksum_memory(struct target *target, uint32_t address,
612 uint32_t count, uint32_t* checksum)
613 {
614 struct working_area *crc_algorithm;
615 struct reg_param reg_params[2];
616 struct mips32_algorithm mips32_info;
617 int retval;
618 uint32_t i;
619
620 /* see contib/loaders/checksum/mips32.s for src */
621
622 static const uint32_t mips_crc_code[] =
623 {
624 0x248C0000, /* addiu $t4, $a0, 0 */
625 0x24AA0000, /* addiu $t2, $a1, 0 */
626 0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */
627 0x10000010, /* beq $zero, $zero, ncomp */
628 0x240B0000, /* addiu $t3, $zero, 0 */
629 /* nbyte: */
630 0x81850000, /* lb $a1, ($t4) */
631 0x218C0001, /* addi $t4, $t4, 1 */
632 0x00052E00, /* sll $a1, $a1, 24 */
633 0x3C0204C1, /* lui $v0, 0x04c1 */
634 0x00852026, /* xor $a0, $a0, $a1 */
635 0x34471DB7, /* ori $a3, $v0, 0x1db7 */
636 0x00003021, /* addu $a2, $zero, $zero */
637 /* loop: */
638 0x00044040, /* sll $t0, $a0, 1 */
639 0x24C60001, /* addiu $a2, $a2, 1 */
640 0x28840000, /* slti $a0, $a0, 0 */
641 0x01074826, /* xor $t1, $t0, $a3 */
642 0x0124400B, /* movn $t0, $t1, $a0 */
643 0x28C30008, /* slti $v1, $a2, 8 */
644 0x1460FFF9, /* bne $v1, $zero, loop */
645 0x01002021, /* addu $a0, $t0, $zero */
646 /* ncomp: */
647 0x154BFFF0, /* bne $t2, $t3, nbyte */
648 0x256B0001, /* addiu $t3, $t3, 1 */
649 0x7000003F, /* sdbbp */
650 };
651
652 /* make sure we have a working area */
653 if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK)
654 {
655 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
656 }
657
658 /* convert flash writing code into a buffer in target endianness */
659 for (i = 0; i < ARRAY_SIZE(mips_crc_code); i++)
660 target_write_u32(target, crc_algorithm->address + i*sizeof(uint32_t), mips_crc_code[i]);
661
662 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
663 mips32_info.isa_mode = MIPS32_ISA_MIPS32;
664
665 init_reg_param(&reg_params[0], "a0", 32, PARAM_IN_OUT);
666 buf_set_u32(reg_params[0].value, 0, 32, address);
667
668 init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);
669 buf_set_u32(reg_params[1].value, 0, 32, count);
670
671 int timeout = 20000 * (1 + (count / (1024 * 1024)));
672
673 if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
674 crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code)-4), timeout,
675 &mips32_info)) != ERROR_OK)
676 {
677 destroy_reg_param(&reg_params[0]);
678 destroy_reg_param(&reg_params[1]);
679 target_free_working_area(target, crc_algorithm);
680 return 0;
681 }
682
683 *checksum = buf_get_u32(reg_params[0].value, 0, 32);
684
685 destroy_reg_param(&reg_params[0]);
686 destroy_reg_param(&reg_params[1]);
687
688 target_free_working_area(target, crc_algorithm);
689
690 return ERROR_OK;
691 }
692
693 /** Checks whether a memory region is zeroed. */
694 int mips32_blank_check_memory(struct target *target,
695 uint32_t address, uint32_t count, uint32_t* blank)
696 {
697 struct working_area *erase_check_algorithm;
698 struct reg_param reg_params[3];
699 struct mips32_algorithm mips32_info;
700 int retval;
701 uint32_t i;
702
703 static const uint32_t erase_check_code[] =
704 {
705 /* nbyte: */
706 0x80880000, /* lb $t0, ($a0) */
707 0x00C83024, /* and $a2, $a2, $t0 */
708 0x24A5FFFF, /* addiu $a1, $a1, -1 */
709 0x14A0FFFC, /* bne $a1, $zero, nbyte */
710 0x24840001, /* addiu $a0, $a0, 1 */
711 0x7000003F /* sdbbp */
712 };
713
714 /* make sure we have a working area */
715 if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
716 {
717 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
718 }
719
720 /* convert flash writing code into a buffer in target endianness */
721 for (i = 0; i < ARRAY_SIZE(erase_check_code); i++)
722 {
723 target_write_u32(target, erase_check_algorithm->address + i*sizeof(uint32_t),
724 erase_check_code[i]);
725 }
726
727 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
728 mips32_info.isa_mode = MIPS32_ISA_MIPS32;
729
730 init_reg_param(&reg_params[0], "a0", 32, PARAM_OUT);
731 buf_set_u32(reg_params[0].value, 0, 32, address);
732
733 init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);
734 buf_set_u32(reg_params[1].value, 0, 32, count);
735
736 init_reg_param(&reg_params[2], "a2", 32, PARAM_IN_OUT);
737 buf_set_u32(reg_params[2].value, 0, 32, 0xff);
738
739 if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
740 erase_check_algorithm->address,
741 erase_check_algorithm->address + (sizeof(erase_check_code)-2),
742 10000, &mips32_info)) != ERROR_OK)
743 {
744 destroy_reg_param(&reg_params[0]);
745 destroy_reg_param(&reg_params[1]);
746 destroy_reg_param(&reg_params[2]);
747 target_free_working_area(target, erase_check_algorithm);
748 return 0;
749 }
750
751 *blank = buf_get_u32(reg_params[2].value, 0, 32);
752
753 destroy_reg_param(&reg_params[0]);
754 destroy_reg_param(&reg_params[1]);
755 destroy_reg_param(&reg_params[2]);
756
757 target_free_working_area(target, erase_check_algorithm);
758
759 return ERROR_OK;
760 }

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)