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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
25 ***************************************************************************/
31 #include <jtag/jtag.h>
33 #include <target/algorithm.h>
34 #include <target/mips32.h>
35 #include <target/mips_m4k.h>
37 #define PIC32MX_MANUF_ID 0x029
39 /* pic32mx memory locations */
41 #define PIC32MX_PHYS_RAM 0x00000000
42 #define PIC32MX_PHYS_PGM_FLASH 0x1D000000
43 #define PIC32MX_PHYS_PERIPHERALS 0x1F800000
44 #define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000
47 * Translate Virtual and Physical addresses.
48 * Note: These macros only work for KSEG0/KSEG1 addresses.
51 #define Virt2Phys(v) ((v) & 0x1FFFFFFF)
53 /* pic32mx configuration register locations */
55 #define PIC32MX_DEVCFG0_1_2 0xBFC00BFC
56 #define PIC32MX_DEVCFG0 0xBFC02FFC
57 #define PIC32MX_DEVCFG1 0xBFC02FF8
58 #define PIC32MX_DEVCFG2 0xBFC02FF4
59 #define PIC32MX_DEVCFG3 0xBFC02FF0
60 #define PIC32MX_DEVID 0xBF80F220
62 #define PIC32MX_BMXPFMSZ 0xBF882060
63 #define PIC32MX_BMXBOOTSZ 0xBF882070
64 #define PIC32MX_BMXDRMSZ 0xBF882040
66 /* pic32mx flash controller register locations */
68 #define PIC32MX_NVMCON 0xBF80F400
69 #define PIC32MX_NVMCONCLR 0xBF80F404
70 #define PIC32MX_NVMCONSET 0xBF80F408
71 #define PIC32MX_NVMCONINV 0xBF80F40C
72 #define NVMCON_NVMWR (1 << 15)
73 #define NVMCON_NVMWREN (1 << 14)
74 #define NVMCON_NVMERR (1 << 13)
75 #define NVMCON_LVDERR (1 << 12)
76 #define NVMCON_LVDSTAT (1 << 11)
77 #define NVMCON_OP_PFM_ERASE 0x5
78 #define NVMCON_OP_PAGE_ERASE 0x4
79 #define NVMCON_OP_ROW_PROG 0x3
80 #define NVMCON_OP_WORD_PROG 0x1
81 #define NVMCON_OP_NOP 0x0
83 #define PIC32MX_NVMKEY 0xBF80F410
84 #define PIC32MX_NVMADDR 0xBF80F420
85 #define PIC32MX_NVMADDRCLR 0xBF80F424
86 #define PIC32MX_NVMADDRSET 0xBF80F428
87 #define PIC32MX_NVMADDRINV 0xBF80F42C
88 #define PIC32MX_NVMDATA 0xBF80F430
89 #define PIC32MX_NVMSRCADDR 0xBF80F440
91 /* flash unlock keys */
93 #define NVMKEY1 0xAA996655
94 #define NVMKEY2 0x556699AA
96 #define MX_1_2 1 /* PIC32mx1xx/2xx */
98 struct pic32mx_flash_bank
{
100 int dev_type
; /* Default 0. 1 for Pic32MX1XX/2XX variant */
104 * DEVID values as per PIC32MX Flash Programming Specification Rev J
107 static const struct pic32mx_devs_s
{
111 {0x04A07053, "110F016B"},
112 {0x04A09053, "110F016C"},
113 {0x04A0B053, "110F016D"},
114 {0x04A06053, "120F032B"},
115 {0x04A08053, "120F032C"},
116 {0x04A0A053, "120F032D"},
117 {0x04D07053, "130F064B"},
118 {0x04D09053, "130F064C"},
119 {0x04D0B053, "130F064D"},
120 {0x04D06053, "150F128B"},
121 {0x04D08053, "150F128C"},
122 {0x04D0A053, "150F128D"},
123 {0x04A01053, "210F016B"},
124 {0x04A03053, "210F016C"},
125 {0x04A05053, "210F016D"},
126 {0x04A00053, "220F032B"},
127 {0x04A02053, "220F032C"},
128 {0x04A04053, "220F032D"},
129 {0x04D01053, "230F064B"},
130 {0x04D03053, "230F064C"},
131 {0x04D05053, "230F064D"},
132 {0x04D00053, "250F128B"},
133 {0x04D02053, "250F128C"},
134 {0x04D04053, "250F128D"},
135 {0x00938053, "360F512L"},
136 {0x00934053, "360F256L"},
137 {0x0092D053, "340F128L"},
138 {0x0092A053, "320F128L"},
139 {0x00916053, "340F512H"},
140 {0x00912053, "340F256H"},
141 {0x0090D053, "340F128H"},
142 {0x0090A053, "320F128H"},
143 {0x00906053, "320F064H"},
144 {0x00902053, "320F032H"},
145 {0x00978053, "460F512L"},
146 {0x00974053, "460F256L"},
147 {0x0096D053, "440F128L"},
148 {0x00952053, "440F256H"},
149 {0x00956053, "440F512H"},
150 {0x0094D053, "440F128H"},
151 {0x00942053, "420F032H"},
152 {0x04307053, "795F512L"},
153 {0x0430E053, "795F512H"},
154 {0x04306053, "775F512L"},
155 {0x0430D053, "775F512H"},
156 {0x04312053, "775F256L"},
157 {0x04303053, "775F256H"},
158 {0x04417053, "764F128L"},
159 {0x0440B053, "764F128H"},
160 {0x04341053, "695F512L"},
161 {0x04325053, "695F512H"},
162 {0x04311053, "675F512L"},
163 {0x0430C053, "675F512H"},
164 {0x04305053, "675F256L"},
165 {0x0430B053, "675F256H"},
166 {0x04413053, "664F128L"},
167 {0x04407053, "664F128H"},
168 {0x04411053, "664F064L"},
169 {0x04405053, "664F064H"},
170 {0x0430F053, "575F512L"},
171 {0x04309053, "575F512H"},
172 {0x04333053, "575F256L"},
173 {0x04317053, "575F256H"},
174 {0x0440F053, "564F128L"},
175 {0x04403053, "564F128H"},
176 {0x0440D053, "564F064L"},
177 {0x04401053, "564F064H"},
178 {0x04400053, "534F064H"},
179 {0x0440C053, "534F064L"},
183 /* flash bank pic32mx <base> <size> 0 0 <target#>
185 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command
)
187 struct pic32mx_flash_bank
*pic32mx_info
;
190 return ERROR_COMMAND_SYNTAX_ERROR
;
192 pic32mx_info
= malloc(sizeof(struct pic32mx_flash_bank
));
193 bank
->driver_priv
= pic32mx_info
;
195 pic32mx_info
->probed
= 0;
196 pic32mx_info
->dev_type
= 0;
201 static uint32_t pic32mx_get_flash_status(struct flash_bank
*bank
)
203 struct target
*target
= bank
->target
;
206 target_read_u32(target
, PIC32MX_NVMCON
, &status
);
211 static uint32_t pic32mx_wait_status_busy(struct flash_bank
*bank
, int timeout
)
215 /* wait for busy to clear */
216 while (((status
= pic32mx_get_flash_status(bank
)) & NVMCON_NVMWR
) && (timeout
-- > 0)) {
217 LOG_DEBUG("status: 0x%" PRIx32
, status
);
221 LOG_DEBUG("timeout: status: 0x%" PRIx32
, status
);
226 static int pic32mx_nvm_exec(struct flash_bank
*bank
, uint32_t op
, uint32_t timeout
)
228 struct target
*target
= bank
->target
;
231 target_write_u32(target
, PIC32MX_NVMCON
, NVMCON_NVMWREN
| op
);
233 /* unlock flash registers */
234 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY1
);
235 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY2
);
237 /* start operation */
238 target_write_u32(target
, PIC32MX_NVMCONSET
, NVMCON_NVMWR
);
240 status
= pic32mx_wait_status_busy(bank
, timeout
);
242 /* lock flash registers */
243 target_write_u32(target
, PIC32MX_NVMCONCLR
, NVMCON_NVMWREN
);
248 static int pic32mx_protect_check(struct flash_bank
*bank
)
250 struct target
*target
= bank
->target
;
251 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
253 uint32_t config0_address
;
258 if (target
->state
!= TARGET_HALTED
) {
259 LOG_ERROR("Target not halted");
260 return ERROR_TARGET_NOT_HALTED
;
263 if (pic32mx_info
->dev_type
== MX_1_2
)
264 config0_address
= PIC32MX_DEVCFG0_1_2
;
266 config0_address
= PIC32MX_DEVCFG0
;
268 target_read_u32(target
, config0_address
, &devcfg0
);
270 if ((devcfg0
& (1 << 28)) == 0) /* code protect bit */
271 num_pages
= 0xffff; /* All pages protected */
272 else if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
273 if (devcfg0
& (1 << 24))
274 num_pages
= 0; /* All pages unprotected */
276 num_pages
= 0xffff; /* All pages protected */
279 if (pic32mx_info
->dev_type
== MX_1_2
)
280 num_pages
= (~devcfg0
>> 10) & 0x3f;
282 num_pages
= (~devcfg0
>> 12) & 0xff;
285 for (s
= 0; s
< bank
->num_sectors
&& s
< num_pages
; s
++)
286 bank
->sectors
[s
].is_protected
= 1;
287 for (; s
< bank
->num_sectors
; s
++)
288 bank
->sectors
[s
].is_protected
= 0;
293 static int pic32mx_erase(struct flash_bank
*bank
, int first
, int last
)
295 struct target
*target
= bank
->target
;
299 if (bank
->target
->state
!= TARGET_HALTED
) {
300 LOG_ERROR("Target not halted");
301 return ERROR_TARGET_NOT_HALTED
;
304 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))
305 && (Virt2Phys(bank
->base
) == PIC32MX_PHYS_PGM_FLASH
)) {
306 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
307 * we need to use the MTAP to perform a full erase */
308 LOG_DEBUG("Erasing entire program flash");
309 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PFM_ERASE
, 50);
310 if (status
& NVMCON_NVMERR
)
311 return ERROR_FLASH_OPERATION_FAILED
;
312 if (status
& NVMCON_LVDERR
)
313 return ERROR_FLASH_OPERATION_FAILED
;
317 for (i
= first
; i
<= last
; i
++) {
318 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(bank
->base
+ bank
->sectors
[i
].offset
));
320 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PAGE_ERASE
, 10);
322 if (status
& NVMCON_NVMERR
)
323 return ERROR_FLASH_OPERATION_FAILED
;
324 if (status
& NVMCON_LVDERR
)
325 return ERROR_FLASH_OPERATION_FAILED
;
326 bank
->sectors
[i
].is_erased
= 1;
332 static int pic32mx_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
334 struct target
*target
= bank
->target
;
336 if (target
->state
!= TARGET_HALTED
) {
337 LOG_ERROR("Target not halted");
338 return ERROR_TARGET_NOT_HALTED
;
344 /* see contib/loaders/flash/pic32mx.s for src */
346 static uint32_t pic32mx_flash_write_code
[] = {
348 0x3C08AA99, /* lui $t0, 0xaa99 */
349 0x35086655, /* ori $t0, 0x6655 */
350 0x3C095566, /* lui $t1, 0x5566 */
351 0x352999AA, /* ori $t1, 0x99aa */
352 0x3C0ABF80, /* lui $t2, 0xbf80 */
353 0x354AF400, /* ori $t2, 0xf400 */
354 0x340B4003, /* ori $t3, $zero, 0x4003 */
355 0x340C8000, /* ori $t4, $zero, 0x8000 */
357 0x2CD30080, /* sltiu $s3, $a2, 128 */
358 0x16600008, /* bne $s3, $zero, write_word */
359 0x340D4000, /* ori $t5, $zero, 0x4000 */
360 0xAD450020, /* sw $a1, 32($t2) */
361 0xAD440040, /* sw $a0, 64($t2) */
362 0x04110016, /* bal progflash */
363 0x24840200, /* addiu $a0, $a0, 512 */
364 0x24A50200, /* addiu $a1, $a1, 512 */
365 0x1000FFF7, /* beq $zero, $zero, write_row */
366 0x24C6FF80, /* addiu $a2, $a2, -128 */
368 0x3C15A000, /* lui $s5, 0xa000 */
369 0x36B50000, /* ori $s5, $s5, 0x0 */
370 0x00952025, /* or $a0, $a0, $s5 */
371 0x10000008, /* beq $zero, $zero, next_word */
372 0x340B4001, /* ori $t3, $zero, 0x4001 */
374 0x8C940000, /* lw $s4, 0($a0) */
375 0xAD540030, /* sw $s4, 48($t2) */
376 0xAD450020, /* sw $a1, 32($t2) */
377 0x04110009, /* bal progflash */
378 0x24840004, /* addiu $a0, $a0, 4 */
379 0x24A50004, /* addiu $a1, $a1, 4 */
380 0x24C6FFFF, /* addiu $a2, $a2, -1 */
382 0x14C0FFF8, /* bne $a2, $zero, prog_word */
383 0x00000000, /* nop */
385 0x10000002, /* beq $zero, $zero, exit */
386 0x24040000, /* addiu $a0, $zero, 0 */
388 0x26240000, /* addiu $a0, $s1, 0 */
390 0x7000003F, /* sdbbp */
392 0xAD4B0000, /* sw $t3, 0($t2) */
393 0xAD480010, /* sw $t0, 16($t2) */
394 0xAD490010, /* sw $t1, 16($t2) */
395 0xAD4C0008, /* sw $t4, 8($t2) */
397 0x8D500000, /* lw $s0, 0($t2) */
398 0x020C8024, /* and $s0, $s0, $t4 */
399 0x1600FFFD, /* bne $s0, $zero, waitflash */
400 0x00000000, /* nop */
401 0x00000000, /* nop */
402 0x00000000, /* nop */
403 0x00000000, /* nop */
404 0x00000000, /* nop */
405 0x8D510000, /* lw $s1, 0($t2) */
406 0x30113000, /* andi $s1, $zero, 0x3000 */
407 0x1620FFEF, /* bne $s1, $zero, error */
408 0xAD4D0004, /* sw $t5, 4($t2) */
409 0x03E00008, /* jr $ra */
413 static int pic32mx_write_block(struct flash_bank
*bank
, uint8_t *buffer
,
414 uint32_t offset
, uint32_t count
)
416 struct target
*target
= bank
->target
;
417 uint32_t buffer_size
= 16384;
418 struct working_area
*write_algorithm
;
419 struct working_area
*source
;
420 uint32_t address
= bank
->base
+ offset
;
421 struct reg_param reg_params
[3];
423 int retval
= ERROR_OK
;
425 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
426 struct mips32_algorithm mips32_info
;
428 /* flash write code */
429 if (target_alloc_working_area(target
, sizeof(pic32mx_flash_write_code
),
430 &write_algorithm
) != ERROR_OK
) {
431 LOG_WARNING("no working area available, can't do block memory writes");
432 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
435 /* Change values for counters and row size, depending on variant */
436 if (pic32mx_info
->dev_type
== MX_1_2
) {
438 pic32mx_flash_write_code
[8] = 0x2CD30020;
439 pic32mx_flash_write_code
[14] = 0x24840080;
440 pic32mx_flash_write_code
[15] = 0x24A50080;
441 pic32mx_flash_write_code
[17] = 0x24C6FFE0;
445 pic32mx_flash_write_code
[8] = 0x2CD30080;
446 pic32mx_flash_write_code
[14] = 0x24840200;
447 pic32mx_flash_write_code
[15] = 0x24A50200;
448 pic32mx_flash_write_code
[17] = 0x24C6FF80;
452 retval
= target_write_buffer(target
, write_algorithm
->address
,
453 sizeof(pic32mx_flash_write_code
), (uint8_t *)pic32mx_flash_write_code
);
454 if (retval
!= ERROR_OK
)
458 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
460 if (buffer_size
<= 256) {
461 /* we already allocated the writing code, but failed to get a
462 * buffer, free the algorithm */
463 target_free_working_area(target
, write_algorithm
);
465 LOG_WARNING("no large enough working area available, can't do block memory writes");
466 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
470 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
471 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
473 init_reg_param(®_params
[0], "a0", 32, PARAM_IN_OUT
);
474 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
475 init_reg_param(®_params
[2], "a2", 32, PARAM_OUT
);
477 int row_offset
= offset
% row_size
;
478 uint8_t *new_buffer
= NULL
;
479 if (row_offset
&& (count
>= (row_size
/ 4))) {
480 new_buffer
= malloc(buffer_size
);
481 if (new_buffer
== NULL
) {
482 LOG_ERROR("Out of memory");
485 memset(new_buffer
, 0xff, row_offset
);
486 address
-= row_offset
;
492 uint32_t thisrun_count
;
495 thisrun_count
= (count
> ((buffer_size
- row_offset
) / 4)) ?
496 ((buffer_size
- row_offset
) / 4) : count
;
498 memcpy(new_buffer
+ row_offset
, buffer
, thisrun_count
* 4);
500 retval
= target_write_buffer(target
, source
->address
,
501 row_offset
+ thisrun_count
* 4, new_buffer
);
502 if (retval
!= ERROR_OK
)
505 thisrun_count
= (count
> (buffer_size
/ 4)) ?
506 (buffer_size
/ 4) : count
;
508 retval
= target_write_buffer(target
, source
->address
,
509 thisrun_count
* 4, buffer
);
510 if (retval
!= ERROR_OK
)
514 buf_set_u32(reg_params
[0].value
, 0, 32, Virt2Phys(source
->address
));
515 buf_set_u32(reg_params
[1].value
, 0, 32, Virt2Phys(address
));
516 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
+ row_offset
/ 4);
518 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
519 write_algorithm
->address
,
520 0, 10000, &mips32_info
);
521 if (retval
!= ERROR_OK
) {
522 LOG_ERROR("error executing pic32mx flash write algorithm");
523 retval
= ERROR_FLASH_OPERATION_FAILED
;
527 status
= buf_get_u32(reg_params
[0].value
, 0, 32);
529 if (status
& NVMCON_NVMERR
) {
530 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
531 retval
= ERROR_FLASH_OPERATION_FAILED
;
535 if (status
& NVMCON_LVDERR
) {
536 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
537 retval
= ERROR_FLASH_OPERATION_FAILED
;
541 buffer
+= thisrun_count
* 4;
542 address
+= thisrun_count
* 4;
543 count
-= thisrun_count
;
545 address
+= row_offset
;
550 target_free_working_area(target
, source
);
551 target_free_working_area(target
, write_algorithm
);
553 destroy_reg_param(®_params
[0]);
554 destroy_reg_param(®_params
[1]);
555 destroy_reg_param(®_params
[2]);
557 if (new_buffer
!= NULL
)
562 static int pic32mx_write_word(struct flash_bank
*bank
, uint32_t address
, uint32_t word
)
564 struct target
*target
= bank
->target
;
566 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(address
));
567 target_write_u32(target
, PIC32MX_NVMDATA
, word
);
569 return pic32mx_nvm_exec(bank
, NVMCON_OP_WORD_PROG
, 5);
572 static int pic32mx_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
574 uint32_t words_remaining
= (count
/ 4);
575 uint32_t bytes_remaining
= (count
& 0x00000003);
576 uint32_t address
= bank
->base
+ offset
;
577 uint32_t bytes_written
= 0;
581 if (bank
->target
->state
!= TARGET_HALTED
) {
582 LOG_ERROR("Target not halted");
583 return ERROR_TARGET_NOT_HALTED
;
586 LOG_DEBUG("writing to flash at address 0x%08" PRIx32
" at offset 0x%8.8" PRIx32
587 " count: 0x%8.8" PRIx32
"", bank
->base
, offset
, count
);
590 LOG_WARNING("offset 0x%" PRIx32
"breaks required 4-byte alignment", offset
);
591 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
594 /* multiple words (4-byte) to be programmed? */
595 if (words_remaining
> 0) {
596 /* try using a block write */
597 retval
= pic32mx_write_block(bank
, buffer
, offset
, words_remaining
);
598 if (retval
!= ERROR_OK
) {
599 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
600 /* if block write failed (no sufficient working area),
601 * we use normal (slow) single dword accesses */
602 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
603 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
604 LOG_ERROR("flash writing failed");
608 buffer
+= words_remaining
* 4;
609 address
+= words_remaining
* 4;
614 while (words_remaining
> 0) {
616 memcpy(&value
, buffer
+ bytes_written
, sizeof(uint32_t));
618 status
= pic32mx_write_word(bank
, address
, value
);
620 if (status
& NVMCON_NVMERR
) {
621 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
622 return ERROR_FLASH_OPERATION_FAILED
;
625 if (status
& NVMCON_LVDERR
) {
626 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
627 return ERROR_FLASH_OPERATION_FAILED
;
635 if (bytes_remaining
) {
636 uint32_t value
= 0xffffffff;
637 memcpy(&value
, buffer
+ bytes_written
, bytes_remaining
);
639 status
= pic32mx_write_word(bank
, address
, value
);
641 if (status
& NVMCON_NVMERR
) {
642 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
643 return ERROR_FLASH_OPERATION_FAILED
;
646 if (status
& NVMCON_LVDERR
) {
647 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
648 return ERROR_FLASH_OPERATION_FAILED
;
655 static int pic32mx_probe(struct flash_bank
*bank
)
657 struct target
*target
= bank
->target
;
658 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
659 struct mips32_common
*mips32
= target
->arch_info
;
660 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
662 uint32_t num_pages
= 0;
666 pic32mx_info
->probed
= 0;
668 device_id
= ejtag_info
->idcode
;
669 LOG_INFO("device id = 0x%08" PRIx32
" (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
671 (unsigned)((device_id
>> 1) & 0x7ff),
672 (unsigned)((device_id
>> 12) & 0xffff),
673 (unsigned)((device_id
>> 28) & 0xf));
675 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
676 LOG_WARNING("Cannot identify target as a PIC32MX family.");
677 return ERROR_FLASH_OPERATION_FAILED
;
680 /* Check for PIC32mx1xx/2xx */
681 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++) {
682 if (pic32mx_devs
[i
].devid
== (device_id
& 0x0fffffff)) {
683 if ((*(pic32mx_devs
[i
].name
) == '1') || (*(pic32mx_devs
[i
].name
) == '2'))
684 pic32mx_info
->dev_type
= MX_1_2
;
689 if (pic32mx_info
->dev_type
== MX_1_2
)
695 if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
696 /* 0x1FC00000: Boot flash size */
698 /* for some reason this register returns 8k for the boot bank size
699 * this does not match the docs, so for now set the boot bank at a
701 if (target_read_u32(target
, PIC32MX_BMXBOOTSZ
, &num_pages
) != ERROR_OK
) {
702 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
703 num_pages
= (12 * 1024);
706 /* fixed 12k boot bank - see comments above */
707 if (pic32mx_info
->dev_type
== MX_1_2
)
708 num_pages
= (3 * 1024);
710 num_pages
= (12 * 1024);
713 /* read the flash size from the device */
714 if (target_read_u32(target
, PIC32MX_BMXPFMSZ
, &num_pages
) != ERROR_OK
) {
715 if (pic32mx_info
->dev_type
== MX_1_2
) {
716 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash");
717 num_pages
= (32 * 1024);
719 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
720 num_pages
= (512 * 1024);
725 LOG_INFO("flash size = %" PRId32
"kbytes", num_pages
/ 1024);
729 bank
->sectors
= NULL
;
732 /* calculate numbers of pages */
733 num_pages
/= page_size
;
734 bank
->size
= (num_pages
* page_size
);
735 bank
->num_sectors
= num_pages
;
736 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
738 for (i
= 0; i
< (int)num_pages
; i
++) {
739 bank
->sectors
[i
].offset
= i
* page_size
;
740 bank
->sectors
[i
].size
= page_size
;
741 bank
->sectors
[i
].is_erased
= -1;
742 bank
->sectors
[i
].is_protected
= 1;
745 pic32mx_info
->probed
= 1;
750 static int pic32mx_auto_probe(struct flash_bank
*bank
)
752 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
753 if (pic32mx_info
->probed
)
755 return pic32mx_probe(bank
);
758 static int pic32mx_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
760 struct target
*target
= bank
->target
;
761 struct mips32_common
*mips32
= target
->arch_info
;
762 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
766 device_id
= ejtag_info
->idcode
;
768 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
769 snprintf(buf
, buf_size
,
770 "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
771 (unsigned)((device_id
>> 1) & 0x7ff),
773 return ERROR_FLASH_OPERATION_FAILED
;
776 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++) {
777 if (pic32mx_devs
[i
].devid
== (device_id
& 0x0fffffff)) {
778 printed
= snprintf(buf
, buf_size
, "PIC32MX%s", pic32mx_devs
[i
].name
);
783 if (pic32mx_devs
[i
].name
== NULL
)
784 printed
= snprintf(buf
, buf_size
, "Unknown");
788 snprintf(buf
, buf_size
, " Ver: 0x%02x",
789 (unsigned)((device_id
>> 28) & 0xf));
794 COMMAND_HANDLER(pic32mx_handle_pgm_word_command
)
796 uint32_t address
, value
;
800 return ERROR_COMMAND_SYNTAX_ERROR
;
802 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
803 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
805 struct flash_bank
*bank
;
806 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 2, &bank
);
807 if (ERROR_OK
!= retval
)
810 if (address
< bank
->base
|| address
>= (bank
->base
+ bank
->size
)) {
811 command_print(CMD_CTX
, "flash address '%s' is out of bounds", CMD_ARGV
[0]);
816 status
= pic32mx_write_word(bank
, address
, value
);
817 if (status
& NVMCON_NVMERR
)
818 res
= ERROR_FLASH_OPERATION_FAILED
;
819 if (status
& NVMCON_LVDERR
)
820 res
= ERROR_FLASH_OPERATION_FAILED
;
823 command_print(CMD_CTX
, "pic32mx pgm word complete");
825 command_print(CMD_CTX
, "pic32mx pgm word failed (status = 0x%x)", status
);
830 COMMAND_HANDLER(pic32mx_handle_unlock_command
)
833 struct target
*target
= NULL
;
834 struct mips_m4k_common
*mips_m4k
;
835 struct mips_ejtag
*ejtag_info
;
839 command_print(CMD_CTX
, "pic32mx unlock <bank>");
840 return ERROR_COMMAND_SYNTAX_ERROR
;
843 struct flash_bank
*bank
;
844 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
845 if (ERROR_OK
!= retval
)
848 target
= bank
->target
;
849 mips_m4k
= target_to_m4k(target
);
850 ejtag_info
= &mips_m4k
->mips32
.ejtag_info
;
852 /* we have to use the MTAP to perform a full erase */
853 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_MTAP
);
854 mips_ejtag_set_instr(ejtag_info
, MTAP_COMMAND
);
856 /* first check status of device */
857 mchip_cmd
= MCHP_STATUS
;
858 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
859 if (mchip_cmd
& (1 << 7)) {
860 /* device is not locked */
861 command_print(CMD_CTX
, "pic32mx is already unlocked, erasing anyway");
864 /* unlock/erase device */
865 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ASERT_RST
);
868 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ERASE
);
871 mchip_cmd
= MCHP_STATUS
;
872 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
873 if (timeout
-- == 0) {
874 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32
"", mchip_cmd
);
878 } while ((mchip_cmd
& (1 << 2)) || (!(mchip_cmd
& (1 << 3))));
880 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_DE_ASSERT_RST
);
882 /* select ejtag tap */
883 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_ETAP
);
885 command_print(CMD_CTX
, "pic32mx unlocked.\n"
886 "INFO: a reset or power cycle is required "
887 "for the new settings to take effect.");
892 static const struct command_registration pic32mx_exec_command_handlers
[] = {
895 .usage
= "<addr> <value> <bank>",
896 .handler
= pic32mx_handle_pgm_word_command
,
897 .mode
= COMMAND_EXEC
,
898 .help
= "program a word",
902 .handler
= pic32mx_handle_unlock_command
,
903 .mode
= COMMAND_EXEC
,
904 .usage
= "[bank_id]",
905 .help
= "Unlock/Erase entire device.",
907 COMMAND_REGISTRATION_DONE
910 static const struct command_registration pic32mx_command_handlers
[] = {
914 .help
= "pic32mx flash command group",
916 .chain
= pic32mx_exec_command_handlers
,
918 COMMAND_REGISTRATION_DONE
921 struct flash_driver pic32mx_flash
= {
923 .commands
= pic32mx_command_handlers
,
924 .flash_bank_command
= pic32mx_flash_bank_command
,
925 .erase
= pic32mx_erase
,
926 .protect
= pic32mx_protect
,
927 .write
= pic32mx_write
,
928 .read
= default_flash_read
,
929 .probe
= pic32mx_probe
,
930 .auto_probe
= pic32mx_auto_probe
,
931 .erase_check
= default_flash_blank_check
,
932 .protect_check
= pic32mx_protect_check
,
933 .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)