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 #define PIC32MX_MANUF_ID 0x029
38 /* pic32mx memory locations */
40 #define PIC32MX_PHYS_RAM 0x00000000
41 #define PIC32MX_PHYS_PGM_FLASH 0x1D000000
42 #define PIC32MX_PHYS_PERIPHERALS 0x1F800000
43 #define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000
46 * Translate Virtual and Physical addresses.
47 * Note: These macros only work for KSEG0/KSEG1 addresses.
50 #define Virt2Phys(v) ((v) & 0x1FFFFFFF)
52 /* pic32mx configuration register locations */
54 #define PIC32MX_DEVCFG0 0xBFC02FFC
55 #define PIC32MX_DEVCFG1 0xBFC02FF8
56 #define PIC32MX_DEVCFG2 0xBFC02FF4
57 #define PIC32MX_DEVCFG3 0xBFC02FF0
58 #define PIC32MX_DEVID 0xBF80F220
60 #define PIC32MX_BMXPFMSZ 0xBF882060
61 #define PIC32MX_BMXBOOTSZ 0xBF882070
62 #define PIC32MX_BMXDRMSZ 0xBF882040
64 /* pic32mx flash controller register locations */
66 #define PIC32MX_NVMCON 0xBF80F400
67 #define PIC32MX_NVMCONCLR 0xBF80F404
68 #define PIC32MX_NVMCONSET 0xBF80F408
69 #define PIC32MX_NVMCONINV 0xBF80F40C
70 #define NVMCON_NVMWR (1 << 15)
71 #define NVMCON_NVMWREN (1 << 14)
72 #define NVMCON_NVMERR (1 << 13)
73 #define NVMCON_LVDERR (1 << 12)
74 #define NVMCON_LVDSTAT (1 << 11)
75 #define NVMCON_OP_PFM_ERASE 0x5
76 #define NVMCON_OP_PAGE_ERASE 0x4
77 #define NVMCON_OP_ROW_PROG 0x3
78 #define NVMCON_OP_WORD_PROG 0x1
79 #define NVMCON_OP_NOP 0x0
81 #define PIC32MX_NVMKEY 0xBF80F410
82 #define PIC32MX_NVMADDR 0xBF80F420
83 #define PIC32MX_NVMADDRCLR 0xBF80F424
84 #define PIC32MX_NVMADDRSET 0xBF80F428
85 #define PIC32MX_NVMADDRINV 0xBF80F42C
86 #define PIC32MX_NVMDATA 0xBF80F430
87 #define PIC32MX_NVMSRCADDR 0xBF80F440
89 /* flash unlock keys */
91 #define NVMKEY1 0xAA996655
92 #define NVMKEY2 0x556699AA
94 struct pic32mx_flash_bank
{
95 struct working_area
*write_algorithm
;
100 * DEVID values as per PIC32MX Flash Programming Specification Rev H
103 static const struct pic32mx_devs_s
{
107 {0x04A07053, "110F016B"},
108 {0x04A09053, "110F016C"},
109 {0x04A0B053, "110F016D"},
110 {0x04A06053, "120F032B"},
111 {0x04A08053, "120F032C"},
112 {0x04A0A053, "120F032D"},
113 {0x04A01053, "210F016B"},
114 {0x04A03053, "210F016C"},
115 {0x04A05053, "210F016D"},
116 {0x04A00053, "220F032B"},
117 {0x04A02053, "220F032C"},
118 {0x04A04053, "220F032D"},
119 {0x00938053, "360F512L"},
120 {0x00934053, "360F256L"},
121 {0x0092D053, "340F128L"},
122 {0x0092A053, "320F128L"},
123 {0x00916053, "340F512H"},
124 {0x00912053, "340F256H"},
125 {0x0090D053, "340F128H"},
126 {0x0090A053, "320F128H"},
127 {0x00906053, "320F064H"},
128 {0x00902053, "320F032H"},
129 {0x00978053, "460F512L"},
130 {0x00974053, "460F256L"},
131 {0x0096D053, "440F128L"},
132 {0x00952053, "440F256H"},
133 {0x00956053, "440F512H"},
134 {0x0094D053, "440F128H"},
135 {0x00942053, "420F032H"},
136 {0x04307053, "795F512L"},
137 {0x0430E053, "795F512H"},
138 {0x04306053, "775F512L"},
139 {0x0430D053, "775F512H"},
140 {0x04312053, "775F256L"},
141 {0x04303053, "775F256H"},
142 {0x04417053, "764F128L"},
143 {0x0440B053, "764F128H"},
144 {0x04341053, "695F512L"},
145 {0x04325053, "695F512H"},
146 {0x04311053, "675F512L"},
147 {0x0430C053, "675F512H"},
148 {0x04305053, "675F256L"},
149 {0x0430B053, "675F256H"},
150 {0x04413053, "664F128L"},
151 {0x04407053, "664F128H"},
152 {0x04411053, "664F064L"},
153 {0x04405053, "664F064H"},
154 {0x0430F053, "575F512L"},
155 {0x04309053, "575F512H"},
156 {0x04333053, "575F256L"},
157 {0x04317053, "575F256H"},
158 {0x0440F053, "564F128L"},
159 {0x04403053, "564F128H"},
160 {0x0440D053, "564F064L"},
161 {0x04401053, "564F064H"},
162 {0x04400053, "534F064H"},
163 {0x0440C053, "534F064L"},
167 /* flash bank pic32mx <base> <size> 0 0 <target#>
169 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command
)
171 struct pic32mx_flash_bank
*pic32mx_info
;
174 return ERROR_COMMAND_SYNTAX_ERROR
;
176 pic32mx_info
= malloc(sizeof(struct pic32mx_flash_bank
));
177 bank
->driver_priv
= pic32mx_info
;
179 pic32mx_info
->write_algorithm
= NULL
;
180 pic32mx_info
->probed
= 0;
185 static uint32_t pic32mx_get_flash_status(struct flash_bank
*bank
)
187 struct target
*target
= bank
->target
;
190 target_read_u32(target
, PIC32MX_NVMCON
, &status
);
195 static uint32_t pic32mx_wait_status_busy(struct flash_bank
*bank
, int timeout
)
199 /* wait for busy to clear */
200 while (((status
= pic32mx_get_flash_status(bank
)) & NVMCON_NVMWR
) && (timeout
-- > 0)) {
201 LOG_DEBUG("status: 0x%" PRIx32
, status
);
205 LOG_DEBUG("timeout: status: 0x%" PRIx32
, status
);
210 static int pic32mx_nvm_exec(struct flash_bank
*bank
, uint32_t op
, uint32_t timeout
)
212 struct target
*target
= bank
->target
;
215 target_write_u32(target
, PIC32MX_NVMCON
, NVMCON_NVMWREN
| op
);
217 /* unlock flash registers */
218 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY1
);
219 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY2
);
221 /* start operation */
222 target_write_u32(target
, PIC32MX_NVMCONSET
, NVMCON_NVMWR
);
224 status
= pic32mx_wait_status_busy(bank
, timeout
);
226 /* lock flash registers */
227 target_write_u32(target
, PIC32MX_NVMCONCLR
, NVMCON_NVMWREN
);
232 static int pic32mx_protect_check(struct flash_bank
*bank
)
234 struct target
*target
= bank
->target
;
240 if (target
->state
!= TARGET_HALTED
) {
241 LOG_ERROR("Target not halted");
242 return ERROR_TARGET_NOT_HALTED
;
245 target_read_u32(target
, PIC32MX_DEVCFG0
, &devcfg0
);
247 if ((devcfg0
& (1 << 28)) == 0) /* code protect bit */
248 num_pages
= 0xffff; /* All pages protected */
249 else if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
250 if (devcfg0
& (1 << 24))
251 num_pages
= 0; /* All pages unprotected */
253 num_pages
= 0xffff; /* All pages protected */
254 } else /* pgm flash */
255 num_pages
= (~devcfg0
>> 12) & 0xff;
257 for (s
= 0; s
< bank
->num_sectors
&& s
< num_pages
; s
++)
258 bank
->sectors
[s
].is_protected
= 1;
259 for (; s
< bank
->num_sectors
; s
++)
260 bank
->sectors
[s
].is_protected
= 0;
265 static int pic32mx_erase(struct flash_bank
*bank
, int first
, int last
)
267 struct target
*target
= bank
->target
;
271 if (bank
->target
->state
!= TARGET_HALTED
) {
272 LOG_ERROR("Target not halted");
273 return ERROR_TARGET_NOT_HALTED
;
276 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))
277 && (Virt2Phys(bank
->base
) == PIC32MX_PHYS_PGM_FLASH
)) {
278 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
279 * we need to use the MTAP to perform a full erase */
280 LOG_DEBUG("Erasing entire program flash");
281 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PFM_ERASE
, 50);
282 if (status
& NVMCON_NVMERR
)
283 return ERROR_FLASH_OPERATION_FAILED
;
284 if (status
& NVMCON_LVDERR
)
285 return ERROR_FLASH_OPERATION_FAILED
;
289 for (i
= first
; i
<= last
; i
++) {
290 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(bank
->base
+ bank
->sectors
[i
].offset
));
292 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PAGE_ERASE
, 10);
294 if (status
& NVMCON_NVMERR
)
295 return ERROR_FLASH_OPERATION_FAILED
;
296 if (status
& NVMCON_LVDERR
)
297 return ERROR_FLASH_OPERATION_FAILED
;
298 bank
->sectors
[i
].is_erased
= 1;
304 static int pic32mx_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
306 struct target
*target
= bank
->target
;
308 if (target
->state
!= TARGET_HALTED
) {
309 LOG_ERROR("Target not halted");
310 return ERROR_TARGET_NOT_HALTED
;
316 /* see contib/loaders/flash/pic32mx.s for src */
318 static const uint32_t pic32mx_flash_write_code
[] = {
320 0x3C08AA99, /* lui $t0, 0xaa99 */
321 0x35086655, /* ori $t0, 0x6655 */
322 0x3C095566, /* lui $t1, 0x5566 */
323 0x352999AA, /* ori $t1, 0x99aa */
324 0x3C0ABF80, /* lui $t2, 0xbf80 */
325 0x354AF400, /* ori $t2, 0xf400 */
326 0x340B4003, /* ori $t3, $zero, 0x4003 */
327 0x340C8000, /* ori $t4, $zero, 0x8000 */
329 0x2CD30080, /* sltiu $s3, $a2, 128 */
330 0x16600008, /* bne $s3, $zero, write_word */
331 0x340D4000, /* ori $t5, $zero, 0x4000 */
332 0xAD450020, /* sw $a1, 32($t2) */
333 0xAD440040, /* sw $a0, 64($t2) */
334 0x04110016, /* bal progflash */
335 0x24840200, /* addiu $a0, $a0, 512 */
336 0x24A50200, /* addiu $a1, $a1, 512 */
337 0x1000FFF7, /* beq $zero, $zero, write_row */
338 0x24C6FF80, /* addiu $a2, $a2, -128 */
340 0x3C15A000, /* lui $s5, 0xa000 */
341 0x36B50000, /* ori $s5, $s5, 0x0 */
342 0x00952025, /* or $a0, $a0, $s5 */
343 0x10000008, /* beq $zero, $zero, next_word */
344 0x340B4001, /* ori $t3, $zero, 0x4001 */
346 0x8C940000, /* lw $s4, 0($a0) */
347 0xAD540030, /* sw $s4, 48($t2) */
348 0xAD450020, /* sw $a1, 32($t2) */
349 0x04110009, /* bal progflash */
350 0x24840004, /* addiu $a0, $a0, 4 */
351 0x24A50004, /* addiu $a1, $a1, 4 */
352 0x24C6FFFF, /* addiu $a2, $a2, -1 */
354 0x14C0FFF8, /* bne $a2, $zero, prog_word */
355 0x00000000, /* nop */
357 0x10000002, /* beq $zero, $zero, exit */
358 0x24040000, /* addiu $a0, $zero, 0 */
360 0x26240000, /* addiu $a0, $s1, 0 */
362 0x7000003F, /* sdbbp */
364 0xAD4B0000, /* sw $t3, 0($t2) */
365 0xAD480010, /* sw $t0, 16($t2) */
366 0xAD490010, /* sw $t1, 16($t2) */
367 0xAD4C0008, /* sw $t4, 8($t2) */
369 0x8D500000, /* lw $s0, 0($t2) */
370 0x020C8024, /* and $s0, $s0, $t4 */
371 0x1600FFFD, /* bne $s0, $zero, waitflash */
372 0x00000000, /* nop */
373 0x00000000, /* nop */
374 0x00000000, /* nop */
375 0x00000000, /* nop */
376 0x00000000, /* nop */
377 0x8D510000, /* lw $s1, 0($t2) */
378 0x30113000, /* andi $s1, $zero, 0x3000 */
379 0x1620FFEF, /* bne $s1, $zero, error */
380 0xAD4D0004, /* sw $t5, 4($t2) */
381 0x03E00008, /* jr $ra */
385 static int pic32mx_write_block(struct flash_bank
*bank
, uint8_t *buffer
,
386 uint32_t offset
, uint32_t count
)
388 struct target
*target
= bank
->target
;
389 uint32_t buffer_size
= 16384;
390 struct working_area
*source
;
391 uint32_t address
= bank
->base
+ offset
;
392 struct reg_param reg_params
[3];
393 int retval
= ERROR_OK
;
395 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
396 struct mips32_algorithm mips32_info
;
398 /* flash write code */
399 if (target_alloc_working_area(target
, sizeof(pic32mx_flash_write_code
),
400 &pic32mx_info
->write_algorithm
) != ERROR_OK
) {
401 LOG_WARNING("no working area available, can't do block memory writes");
402 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
405 retval
= target_write_buffer(target
, pic32mx_info
->write_algorithm
->address
,
406 sizeof(pic32mx_flash_write_code
), (uint8_t *)pic32mx_flash_write_code
);
407 if (retval
!= ERROR_OK
)
411 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
413 if (buffer_size
<= 256) {
414 /* if we already allocated the writing code, but failed to get a
415 * buffer, free the algorithm */
416 if (pic32mx_info
->write_algorithm
)
417 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
419 LOG_WARNING("no large enough working area available, can't do block memory writes");
420 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
424 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
425 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
427 init_reg_param(®_params
[0], "a0", 32, PARAM_IN_OUT
);
428 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
429 init_reg_param(®_params
[2], "a2", 32, PARAM_OUT
);
433 uint32_t thisrun_count
= (count
> (buffer_size
/ 4)) ?
434 (buffer_size
/ 4) : count
;
436 retval
= target_write_buffer(target
, source
->address
,
437 thisrun_count
* 4, buffer
);
438 if (retval
!= ERROR_OK
)
441 buf_set_u32(reg_params
[0].value
, 0, 32, Virt2Phys(source
->address
));
442 buf_set_u32(reg_params
[1].value
, 0, 32, Virt2Phys(address
));
443 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
445 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
446 pic32mx_info
->write_algorithm
->address
,
447 0, 10000, &mips32_info
);
448 if (retval
!= ERROR_OK
) {
449 LOG_ERROR("error executing pic32mx flash write algorithm");
450 retval
= ERROR_FLASH_OPERATION_FAILED
;
454 status
= buf_get_u32(reg_params
[0].value
, 0, 32);
456 if (status
& NVMCON_NVMERR
) {
457 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
458 retval
= ERROR_FLASH_OPERATION_FAILED
;
462 if (status
& NVMCON_LVDERR
) {
463 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
464 retval
= ERROR_FLASH_OPERATION_FAILED
;
468 buffer
+= thisrun_count
* 4;
469 address
+= thisrun_count
* 4;
470 count
-= thisrun_count
;
473 target_free_working_area(target
, source
);
474 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
476 destroy_reg_param(®_params
[0]);
477 destroy_reg_param(®_params
[1]);
478 destroy_reg_param(®_params
[2]);
483 static int pic32mx_write_word(struct flash_bank
*bank
, uint32_t address
, uint32_t word
)
485 struct target
*target
= bank
->target
;
487 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(address
));
488 target_write_u32(target
, PIC32MX_NVMDATA
, word
);
490 return pic32mx_nvm_exec(bank
, NVMCON_OP_WORD_PROG
, 5);
493 static int pic32mx_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
495 uint32_t words_remaining
= (count
/ 4);
496 uint32_t bytes_remaining
= (count
& 0x00000003);
497 uint32_t address
= bank
->base
+ offset
;
498 uint32_t bytes_written
= 0;
502 if (bank
->target
->state
!= TARGET_HALTED
) {
503 LOG_ERROR("Target not halted");
504 return ERROR_TARGET_NOT_HALTED
;
507 LOG_DEBUG("writing to flash at address 0x%08" PRIx32
" at offset 0x%8.8" PRIx32
508 " count: 0x%8.8" PRIx32
"", bank
->base
, offset
, count
);
511 LOG_WARNING("offset 0x%" PRIx32
"breaks required 4-byte alignment", offset
);
512 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
515 /* multiple words (4-byte) to be programmed? */
516 if (words_remaining
> 0) {
517 /* try using a block write */
518 retval
= pic32mx_write_block(bank
, buffer
, offset
, words_remaining
);
519 if (retval
!= ERROR_OK
) {
520 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
521 /* if block write failed (no sufficient working area),
522 * we use normal (slow) single dword accesses */
523 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
524 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
525 LOG_ERROR("flash writing failed");
529 buffer
+= words_remaining
* 4;
530 address
+= words_remaining
* 4;
535 while (words_remaining
> 0) {
537 memcpy(&value
, buffer
+ bytes_written
, sizeof(uint32_t));
539 status
= pic32mx_write_word(bank
, address
, value
);
541 if (status
& NVMCON_NVMERR
) {
542 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
543 return ERROR_FLASH_OPERATION_FAILED
;
546 if (status
& NVMCON_LVDERR
) {
547 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
548 return ERROR_FLASH_OPERATION_FAILED
;
556 if (bytes_remaining
) {
557 uint32_t value
= 0xffffffff;
558 memcpy(&value
, buffer
+ bytes_written
, bytes_remaining
);
560 status
= pic32mx_write_word(bank
, address
, value
);
562 if (status
& NVMCON_NVMERR
) {
563 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
564 return ERROR_FLASH_OPERATION_FAILED
;
567 if (status
& NVMCON_LVDERR
) {
568 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
569 return ERROR_FLASH_OPERATION_FAILED
;
576 static int pic32mx_probe(struct flash_bank
*bank
)
578 struct target
*target
= bank
->target
;
579 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
580 struct mips32_common
*mips32
= target
->arch_info
;
581 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
583 uint32_t num_pages
= 0;
587 pic32mx_info
->probed
= 0;
589 device_id
= ejtag_info
->idcode
;
590 LOG_INFO("device id = 0x%08" PRIx32
" (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
592 (unsigned)((device_id
>> 1) & 0x7ff),
593 (unsigned)((device_id
>> 12) & 0xffff),
594 (unsigned)((device_id
>> 28) & 0xf));
596 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
597 LOG_WARNING("Cannot identify target as a PIC32MX family.");
598 return ERROR_FLASH_OPERATION_FAILED
;
603 if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
604 /* 0x1FC00000: Boot flash size */
606 /* for some reason this register returns 8k for the boot bank size
607 * this does not match the docs, so for now set the boot bank at a
609 if (target_read_u32(target
, PIC32MX_BMXBOOTSZ
, &num_pages
) != ERROR_OK
) {
610 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
611 num_pages
= (12 * 1024);
614 /* fixed 12k boot bank - see comments above */
615 num_pages
= (12 * 1024);
618 /* read the flash size from the device */
619 if (target_read_u32(target
, PIC32MX_BMXPFMSZ
, &num_pages
) != ERROR_OK
) {
620 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
621 num_pages
= (512 * 1024);
625 LOG_INFO("flash size = %" PRId32
"kbytes", num_pages
/ 1024);
629 bank
->sectors
= NULL
;
632 /* calculate numbers of pages */
633 num_pages
/= page_size
;
634 bank
->size
= (num_pages
* page_size
);
635 bank
->num_sectors
= num_pages
;
636 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
638 for (i
= 0; i
< (int)num_pages
; i
++) {
639 bank
->sectors
[i
].offset
= i
* page_size
;
640 bank
->sectors
[i
].size
= page_size
;
641 bank
->sectors
[i
].is_erased
= -1;
642 bank
->sectors
[i
].is_protected
= 1;
645 pic32mx_info
->probed
= 1;
650 static int pic32mx_auto_probe(struct flash_bank
*bank
)
652 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
653 if (pic32mx_info
->probed
)
655 return pic32mx_probe(bank
);
658 static int pic32mx_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
660 struct target
*target
= bank
->target
;
661 struct mips32_common
*mips32
= target
->arch_info
;
662 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
666 device_id
= ejtag_info
->idcode
;
668 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
669 snprintf(buf
, buf_size
,
670 "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
671 (unsigned)((device_id
>> 1) & 0x7ff),
673 return ERROR_FLASH_OPERATION_FAILED
;
676 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++) {
677 if (pic32mx_devs
[i
].devid
== (device_id
& 0x0fffffff)) {
678 printed
= snprintf(buf
, buf_size
, "PIC32MX%s", pic32mx_devs
[i
].name
);
683 if (pic32mx_devs
[i
].name
== NULL
)
684 printed
= snprintf(buf
, buf_size
, "Unknown");
688 snprintf(buf
, buf_size
, " Ver: 0x%02x",
689 (unsigned)((device_id
>> 28) & 0xf));
694 COMMAND_HANDLER(pic32mx_handle_pgm_word_command
)
696 uint32_t address
, value
;
700 return ERROR_COMMAND_SYNTAX_ERROR
;
702 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
703 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
705 struct flash_bank
*bank
;
706 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 2, &bank
);
707 if (ERROR_OK
!= retval
)
710 if (address
< bank
->base
|| address
>= (bank
->base
+ bank
->size
)) {
711 command_print(CMD_CTX
, "flash address '%s' is out of bounds", CMD_ARGV
[0]);
716 status
= pic32mx_write_word(bank
, address
, value
);
717 if (status
& NVMCON_NVMERR
)
718 res
= ERROR_FLASH_OPERATION_FAILED
;
719 if (status
& NVMCON_LVDERR
)
720 res
= ERROR_FLASH_OPERATION_FAILED
;
723 command_print(CMD_CTX
, "pic32mx pgm word complete");
725 command_print(CMD_CTX
, "pic32mx pgm word failed (status = 0x%x)", status
);
730 COMMAND_HANDLER(pic32mx_handle_unlock_command
)
733 struct target
*target
= NULL
;
734 struct mips_m4k_common
*mips_m4k
;
735 struct mips_ejtag
*ejtag_info
;
739 command_print(CMD_CTX
, "pic32mx unlock <bank>");
740 return ERROR_COMMAND_SYNTAX_ERROR
;
743 struct flash_bank
*bank
;
744 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
745 if (ERROR_OK
!= retval
)
748 target
= bank
->target
;
749 mips_m4k
= target_to_m4k(target
);
750 ejtag_info
= &mips_m4k
->mips32
.ejtag_info
;
752 /* we have to use the MTAP to perform a full erase */
753 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_MTAP
);
754 mips_ejtag_set_instr(ejtag_info
, MTAP_COMMAND
);
756 /* first check status of device */
757 mchip_cmd
= MCHP_STATUS
;
758 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
759 if (mchip_cmd
& (1 << 7)) {
760 /* device is not locked */
761 command_print(CMD_CTX
, "pic32mx is already unlocked, erasing anyway");
764 /* unlock/erase device */
765 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ASERT_RST
);
767 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ERASE
);
770 mchip_cmd
= MCHP_STATUS
;
771 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
772 if (timeout
-- == 0) {
773 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32
"", mchip_cmd
);
777 } while ((mchip_cmd
& (1 << 2)) || (!(mchip_cmd
& (1 << 3))));
779 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_DE_ASSERT_RST
);
781 /* select ejtag tap */
782 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_ETAP
);
784 command_print(CMD_CTX
, "pic32mx unlocked.\n"
785 "INFO: a reset or power cycle is required "
786 "for the new settings to take effect.");
791 static const struct command_registration pic32mx_exec_command_handlers
[] = {
794 .usage
= "<addr> <value> <bank>",
795 .handler
= pic32mx_handle_pgm_word_command
,
796 .mode
= COMMAND_EXEC
,
797 .help
= "program a word",
801 .handler
= pic32mx_handle_unlock_command
,
802 .mode
= COMMAND_EXEC
,
803 .usage
= "[bank_id]",
804 .help
= "Unlock/Erase entire device.",
806 COMMAND_REGISTRATION_DONE
809 static const struct command_registration pic32mx_command_handlers
[] = {
813 .help
= "pic32mx flash command group",
815 .chain
= pic32mx_exec_command_handlers
,
817 COMMAND_REGISTRATION_DONE
820 struct flash_driver pic32mx_flash
= {
822 .commands
= pic32mx_command_handlers
,
823 .flash_bank_command
= pic32mx_flash_bank_command
,
824 .erase
= pic32mx_erase
,
825 .protect
= pic32mx_protect
,
826 .write
= pic32mx_write
,
827 .read
= default_flash_read
,
828 .probe
= pic32mx_probe
,
829 .auto_probe
= pic32mx_auto_probe
,
830 .erase_check
= default_flash_mem_blank_check
,
831 .protect_check
= pic32mx_protect_check
,
832 .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)