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 /* see contib/loaders/flash/pic32mx.s for src */
232 static const uint32_t pic32mx_flash_write_code
[] = {
234 0x3C08AA99, /* lui $t0, 0xaa99 */
235 0x35086655, /* ori $t0, 0x6655 */
236 0x3C095566, /* lui $t1, 0x5566 */
237 0x352999AA, /* ori $t1, 0x99aa */
238 0x3C0ABF80, /* lui $t2, 0xbf80 */
239 0x354AF400, /* ori $t2, 0xf400 */
240 0x340B4003, /* ori $t3, $zero, 0x4003 */
241 0x340C8000, /* ori $t4, $zero, 0x8000 */
243 0x2CD30080, /* sltiu $s3, $a2, 128 */
244 0x16600008, /* bne $s3, $zero, write_word */
245 0x340D4000, /* ori $t5, $zero, 0x4000 */
246 0xAD450020, /* sw $a1, 32($t2) */
247 0xAD440040, /* sw $a0, 64($t2) */
248 0x04110016, /* bal progflash */
249 0x24840200, /* addiu $a0, $a0, 512 */
250 0x24A50200, /* addiu $a1, $a1, 512 */
251 0x1000FFF7, /* beq $zero, $zero, write_row */
252 0x24C6FF80, /* addiu $a2, $a2, -128 */
254 0x3C15A000, /* lui $s5, 0xa000 */
255 0x36B50000, /* ori $s5, $s5, 0x0 */
256 0x00952025, /* or $a0, $a0, $s5 */
257 0x10000008, /* beq $zero, $zero, next_word */
258 0x340B4001, /* ori $t3, $zero, 0x4001 */
260 0x8C940000, /* lw $s4, 0($a0) */
261 0xAD540030, /* sw $s4, 48($t2) */
262 0xAD450020, /* sw $a1, 32($t2) */
263 0x04110009, /* bal progflash */
264 0x24840004, /* addiu $a0, $a0, 4 */
265 0x24A50004, /* addiu $a1, $a1, 4 */
266 0x24C6FFFF, /* addiu $a2, $a2, -1 */
268 0x14C0FFF8, /* bne $a2, $zero, prog_word */
269 0x00000000, /* nop */
271 0x10000002, /* beq $zero, $zero, exit */
272 0x24040000, /* addiu $a0, $zero, 0 */
274 0x26240000, /* addiu $a0, $s1, 0 */
276 0x7000003F, /* sdbbp */
278 0xAD4B0000, /* sw $t3, 0($t2) */
279 0xAD480010, /* sw $t0, 16($t2) */
280 0xAD490010, /* sw $t1, 16($t2) */
281 0xAD4C0008, /* sw $t4, 8($t2) */
283 0x8D500000, /* lw $s0, 0($t2) */
284 0x020C8024, /* and $s0, $s0, $t4 */
285 0x1600FFFD, /* bne $s0, $zero, waitflash */
286 0x00000000, /* nop */
287 0x00000000, /* nop */
288 0x00000000, /* nop */
289 0x00000000, /* nop */
290 0x00000000, /* nop */
291 0x8D510000, /* lw $s1, 0($t2) */
292 0x30113000, /* andi $s1, $zero, 0x3000 */
293 0x1620FFEF, /* bne $s1, $zero, error */
294 0xAD4D0004, /* sw $t5, 4($t2) */
295 0x03E00008, /* jr $ra */
299 static int pic32mx_write_block(struct flash_bank
*bank
, uint8_t *buffer
,
300 uint32_t offset
, uint32_t count
)
302 struct target
*target
= bank
->target
;
303 uint32_t buffer_size
= 16384;
304 struct working_area
*source
;
305 uint32_t address
= bank
->base
+ offset
;
306 struct reg_param reg_params
[3];
307 int retval
= ERROR_OK
;
309 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
310 struct mips32_algorithm mips32_info
;
312 /* flash write code */
313 if (target_alloc_working_area(target
, sizeof(pic32mx_flash_write_code
),
314 &pic32mx_info
->write_algorithm
) != ERROR_OK
)
316 LOG_WARNING("no working area available, can't do block memory writes");
317 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
320 if ((retval
= target_write_buffer(target
,
321 pic32mx_info
->write_algorithm
->address
,
322 sizeof(pic32mx_flash_write_code
),
323 (uint8_t*)pic32mx_flash_write_code
)) != ERROR_OK
)
327 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
)
330 if (buffer_size
<= 256)
332 /* if we already allocated the writing code, but failed to get a
333 * buffer, free the algorithm */
334 if (pic32mx_info
->write_algorithm
)
335 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
337 LOG_WARNING("no large enough working area available, can't do block memory writes");
338 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
342 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
343 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
345 init_reg_param(®_params
[0], "a0", 32, PARAM_IN_OUT
);
346 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
347 init_reg_param(®_params
[2], "a2", 32, PARAM_OUT
);
352 uint32_t thisrun_count
= (count
> (buffer_size
/ 4)) ?
353 (buffer_size
/ 4) : count
;
355 if ((retval
= target_write_buffer(target
, source
->address
,
356 thisrun_count
* 4, buffer
)) != ERROR_OK
)
359 buf_set_u32(reg_params
[0].value
, 0, 32, Virt2Phys(source
->address
));
360 buf_set_u32(reg_params
[1].value
, 0, 32, Virt2Phys(address
));
361 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
363 if ((retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
364 pic32mx_info
->write_algorithm
->address
,
366 10000, &mips32_info
)) != ERROR_OK
)
368 LOG_ERROR("error executing pic32mx flash write algorithm");
369 retval
= ERROR_FLASH_OPERATION_FAILED
;
373 status
= buf_get_u32(reg_params
[0].value
, 0, 32);
375 if (status
& NVMCON_NVMERR
)
377 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
378 retval
= ERROR_FLASH_OPERATION_FAILED
;
382 if (status
& NVMCON_LVDERR
)
384 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
385 retval
= ERROR_FLASH_OPERATION_FAILED
;
389 buffer
+= thisrun_count
* 4;
390 address
+= thisrun_count
* 4;
391 count
-= thisrun_count
;
394 target_free_working_area(target
, source
);
395 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
397 destroy_reg_param(®_params
[0]);
398 destroy_reg_param(®_params
[1]);
399 destroy_reg_param(®_params
[2]);
404 static int pic32mx_write_word(struct flash_bank
*bank
, uint32_t address
, uint32_t word
)
406 struct target
*target
= bank
->target
;
408 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(address
));
409 target_write_u32(target
, PIC32MX_NVMDATA
, word
);
411 return pic32mx_nvm_exec(bank
, NVMCON_OP_WORD_PROG
, 5);
414 static int pic32mx_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
416 uint32_t words_remaining
= (count
/ 4);
417 uint32_t bytes_remaining
= (count
& 0x00000003);
418 uint32_t address
= bank
->base
+ offset
;
419 uint32_t bytes_written
= 0;
423 if (bank
->target
->state
!= TARGET_HALTED
)
425 LOG_ERROR("Target not halted");
426 return ERROR_TARGET_NOT_HALTED
;
429 LOG_DEBUG("writing to flash at address 0x%08" PRIx32
" at offset 0x%8.8" PRIx32
430 " count: 0x%8.8" PRIx32
"", bank
->base
, offset
, count
);
434 LOG_WARNING("offset 0x%" PRIx32
"breaks required 4-byte alignment", offset
);
435 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
438 /* multiple words (4-byte) to be programmed? */
439 if (words_remaining
> 0)
441 /* try using a block write */
442 if ((retval
= pic32mx_write_block(bank
, buffer
, offset
, words_remaining
)) != ERROR_OK
)
444 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
446 /* if block write failed (no sufficient working area),
447 * we use normal (slow) single dword accesses */
448 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
450 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
452 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
453 return ERROR_FLASH_OPERATION_FAILED
;
458 buffer
+= words_remaining
* 4;
459 address
+= words_remaining
* 4;
464 while (words_remaining
> 0)
467 memcpy(&value
, buffer
+ bytes_written
, sizeof(uint32_t));
469 status
= pic32mx_write_word(bank
, address
, value
);
471 if (status
& NVMCON_NVMERR
)
473 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
474 return ERROR_FLASH_OPERATION_FAILED
;
477 if (status
& NVMCON_LVDERR
)
479 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
480 return ERROR_FLASH_OPERATION_FAILED
;
490 uint32_t value
= 0xffffffff;
491 memcpy(&value
, buffer
+ bytes_written
, bytes_remaining
);
493 status
= pic32mx_write_word(bank
, address
, value
);
495 if (status
& NVMCON_NVMERR
)
497 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
498 return ERROR_FLASH_OPERATION_FAILED
;
501 if (status
& NVMCON_LVDERR
)
503 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
504 return ERROR_FLASH_OPERATION_FAILED
;
511 static int pic32mx_probe(struct flash_bank
*bank
)
513 struct target
*target
= bank
->target
;
514 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
515 struct mips32_common
*mips32
= target
->arch_info
;
516 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
518 uint32_t num_pages
= 0;
522 pic32mx_info
->probed
= 0;
524 device_id
= ejtag_info
->idcode
;
525 LOG_INFO("device id = 0x%08" PRIx32
" (manuf 0x%03x dev 0x%02x, ver 0x%02x)",
527 (unsigned)((device_id
>> 1) & 0x7ff),
528 (unsigned)((device_id
>> 12) & 0xff),
529 (unsigned)((device_id
>> 28) & 0xf));
531 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
532 LOG_WARNING("Cannot identify target as a PIC32MX family.");
533 return ERROR_FLASH_OPERATION_FAILED
;
538 if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
)
540 /* 0x1FC00000: Boot flash size */
542 /* for some reason this register returns 8k for the boot bank size
543 * this does not match the docs, so for now set the boot bank at a
545 if (target_read_u32(target
, PIC32MX_BMXBOOTSZ
, &num_pages
) != ERROR_OK
) {
546 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
547 num_pages
= (12 * 1024);
550 /* fixed 12k boot bank - see comments above */
551 num_pages
= (12 * 1024);
556 /* read the flash size from the device */
557 if (target_read_u32(target
, PIC32MX_BMXPFMSZ
, &num_pages
) != ERROR_OK
) {
558 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
559 num_pages
= (512 * 1024);
563 LOG_INFO("flash size = %" PRId32
"kbytes", num_pages
/ 1024);
568 bank
->sectors
= NULL
;
571 /* calculate numbers of pages */
572 num_pages
/= page_size
;
573 bank
->size
= (num_pages
* page_size
);
574 bank
->num_sectors
= num_pages
;
575 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
577 for (i
= 0; i
< (int)num_pages
; i
++)
579 bank
->sectors
[i
].offset
= i
* page_size
;
580 bank
->sectors
[i
].size
= page_size
;
581 bank
->sectors
[i
].is_erased
= -1;
582 bank
->sectors
[i
].is_protected
= 1;
585 pic32mx_info
->probed
= 1;
590 static int pic32mx_auto_probe(struct flash_bank
*bank
)
592 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
593 if (pic32mx_info
->probed
)
595 return pic32mx_probe(bank
);
598 static int pic32mx_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
600 struct target
*target
= bank
->target
;
601 struct mips32_common
*mips32
= target
->arch_info
;
602 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
606 device_id
= ejtag_info
->idcode
;
608 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
609 snprintf(buf
, buf_size
,
610 "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
611 (unsigned)((device_id
>> 1) & 0x7ff),
613 return ERROR_FLASH_OPERATION_FAILED
;
616 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++)
618 if (pic32mx_devs
[i
].devid
== ((device_id
>> 12) & 0xff)) {
619 printed
= snprintf(buf
, buf_size
, "PIC32MX%s", pic32mx_devs
[i
].name
);
624 if (pic32mx_devs
[i
].name
== NULL
) {
625 printed
= snprintf(buf
, buf_size
, "Unknown");
630 printed
= snprintf(buf
, buf_size
, " Ver: 0x%02x",
631 (unsigned)((device_id
>> 28) & 0xf));
636 COMMAND_HANDLER(pic32mx_handle_pgm_word_command
)
638 uint32_t address
, value
;
643 command_print(CMD_CTX
, "pic32mx pgm_word <addr> <value> <bank>");
647 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
648 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
650 struct flash_bank
*bank
;
651 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 2, &bank
);
652 if (ERROR_OK
!= retval
)
655 if (address
< bank
->base
|| address
>= (bank
->base
+ bank
->size
))
657 command_print(CMD_CTX
, "flash address '%s' is out of bounds", CMD_ARGV
[0]);
662 status
= pic32mx_write_word(bank
, address
, value
);
663 if (status
& NVMCON_NVMERR
)
664 res
= ERROR_FLASH_OPERATION_FAILED
;
665 if (status
& NVMCON_LVDERR
)
666 res
= ERROR_FLASH_OPERATION_FAILED
;
669 command_print(CMD_CTX
, "pic32mx pgm word complete");
671 command_print(CMD_CTX
, "pic32mx pgm word failed (status = 0x%x)", status
);
676 COMMAND_HANDLER(pic32mx_handle_unlock_command
)
679 struct target
*target
= NULL
;
680 struct mips_m4k_common
*mips_m4k
;
681 struct mips_ejtag
*ejtag_info
;
686 command_print(CMD_CTX
, "pic32mx unlock <bank>");
690 struct flash_bank
*bank
;
691 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
692 if (ERROR_OK
!= retval
)
695 target
= bank
->target
;
696 mips_m4k
= target_to_m4k(target
);
697 ejtag_info
= &mips_m4k
->mips32
.ejtag_info
;
699 /* we have to use the MTAP to perform a full erase */
700 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_MTAP
);
701 mips_ejtag_set_instr(ejtag_info
, MTAP_COMMAND
);
703 /* first check status of device */
704 mchip_cmd
= MCHP_STATUS
;
705 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
706 if (mchip_cmd
& (1 << 7))
708 /* device is not locked */
709 command_print(CMD_CTX
, "pic32mx is already unlocked, erasing anyway");
712 /* unlock/erase device */
713 mchip_cmd
= MCHP_ASERT_RST
;
714 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
716 mchip_cmd
= MCHP_ERASE
;
717 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
720 mchip_cmd
= MCHP_STATUS
;
721 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
724 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32
"", mchip_cmd
);
728 } while ((mchip_cmd
& (1 << 2)) || (!(mchip_cmd
& (1 << 3))));
730 mchip_cmd
= MCHP_DE_ASSERT_RST
;
731 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
733 /* select ejtag tap */
734 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_ETAP
);
736 command_print(CMD_CTX
, "pic32mx unlocked.\n"
737 "INFO: a reset or power cycle is required "
738 "for the new settings to take effect.");
743 static const struct command_registration pic32mx_exec_command_handlers
[] = {
746 .handler
= pic32mx_handle_pgm_word_command
,
747 .mode
= COMMAND_EXEC
,
748 .help
= "program a word",
752 .handler
= pic32mx_handle_unlock_command
,
753 .mode
= COMMAND_EXEC
,
754 .usage
= "[bank_id]",
755 .help
= "Unlock/Erase entire device.",
757 COMMAND_REGISTRATION_DONE
760 static const struct command_registration pic32mx_command_handlers
[] = {
764 .help
= "pic32mx flash command group",
765 .chain
= pic32mx_exec_command_handlers
,
767 COMMAND_REGISTRATION_DONE
770 struct flash_driver pic32mx_flash
= {
772 .commands
= pic32mx_command_handlers
,
773 .flash_bank_command
= pic32mx_flash_bank_command
,
774 .erase
= pic32mx_erase
,
775 .protect
= pic32mx_protect
,
776 .write
= pic32mx_write
,
777 .read
= default_flash_read
,
778 .probe
= pic32mx_probe
,
779 .auto_probe
= pic32mx_auto_probe
,
780 .erase_check
= default_flash_mem_blank_check
,
781 .protect_check
= pic32mx_protect_check
,
782 .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)