1 /***************************************************************************
2 * Copyright (C) 2008 by Spencer Oliver *
3 * spen@spen-soft.co.uk *
5 * Copyright (C) 2008 by David T.L. Wong *
7 * Copyright (C) 2007,2008 Øyvind Harboe *
8 * oyvind.harboe@zylin.com *
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. *
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. *
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 ***************************************************************************/
30 #include "breakpoints.h"
31 #include "algorithm.h"
34 static char* mips32_core_reg_list
[] =
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"
43 static const char *mips_isa_strings
[] =
48 static struct mips32_core_reg mips32_core_reg_list_arch_info
[MIPS32NUMCOREREGS
] =
91 /* number of mips dummy fp regs fp0 - fp31 + fsr and fir
92 * we also add 18 unknown registers to handle gdb requests */
94 #define MIPS32NUMFPREGS 34 + 18
96 static uint8_t mips32_gdb_dummy_fp_value
[] = {0, 0, 0, 0};
98 static struct reg mips32_gdb_dummy_fp_reg
=
100 .name
= "GDB dummy floating-point register",
101 .value
= mips32_gdb_dummy_fp_value
,
108 static int mips32_get_core_reg(struct reg
*reg
)
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
);
115 if (target
->state
!= TARGET_HALTED
)
117 return ERROR_TARGET_NOT_HALTED
;
120 retval
= mips32_target
->read_core_reg(target
, mips32_reg
->num
);
125 static int mips32_set_core_reg(struct reg
*reg
, uint8_t *buf
)
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);
131 if (target
->state
!= TARGET_HALTED
)
133 return ERROR_TARGET_NOT_HALTED
;
136 buf_set_u32(reg
->value
, 0, 32, value
);
143 static int mips32_read_core_reg(struct target
*target
, int num
)
147 /* get pointers to arch-specific information */
148 struct mips32_common
*mips32
= target_to_mips32(target
);
150 if ((num
< 0) || (num
>= MIPS32NUMCOREREGS
))
151 return ERROR_INVALID_ARGUMENTS
;
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;
161 static int mips32_write_core_reg(struct target
*target
, int num
)
165 /* get pointers to arch-specific information */
166 struct mips32_common
*mips32
= target_to_mips32(target
);
168 if ((num
< 0) || (num
>= MIPS32NUMCOREREGS
))
169 return ERROR_INVALID_ARGUMENTS
;
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;
180 int mips32_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
182 /* get pointers to arch-specific information */
183 struct mips32_common
*mips32
= target_to_mips32(target
);
186 /* include floating point registers */
187 *reg_list_size
= MIPS32NUMCOREREGS
+ MIPS32NUMFPREGS
;
188 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
190 for (i
= 0; i
< MIPS32NUMCOREREGS
; i
++)
192 (*reg_list
)[i
] = &mips32
->core_cache
->reg_list
[i
];
195 /* add dummy floating points regs */
196 for (i
= MIPS32NUMCOREREGS
; i
< (MIPS32NUMCOREREGS
+ MIPS32NUMFPREGS
); i
++)
198 (*reg_list
)[i
] = &mips32_gdb_dummy_fp_reg
;
204 int mips32_save_context(struct target
*target
)
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
;
212 /* read core registers */
213 mips32_pracc_read_regs(ejtag_info
, mips32
->core_regs
);
215 for (i
= 0; i
< MIPS32NUMCOREREGS
; i
++)
217 if (!mips32
->core_cache
->reg_list
[i
].valid
)
219 mips32
->read_core_reg(target
, i
);
226 int mips32_restore_context(struct target
*target
)
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
;
234 for (i
= 0; i
< MIPS32NUMCOREREGS
; i
++)
236 if (mips32
->core_cache
->reg_list
[i
].dirty
)
238 mips32
->write_core_reg(target
, i
);
242 /* write core regs */
243 mips32_pracc_write_regs(ejtag_info
, mips32
->core_regs
);
248 int mips32_arch_state(struct target
*target
)
250 struct mips32_common
*mips32
= target_to_mips32(target
);
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));
260 static const struct reg_arch_type mips32_reg_type
= {
261 .get
= mips32_get_core_reg
,
262 .set
= mips32_set_core_reg
,
265 struct reg_cache
*mips32_build_reg_cache(struct target
*target
)
267 /* get pointers to arch-specific information */
268 struct mips32_common
*mips32
= target_to_mips32(target
);
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
);
277 register_init_dummy(&mips32_gdb_dummy_fp_reg
);
279 /* Build the process context cache */
280 cache
->name
= "mips32 registers";
282 cache
->reg_list
= reg_list
;
283 cache
->num_regs
= num_regs
;
285 mips32
->core_cache
= cache
;
287 for (i
= 0; i
< num_regs
; i
++)
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
];
304 int mips32_init_arch_info(struct target
*target
, struct mips32_common
*mips32
, struct jtag_tap
*tap
)
306 target
->arch_info
= mips32
;
307 mips32
->common_magic
= MIPS32_COMMON_MAGIC
;
308 mips32
->fast_data_area
= NULL
;
310 /* has breakpoint/watchpint unit been scanned */
311 mips32
->bp_scanned
= 0;
312 mips32
->data_break_list
= NULL
;
314 mips32
->ejtag_info
.tap
= tap
;
315 mips32
->read_core_reg
= mips32_read_core_reg
;
316 mips32
->write_core_reg
= mips32_write_core_reg
;
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
)
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
)
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
)
338 if ((retval
= target_halt(target
)) != ERROR_OK
)
340 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
344 return ERROR_TARGET_TIMEOUT
;
347 pc
= buf_get_u32(mips32
->core_cache
->reg_list
[MIPS32_PC
].value
, 0, 32);
348 if (exit_point
&& (pc
!= exit_point
))
350 LOG_DEBUG("failed algorithm halted at 0x%" PRIx32
" ", pc
);
351 return ERROR_TARGET_TIMEOUT
;
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
)
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
;
366 uint32_t context
[MIPS32NUMCOREREGS
];
368 int retval
= ERROR_OK
;
370 LOG_DEBUG("Running algorithm");
372 /* NOTE: mips32_run_algorithm requires that each algorithm uses a software breakpoint
373 * at the exit point */
375 if (mips32
->common_magic
!= MIPS32_COMMON_MAGIC
)
377 LOG_ERROR("current target isn't a MIPS32 target");
378 return ERROR_TARGET_INVALID
;
381 if (target
->state
!= TARGET_HALTED
)
383 LOG_WARNING("target not halted");
384 return ERROR_TARGET_NOT_HALTED
;
387 /* refresh core register cache */
388 for (i
= 0; i
< MIPS32NUMCOREREGS
; i
++)
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);
395 for (i
= 0; i
< num_mem_params
; i
++)
397 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
,
398 mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
404 for (i
= 0; i
< num_reg_params
; i
++)
406 struct reg
*reg
= register_get_by_name(mips32
->core_cache
, reg_params
[i
].reg_name
, 0);
410 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
411 return ERROR_INVALID_ARGUMENTS
;
414 if (reg
->size
!= reg_params
[i
].size
)
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
;
421 mips32_set_core_reg(reg
, reg_params
[i
].value
);
424 mips32
->isa_mode
= mips32_algorithm_info
->isa_mode
;
426 retval
= mips32_run_and_wait(target
, entry_point
, timeout_ms
, exit_point
, mips32
);
428 if (retval
!= ERROR_OK
)
431 for (i
= 0; i
< num_mem_params
; i
++)
433 if (mem_params
[i
].direction
!= PARAM_OUT
)
435 if ((retval
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
,
436 mem_params
[i
].value
)) != ERROR_OK
)
443 for (i
= 0; i
< num_reg_params
; i
++)
445 if (reg_params
[i
].direction
!= PARAM_OUT
)
447 struct reg
*reg
= register_get_by_name(mips32
->core_cache
, reg_params
[i
].reg_name
, 0);
450 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
451 return ERROR_INVALID_ARGUMENTS
;
454 if (reg
->size
!= reg_params
[i
].size
)
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
;
461 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
465 /* restore everything we saved before */
466 for (i
= 0; i
< MIPS32NUMCOREREGS
; i
++)
469 regvalue
= buf_get_u32(mips32
->core_cache
->reg_list
[i
].value
, 0, 32);
470 if (regvalue
!= context
[i
])
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
,
476 mips32
->core_cache
->reg_list
[i
].valid
= 1;
477 mips32
->core_cache
->reg_list
[i
].dirty
= 1;
481 mips32
->isa_mode
= isa_mode
;
486 int mips32_examine(struct target
*target
)
488 struct mips32_common
*mips32
= target_to_mips32(target
);
490 if (!target_was_examined(target
))
492 target_set_examined(target
);
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;
505 int mips32_configure_break_unit(struct target
*target
)
507 /* get pointers to arch-specific information */
508 struct mips32_common
*mips32
= target_to_mips32(target
);
510 uint32_t dcr
, bpinfo
;
513 if (mips32
->bp_scanned
)
516 /* get info about breakpoint support */
517 if ((retval
= target_read_u32(target
, EJTAG_DCR
, &dcr
)) != ERROR_OK
)
520 if (dcr
& EJTAG_DCR_IB
)
522 /* get number of inst breakpoints */
523 if ((retval
= target_read_u32(target
, EJTAG_IBS
, &bpinfo
)) != ERROR_OK
)
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
++)
531 mips32
->inst_break_list
[i
].reg_address
= EJTAG_IBA1
+ (0x100 * i
);
535 if ((retval
= target_write_u32(target
, EJTAG_IBS
, 0)) != ERROR_OK
)
539 if (dcr
& EJTAG_DCR_DB
)
541 /* get number of data breakpoints */
542 if ((retval
= target_read_u32(target
, EJTAG_DBS
, &bpinfo
)) != ERROR_OK
)
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
++)
550 mips32
->data_break_list
[i
].reg_address
= EJTAG_DBA1
+ (0x100 * i
);
554 if ((retval
= target_write_u32(target
, EJTAG_DBS
, 0)) != ERROR_OK
)
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
) ) )
562 LOG_WARNING("DCR endianness settings does not match target settings");
565 LOG_DEBUG("DCR 0x%" PRIx32
" numinst %i numdata %i", dcr
, mips32
->num_inst_bpoints
,
566 mips32
->num_data_bpoints
);
568 mips32
->bp_scanned
= 1;
573 int mips32_enable_interrupts(struct target
*target
, int enable
)
579 /* read debug control register */
580 if ((retval
= target_read_u32(target
, EJTAG_DCR
, &dcr
)) != ERROR_OK
)
585 if (!(dcr
& EJTAG_DCR_INTE
))
587 /* enable interrupts */
588 dcr
|= EJTAG_DCR_INTE
;
594 if (dcr
& EJTAG_DCR_INTE
)
596 /* disable interrupts */
597 dcr
&= ~EJTAG_DCR_INTE
;
604 if ((retval
= target_write_u32(target
, EJTAG_DCR
, dcr
)) != ERROR_OK
)
611 int mips32_checksum_memory(struct target
*target
, uint32_t address
,
612 uint32_t count
, uint32_t* checksum
)
614 struct working_area
*crc_algorithm
;
615 struct reg_param reg_params
[2];
616 struct mips32_algorithm mips32_info
;
620 /* see contib/loaders/checksum/mips32.s for src */
622 static const uint32_t mips_crc_code
[] =
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 */
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 */
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 */
647 0x154BFFF0, /* bne $t2, $t3, nbyte */
648 0x256B0001, /* addiu $t3, $t3, 1 */
649 0x7000003F, /* sdbbp */
652 /* make sure we have a working area */
653 if (target_alloc_working_area(target
, sizeof(mips_crc_code
), &crc_algorithm
) != ERROR_OK
)
655 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
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
]);
662 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
663 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
665 init_reg_param(®_params
[0], "a0", 32, PARAM_IN_OUT
);
666 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
668 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
669 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
671 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
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
)
677 destroy_reg_param(®_params
[0]);
678 destroy_reg_param(®_params
[1]);
679 target_free_working_area(target
, crc_algorithm
);
683 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
685 destroy_reg_param(®_params
[0]);
686 destroy_reg_param(®_params
[1]);
688 target_free_working_area(target
, crc_algorithm
);
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
)
697 struct working_area
*erase_check_algorithm
;
698 struct reg_param reg_params
[3];
699 struct mips32_algorithm mips32_info
;
703 static const uint32_t erase_check_code
[] =
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 */
714 /* make sure we have a working area */
715 if (target_alloc_working_area(target
, sizeof(erase_check_code
), &erase_check_algorithm
) != ERROR_OK
)
717 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
720 /* convert flash writing code into a buffer in target endianness */
721 for (i
= 0; i
< ARRAY_SIZE(erase_check_code
); i
++)
723 target_write_u32(target
, erase_check_algorithm
->address
+ i
*sizeof(uint32_t),
724 erase_check_code
[i
]);
727 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
728 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
730 init_reg_param(®_params
[0], "a0", 32, PARAM_OUT
);
731 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
733 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
734 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
736 init_reg_param(®_params
[2], "a2", 32, PARAM_IN_OUT
);
737 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
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
)
744 destroy_reg_param(®_params
[0]);
745 destroy_reg_param(®_params
[1]);
746 destroy_reg_param(®_params
[2]);
747 target_free_working_area(target
, erase_check_algorithm
);
751 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
753 destroy_reg_param(®_params
[0]);
754 destroy_reg_param(®_params
[1]);
755 destroy_reg_param(®_params
[2]);
757 target_free_working_area(target
, erase_check_algorithm
);
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)