1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2008 by John McCarthy *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
32 #include <target/algorithm.h>
33 #include <target/mips32.h>
34 #include <target/mips_m4k.h>
36 static const struct pic32mx_devs_s
{
67 /* flash bank pic32mx <base> <size> 0 0 <target#>
69 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command
)
71 struct pic32mx_flash_bank
*pic32mx_info
;
75 LOG_WARNING("incomplete flash_bank pic32mx configuration");
76 return ERROR_FLASH_BANK_INVALID
;
79 pic32mx_info
= malloc(sizeof(struct pic32mx_flash_bank
));
80 bank
->driver_priv
= pic32mx_info
;
82 pic32mx_info
->write_algorithm
= NULL
;
83 pic32mx_info
->probed
= 0;
88 static uint32_t pic32mx_get_flash_status(struct flash_bank
*bank
)
90 struct target
*target
= bank
->target
;
93 target_read_u32(target
, PIC32MX_NVMCON
, &status
);
98 static uint32_t pic32mx_wait_status_busy(struct flash_bank
*bank
, int timeout
)
102 /* wait for busy to clear */
103 while (((status
= pic32mx_get_flash_status(bank
)) & NVMCON_NVMWR
) && (timeout
-- > 0))
105 LOG_DEBUG("status: 0x%" PRIx32
, status
);
109 LOG_DEBUG("timeout: status: 0x%" PRIx32
, status
);
114 static int pic32mx_nvm_exec(struct flash_bank
*bank
, uint32_t op
, uint32_t timeout
)
116 struct target
*target
= bank
->target
;
119 target_write_u32(target
, PIC32MX_NVMCON
, NVMCON_NVMWREN
| op
);
121 /* unlock flash registers */
122 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY1
);
123 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY2
);
125 /* start operation */
126 target_write_u32(target
, PIC32MX_NVMCONSET
, NVMCON_NVMWR
);
128 status
= pic32mx_wait_status_busy(bank
, timeout
);
130 /* lock flash registers */
131 target_write_u32(target
, PIC32MX_NVMCONCLR
, NVMCON_NVMWREN
);
136 static int pic32mx_protect_check(struct flash_bank
*bank
)
138 struct target
*target
= bank
->target
;
144 if (target
->state
!= TARGET_HALTED
)
146 LOG_ERROR("Target not halted");
147 return ERROR_TARGET_NOT_HALTED
;
150 target_read_u32(target
, PIC32MX_DEVCFG0
, &devcfg0
);
152 if ((devcfg0
& (1 << 28)) == 0) /* code protect bit */
153 num_pages
= 0xffff; /* All pages protected */
154 else if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
)
156 if (devcfg0
& (1 << 24))
157 num_pages
= 0; /* All pages unprotected */
159 num_pages
= 0xffff; /* All pages protected */
162 num_pages
= (~devcfg0
>> 12) & 0xff;
164 for (s
= 0; s
< bank
->num_sectors
&& s
< num_pages
; s
++)
165 bank
->sectors
[s
].is_protected
= 1;
166 for (; s
< bank
->num_sectors
; s
++)
167 bank
->sectors
[s
].is_protected
= 0;
172 static int pic32mx_erase(struct flash_bank
*bank
, int first
, int last
)
174 struct target
*target
= bank
->target
;
178 if (bank
->target
->state
!= TARGET_HALTED
)
180 LOG_ERROR("Target not halted");
181 return ERROR_TARGET_NOT_HALTED
;
184 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))
185 && (Virt2Phys(bank
->base
) == PIC32MX_PHYS_PGM_FLASH
))
187 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
188 * we need to use the MTAP to perform a full erase */
189 LOG_DEBUG("Erasing entire program flash");
190 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PFM_ERASE
, 50);
191 if (status
& NVMCON_NVMERR
)
192 return ERROR_FLASH_OPERATION_FAILED
;
193 if (status
& NVMCON_LVDERR
)
194 return ERROR_FLASH_OPERATION_FAILED
;
198 for (i
= first
; i
<= last
; i
++)
200 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(bank
->base
+ bank
->sectors
[i
].offset
));
202 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PAGE_ERASE
, 10);
204 if (status
& NVMCON_NVMERR
)
205 return ERROR_FLASH_OPERATION_FAILED
;
206 if (status
& NVMCON_LVDERR
)
207 return ERROR_FLASH_OPERATION_FAILED
;
208 bank
->sectors
[i
].is_erased
= 1;
214 static int pic32mx_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
216 struct pic32mx_flash_bank
*pic32mx_info
= NULL
;
217 struct target
*target
= bank
->target
;
219 pic32mx_info
= bank
->driver_priv
;
221 if (target
->state
!= TARGET_HALTED
)
223 LOG_ERROR("Target not halted");
224 return ERROR_TARGET_NOT_HALTED
;
230 static const uint32_t pic32mx_flash_write_code
[] = {
232 0x3C08AA99, /* lui $t0, 0xaa99 */
233 0x35086655, /* ori $t0, 0x6655 */
234 0x3C095566, /* lui $t1, 0x5566 */
235 0x352999AA, /* ori $t1, 0x99aa */
236 0x3C0ABF80, /* lui $t2, 0xbf80 */
237 0x354AF400, /* ori $t2, 0xf400 */
238 0x340B4003, /* ori $t3, $zero, 0x4003 */
239 0x340C8000, /* ori $t4, $zero, 0x8000 */
241 0x2CD30080, /* sltiu $s3, $a2, 128 */
242 0x16600008, /* bne $s3, $zero, write_word */
243 0x340D4000, /* ori $t5, $zero, 0x4000 */
244 0xAD450020, /* sw $a1, 32($t2) */
245 0xAD440040, /* sw $a0, 64($t2) */
246 0x04110016, /* bal progflash */
247 0x24840200, /* addiu $a0, $a0, 512 */
248 0x24A50200, /* addiu $a1, $a1, 512 */
249 0x1000FFF7, /* beq $zero, $zero, write_row */
250 0x24C6FF80, /* addiu $a2, $a2, -128 */
252 0x3C15A000, /* lui $s5, 0xa000 */
253 0x36B50000, /* ori $s5, $s5, 0x0 */
254 0x00952025, /* or $a0, $a0, $s5 */
255 0x10000008, /* beq $zero, $zero, next_word */
256 0x340B4001, /* ori $t3, $zero, 0x4001 */
258 0x8C940000, /* lw $s4, 0($a0) */
259 0xAD540030, /* sw $s4, 48($t2) */
260 0xAD450020, /* sw $a1, 32($t2) */
261 0x04110009, /* bal progflash */
262 0x24840004, /* addiu $a0, $a0, 4 */
263 0x24A50004, /* addiu $a1, $a1, 4 */
264 0x24C6FFFF, /* addiu $a2, $a2, -1 */
266 0x14C0FFF8, /* bne $a2, $zero, prog_word */
267 0x00000000, /* nop */
269 0x10000002, /* beq $zero, $zero, exit */
270 0x24040000, /* addiu $a0, $zero, 0 */
272 0x26240000, /* addiu $a0, $s1, 0 */
274 0x7000003F, /* sdbbp */
276 0xAD4B0000, /* sw $t3, 0($t2) */
277 0xAD480010, /* sw $t0, 16($t2) */
278 0xAD490010, /* sw $t1, 16($t2) */
279 0xAD4C0008, /* sw $t4, 8($t2) */
281 0x8D500000, /* lw $s0, 0($t2) */
282 0x020C8024, /* and $s0, $s0, $t4 */
283 0x1600FFFD, /* bne $s0, $zero, waitflash */
284 0x00000000, /* nop */
285 0x00000000, /* nop */
286 0x00000000, /* nop */
287 0x00000000, /* nop */
288 0x00000000, /* nop */
289 0x8D510000, /* lw $s1, 0($t2) */
290 0x30113000, /* andi $s1, $zero, 0x3000 */
291 0x1620FFEF, /* bne $s1, $zero, error */
292 0xAD4D0004, /* sw $t5, 4($t2) */
293 0x03E00008, /* jr $ra */
297 static int pic32mx_write_block(struct flash_bank
*bank
, uint8_t *buffer
,
298 uint32_t offset
, uint32_t count
)
300 struct target
*target
= bank
->target
;
301 uint32_t buffer_size
= 16384;
302 struct working_area
*source
;
303 uint32_t address
= bank
->base
+ offset
;
304 struct reg_param reg_params
[3];
305 int retval
= ERROR_OK
;
307 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
308 struct mips32_algorithm mips32_info
;
310 /* flash write code */
311 if (target_alloc_working_area(target
, sizeof(pic32mx_flash_write_code
),
312 &pic32mx_info
->write_algorithm
) != ERROR_OK
)
314 LOG_WARNING("no working area available, can't do block memory writes");
315 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
318 if ((retval
= target_write_buffer(target
,
319 pic32mx_info
->write_algorithm
->address
,
320 sizeof(pic32mx_flash_write_code
),
321 (uint8_t*)pic32mx_flash_write_code
)) != ERROR_OK
)
325 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
)
328 if (buffer_size
<= 256)
330 /* if we already allocated the writing code, but failed to get a
331 * buffer, free the algorithm */
332 if (pic32mx_info
->write_algorithm
)
333 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
335 LOG_WARNING("no large enough working area available, can't do block memory writes");
336 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
340 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
341 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
343 init_reg_param(®_params
[0], "a0", 32, PARAM_IN_OUT
);
344 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
345 init_reg_param(®_params
[2], "a2", 32, PARAM_OUT
);
350 uint32_t thisrun_count
= (count
> (buffer_size
/ 4)) ?
351 (buffer_size
/ 4) : count
;
353 if ((retval
= target_write_buffer(target
, source
->address
,
354 thisrun_count
* 4, buffer
)) != ERROR_OK
)
357 buf_set_u32(reg_params
[0].value
, 0, 32, Virt2Phys(source
->address
));
358 buf_set_u32(reg_params
[1].value
, 0, 32, Virt2Phys(address
));
359 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
361 if ((retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
362 pic32mx_info
->write_algorithm
->address
,
363 pic32mx_info
->write_algorithm
->address
+ (sizeof(pic32mx_flash_write_code
) - 76),
364 10000, &mips32_info
)) != ERROR_OK
)
366 LOG_ERROR("error executing pic32mx flash write algorithm");
367 retval
= ERROR_FLASH_OPERATION_FAILED
;
371 status
= buf_get_u32(reg_params
[0].value
, 0, 32);
373 if (status
& NVMCON_NVMERR
)
375 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
376 retval
= ERROR_FLASH_OPERATION_FAILED
;
380 if (status
& NVMCON_LVDERR
)
382 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
383 retval
= ERROR_FLASH_OPERATION_FAILED
;
387 buffer
+= thisrun_count
* 4;
388 address
+= thisrun_count
* 4;
389 count
-= thisrun_count
;
392 target_free_working_area(target
, source
);
393 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
395 destroy_reg_param(®_params
[0]);
396 destroy_reg_param(®_params
[1]);
397 destroy_reg_param(®_params
[2]);
402 static int pic32mx_write_word(struct flash_bank
*bank
, uint32_t address
, uint32_t word
)
404 struct target
*target
= bank
->target
;
406 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(address
));
407 target_write_u32(target
, PIC32MX_NVMDATA
, word
);
409 return pic32mx_nvm_exec(bank
, NVMCON_OP_WORD_PROG
, 5);
412 static int pic32mx_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
414 uint32_t words_remaining
= (count
/ 4);
415 uint32_t bytes_remaining
= (count
& 0x00000003);
416 uint32_t address
= bank
->base
+ offset
;
417 uint32_t bytes_written
= 0;
421 if (bank
->target
->state
!= TARGET_HALTED
)
423 LOG_ERROR("Target not halted");
424 return ERROR_TARGET_NOT_HALTED
;
427 LOG_DEBUG("writing to flash at address 0x%08" PRIx32
" at offset 0x%8.8" PRIx32
428 " count: 0x%8.8" PRIx32
"", bank
->base
, offset
, count
);
432 LOG_WARNING("offset 0x%" PRIx32
"breaks required 4-byte alignment", offset
);
433 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
436 /* multiple words (4-byte) to be programmed? */
437 if (words_remaining
> 0)
439 /* try using a block write */
440 if ((retval
= pic32mx_write_block(bank
, buffer
, offset
, words_remaining
)) != ERROR_OK
)
442 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
444 /* if block write failed (no sufficient working area),
445 * we use normal (slow) single dword accesses */
446 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
448 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
450 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
451 return ERROR_FLASH_OPERATION_FAILED
;
456 buffer
+= words_remaining
* 4;
457 address
+= words_remaining
* 4;
462 while (words_remaining
> 0)
465 memcpy(&value
, buffer
+ bytes_written
, sizeof(uint32_t));
467 status
= pic32mx_write_word(bank
, address
, value
);
469 if (status
& NVMCON_NVMERR
)
471 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
472 return ERROR_FLASH_OPERATION_FAILED
;
475 if (status
& NVMCON_LVDERR
)
477 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
478 return ERROR_FLASH_OPERATION_FAILED
;
488 uint32_t value
= 0xffffffff;
489 memcpy(&value
, buffer
+ bytes_written
, bytes_remaining
);
491 status
= pic32mx_write_word(bank
, address
, value
);
493 if (status
& NVMCON_NVMERR
)
495 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
496 return ERROR_FLASH_OPERATION_FAILED
;
499 if (status
& NVMCON_LVDERR
)
501 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
502 return ERROR_FLASH_OPERATION_FAILED
;
509 static int pic32mx_probe(struct flash_bank
*bank
)
511 struct target
*target
= bank
->target
;
512 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
513 struct mips32_common
*mips32
= target
->arch_info
;
514 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
516 uint32_t num_pages
= 0;
520 pic32mx_info
->probed
= 0;
522 device_id
= ejtag_info
->idcode
;
523 LOG_INFO("device id = 0x%08" PRIx32
" (manuf 0x%03x dev 0x%02x, ver 0x%02x)",
525 (unsigned)((device_id
>> 1) & 0x7ff),
526 (unsigned)((device_id
>> 12) & 0xff),
527 (unsigned)((device_id
>> 28) & 0xf));
529 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
530 LOG_WARNING("Cannot identify target as a PIC32MX family.");
531 return ERROR_FLASH_OPERATION_FAILED
;
536 if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
)
538 /* 0x1FC00000: Boot flash size */
540 /* for some reason this register returns 8k for the boot bank size
541 * this does not match the docs, so for now set the boot bank at a
543 if (target_read_u32(target
, PIC32MX_BMXBOOTSZ
, &num_pages
) != ERROR_OK
) {
544 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
545 num_pages
= (12 * 1024);
548 /* fixed 12k boot bank - see comments above */
549 num_pages
= (12 * 1024);
554 /* read the flash size from the device */
555 if (target_read_u32(target
, PIC32MX_BMXPFMSZ
, &num_pages
) != ERROR_OK
) {
556 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
557 num_pages
= (512 * 1024);
561 LOG_INFO("flash size = %" PRId32
"kbytes", num_pages
/ 1024);
563 /* calculate numbers of pages */
564 num_pages
/= page_size
;
565 bank
->size
= (num_pages
* page_size
);
566 bank
->num_sectors
= num_pages
;
567 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
569 for (i
= 0; i
< (int)num_pages
; i
++)
571 bank
->sectors
[i
].offset
= i
* page_size
;
572 bank
->sectors
[i
].size
= page_size
;
573 bank
->sectors
[i
].is_erased
= -1;
574 bank
->sectors
[i
].is_protected
= 1;
577 pic32mx_info
->probed
= 1;
582 static int pic32mx_auto_probe(struct flash_bank
*bank
)
584 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
585 if (pic32mx_info
->probed
)
587 return pic32mx_probe(bank
);
590 static int pic32mx_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
592 struct target
*target
= bank
->target
;
593 struct mips32_common
*mips32
= target
->arch_info
;
594 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
598 device_id
= ejtag_info
->idcode
;
600 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
601 snprintf(buf
, buf_size
,
602 "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
603 (unsigned)((device_id
>> 1) & 0x7ff),
605 return ERROR_FLASH_OPERATION_FAILED
;
608 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++)
610 if (pic32mx_devs
[i
].devid
== ((device_id
>> 12) & 0xff)) {
611 printed
= snprintf(buf
, buf_size
, "PIC32MX%s", pic32mx_devs
[i
].name
);
616 if (pic32mx_devs
[i
].name
== NULL
) {
617 printed
= snprintf(buf
, buf_size
, "Unknown");
622 printed
= snprintf(buf
, buf_size
, " Ver: 0x%02x",
623 (unsigned)((device_id
>> 28) & 0xf));
628 COMMAND_HANDLER(pic32mx_handle_pgm_word_command
)
630 uint32_t address
, value
;
635 command_print(CMD_CTX
, "pic32mx pgm_word <addr> <value> <bank>");
639 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
640 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
642 struct flash_bank
*bank
;
643 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 2, &bank
);
644 if (ERROR_OK
!= retval
)
647 if (address
< bank
->base
|| address
>= (bank
->base
+ bank
->size
))
649 command_print(CMD_CTX
, "flash address '%s' is out of bounds", CMD_ARGV
[0]);
654 status
= pic32mx_write_word(bank
, address
, value
);
655 if (status
& NVMCON_NVMERR
)
656 res
= ERROR_FLASH_OPERATION_FAILED
;
657 if (status
& NVMCON_LVDERR
)
658 res
= ERROR_FLASH_OPERATION_FAILED
;
661 command_print(CMD_CTX
, "pic32mx pgm word complete");
663 command_print(CMD_CTX
, "pic32mx pgm word failed (status = 0x%x)", status
);
668 COMMAND_HANDLER(pic32mx_handle_unlock_command
)
671 struct target
*target
= NULL
;
672 struct mips_m4k_common
*mips_m4k
;
673 struct mips_ejtag
*ejtag_info
;
678 command_print(CMD_CTX
, "pic32mx unlock <bank>");
682 struct flash_bank
*bank
;
683 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
684 if (ERROR_OK
!= retval
)
687 target
= bank
->target
;
688 mips_m4k
= target_to_m4k(target
);
689 ejtag_info
= &mips_m4k
->mips32
.ejtag_info
;
691 /* we have to use the MTAP to perform a full erase */
692 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_MTAP
);
693 mips_ejtag_set_instr(ejtag_info
, MTAP_COMMAND
);
695 /* first check status of device */
696 mchip_cmd
= MCHP_STATUS
;
697 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
698 if (mchip_cmd
& (1 << 7))
700 /* device is not locked */
701 command_print(CMD_CTX
, "pic32mx is already unlocked, erasing anyway");
704 /* unlock/erase device */
705 mchip_cmd
= MCHP_ASERT_RST
;
706 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
708 mchip_cmd
= MCHP_ERASE
;
709 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
712 mchip_cmd
= MCHP_STATUS
;
713 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
716 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32
"", mchip_cmd
);
720 } while ((mchip_cmd
& (1 << 2)) || (!(mchip_cmd
& (1 << 3))));
722 mchip_cmd
= MCHP_DE_ASSERT_RST
;
723 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
725 /* select ejtag tap */
726 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_ETAP
);
728 command_print(CMD_CTX
, "pic32mx unlocked.\n"
729 "INFO: a reset or power cycle is required "
730 "for the new settings to take effect.");
735 static const struct command_registration pic32mx_exec_command_handlers
[] = {
738 .handler
= pic32mx_handle_pgm_word_command
,
739 .mode
= COMMAND_EXEC
,
740 .help
= "program a word",
744 .handler
= pic32mx_handle_unlock_command
,
745 .mode
= COMMAND_EXEC
,
746 .usage
= "[bank_id]",
747 .help
= "Unlock/Erase entire device.",
749 COMMAND_REGISTRATION_DONE
752 static const struct command_registration pic32mx_command_handlers
[] = {
756 .help
= "pic32mx flash command group",
757 .chain
= pic32mx_exec_command_handlers
,
759 COMMAND_REGISTRATION_DONE
762 struct flash_driver pic32mx_flash
= {
764 .commands
= pic32mx_command_handlers
,
765 .flash_bank_command
= pic32mx_flash_bank_command
,
766 .erase
= pic32mx_erase
,
767 .protect
= pic32mx_protect
,
768 .write
= pic32mx_write
,
769 .probe
= pic32mx_probe
,
770 .auto_probe
= pic32mx_auto_probe
,
771 .erase_check
= default_flash_mem_blank_check
,
772 .protect_check
= pic32mx_protect_check
,
773 .info
= pic32mx_info
,
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)