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, see <http://www.gnu.org/licenses/>. *
23 ***************************************************************************/
29 #include <jtag/jtag.h>
31 #include <target/algorithm.h>
32 #include <target/mips32.h>
33 #include <target/mips_m4k.h>
35 #define PIC32MX_MANUF_ID 0x029
37 /* pic32mx memory locations */
39 #define PIC32MX_PHYS_RAM 0x00000000
40 #define PIC32MX_PHYS_PGM_FLASH 0x1D000000
41 #define PIC32MX_PHYS_PERIPHERALS 0x1F800000
42 #define PIC32MX_PHYS_BOOT_FLASH 0x1FC00000
45 * Translate Virtual and Physical addresses.
46 * Note: These macros only work for KSEG0/KSEG1 addresses.
49 #define Virt2Phys(v) ((v) & 0x1FFFFFFF)
51 /* pic32mx configuration register locations */
53 #define PIC32MX_DEVCFG0_1xx_2xx 0xBFC00BFC
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 #define MX_1xx_2xx 1 /* PIC32mx1xx/2xx */
95 #define MX_17x_27x 2 /* PIC32mx17x/27x */
97 struct pic32mx_flash_bank
{
99 int dev_type
; /* Default 0. 1 for Pic32MX1XX/2XX variant */
103 * DEVID values as per PIC32MX Flash Programming Specification Rev N
106 static const struct pic32mx_devs_s
{
110 {0x04A07053, "110F016B"},
111 {0x04A09053, "110F016C"},
112 {0x04A0B053, "110F016D"},
113 {0x04A06053, "120F032B"},
114 {0x04A08053, "120F032C"},
115 {0x04A0A053, "120F032D"},
116 {0x04D07053, "130F064B"},
117 {0x04D09053, "130F064C"},
118 {0x04D0B053, "130F064D"},
119 {0x04D06053, "150F128B"},
120 {0x04D08053, "150F128C"},
121 {0x04D0A053, "150F128D"},
122 {0x06610053, "170F256B"},
123 {0x0661A053, "170F256D"},
124 {0x04A01053, "210F016B"},
125 {0x04A03053, "210F016C"},
126 {0x04A05053, "210F016D"},
127 {0x04A00053, "220F032B"},
128 {0x04A02053, "220F032C"},
129 {0x04A04053, "220F032D"},
130 {0x04D01053, "230F064B"},
131 {0x04D03053, "230F064C"},
132 {0x04D05053, "230F064D"},
133 {0x04D00053, "250F128B"},
134 {0x04D02053, "250F128C"},
135 {0x04D04053, "250F128D"},
136 {0x06600053, "270F256B"},
137 {0x0660A053, "270F256D"},
138 {0x05600053, "330F064H"},
139 {0x05601053, "330F064L"},
140 {0x05602053, "430F064H"},
141 {0x05603053, "430F064L"},
142 {0x0570C053, "350F128H"},
143 {0x0570D053, "350F128L"},
144 {0x0570E053, "450F128H"},
145 {0x0570F053, "450F128L"},
146 {0x05704053, "350F256H"},
147 {0x05705053, "350F256L"},
148 {0x05706053, "450F256H"},
149 {0x05707053, "450F256L"},
150 {0x05808053, "370F512H"},
151 {0x05809053, "370F512L"},
152 {0x0580A053, "470F512H"},
153 {0x0580B053, "470F512L"},
154 {0x00938053, "360F512L"},
155 {0x00934053, "360F256L"},
156 {0x0092D053, "340F128L"},
157 {0x0092A053, "320F128L"},
158 {0x00916053, "340F512H"},
159 {0x00912053, "340F256H"},
160 {0x0090D053, "340F128H"},
161 {0x0090A053, "320F128H"},
162 {0x00906053, "320F064H"},
163 {0x00902053, "320F032H"},
164 {0x00978053, "460F512L"},
165 {0x00974053, "460F256L"},
166 {0x0096D053, "440F128L"},
167 {0x00952053, "440F256H"},
168 {0x00956053, "440F512H"},
169 {0x0094D053, "440F128H"},
170 {0x00942053, "420F032H"},
171 {0x04307053, "795F512L"},
172 {0x0430E053, "795F512H"},
173 {0x04306053, "775F512L"},
174 {0x0430D053, "775F512H"},
175 {0x04312053, "775F256L"},
176 {0x04303053, "775F256H"},
177 {0x04417053, "764F128L"},
178 {0x0440B053, "764F128H"},
179 {0x04341053, "695F512L"},
180 {0x04325053, "695F512H"},
181 {0x04311053, "675F512L"},
182 {0x0430C053, "675F512H"},
183 {0x04305053, "675F256L"},
184 {0x0430B053, "675F256H"},
185 {0x04413053, "664F128L"},
186 {0x04407053, "664F128H"},
187 {0x04411053, "664F064L"},
188 {0x04405053, "664F064H"},
189 {0x0430F053, "575F512L"},
190 {0x04309053, "575F512H"},
191 {0x04333053, "575F256L"},
192 {0x04317053, "575F256H"},
193 {0x0440F053, "564F128L"},
194 {0x04403053, "564F128H"},
195 {0x0440D053, "564F064L"},
196 {0x04401053, "564F064H"},
197 {0x04400053, "534F064H"},
198 {0x0440C053, "534F064L"},
202 /* flash bank pic32mx <base> <size> 0 0 <target#>
204 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command
)
206 struct pic32mx_flash_bank
*pic32mx_info
;
209 return ERROR_COMMAND_SYNTAX_ERROR
;
211 pic32mx_info
= malloc(sizeof(struct pic32mx_flash_bank
));
212 bank
->driver_priv
= pic32mx_info
;
214 pic32mx_info
->probed
= false;
215 pic32mx_info
->dev_type
= 0;
220 static uint32_t pic32mx_get_flash_status(struct flash_bank
*bank
)
222 struct target
*target
= bank
->target
;
225 target_read_u32(target
, PIC32MX_NVMCON
, &status
);
230 static uint32_t pic32mx_wait_status_busy(struct flash_bank
*bank
, int timeout
)
234 /* wait for busy to clear */
235 while (((status
= pic32mx_get_flash_status(bank
)) & NVMCON_NVMWR
) && (timeout
-- > 0)) {
236 LOG_DEBUG("status: 0x%" PRIx32
, status
);
240 LOG_DEBUG("timeout: status: 0x%" PRIx32
, status
);
245 static int pic32mx_nvm_exec(struct flash_bank
*bank
, uint32_t op
, uint32_t timeout
)
247 struct target
*target
= bank
->target
;
250 target_write_u32(target
, PIC32MX_NVMCON
, NVMCON_NVMWREN
| op
);
252 /* unlock flash registers */
253 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY1
);
254 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY2
);
256 /* start operation */
257 target_write_u32(target
, PIC32MX_NVMCONSET
, NVMCON_NVMWR
);
259 status
= pic32mx_wait_status_busy(bank
, timeout
);
261 /* lock flash registers */
262 target_write_u32(target
, PIC32MX_NVMCONCLR
, NVMCON_NVMWREN
);
267 static int pic32mx_protect_check(struct flash_bank
*bank
)
269 struct target
*target
= bank
->target
;
270 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
272 uint32_t config0_address
;
274 unsigned int s
, num_pages
;
276 if (target
->state
!= TARGET_HALTED
) {
277 LOG_ERROR("Target not halted");
278 return ERROR_TARGET_NOT_HALTED
;
281 switch (pic32mx_info
->dev_type
) {
284 config0_address
= PIC32MX_DEVCFG0_1xx_2xx
;
287 config0_address
= PIC32MX_DEVCFG0
;
291 target_read_u32(target
, config0_address
, &devcfg0
);
293 if ((devcfg0
& (1 << 28)) == 0) /* code protect bit */
294 num_pages
= 0xffff; /* All pages protected */
295 else if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
296 if (devcfg0
& (1 << 24))
297 num_pages
= 0; /* All pages unprotected */
299 num_pages
= 0xffff; /* All pages protected */
302 switch (pic32mx_info
->dev_type
) {
304 num_pages
= (~devcfg0
>> 10) & 0x7f;
307 num_pages
= (~devcfg0
>> 10) & 0x1ff;
310 num_pages
= (~devcfg0
>> 12) & 0xff;
315 for (s
= 0; s
< bank
->num_sectors
&& s
< num_pages
; s
++)
316 bank
->sectors
[s
].is_protected
= 1;
317 for (; s
< bank
->num_sectors
; s
++)
318 bank
->sectors
[s
].is_protected
= 0;
323 static int pic32mx_erase(struct flash_bank
*bank
, unsigned int first
,
326 struct target
*target
= bank
->target
;
329 if (bank
->target
->state
!= TARGET_HALTED
) {
330 LOG_ERROR("Target not halted");
331 return ERROR_TARGET_NOT_HALTED
;
334 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))
335 && (Virt2Phys(bank
->base
) == PIC32MX_PHYS_PGM_FLASH
)) {
336 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
337 * we need to use the MTAP to perform a full erase */
338 LOG_DEBUG("Erasing entire program flash");
339 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PFM_ERASE
, 50);
340 if (status
& NVMCON_NVMERR
)
341 return ERROR_FLASH_OPERATION_FAILED
;
342 if (status
& NVMCON_LVDERR
)
343 return ERROR_FLASH_OPERATION_FAILED
;
347 for (unsigned int i
= first
; i
<= last
; i
++) {
348 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(bank
->base
+ bank
->sectors
[i
].offset
));
350 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PAGE_ERASE
, 10);
352 if (status
& NVMCON_NVMERR
)
353 return ERROR_FLASH_OPERATION_FAILED
;
354 if (status
& NVMCON_LVDERR
)
355 return ERROR_FLASH_OPERATION_FAILED
;
356 bank
->sectors
[i
].is_erased
= 1;
362 static int pic32mx_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
365 struct target
*target
= bank
->target
;
367 if (target
->state
!= TARGET_HALTED
) {
368 LOG_ERROR("Target not halted");
369 return ERROR_TARGET_NOT_HALTED
;
375 /* see contrib/loaders/flash/pic32mx.s for src */
377 static uint32_t pic32mx_flash_write_code
[] = {
379 0x3C08AA99, /* lui $t0, 0xaa99 */
380 0x35086655, /* ori $t0, 0x6655 */
381 0x3C095566, /* lui $t1, 0x5566 */
382 0x352999AA, /* ori $t1, 0x99aa */
383 0x3C0ABF80, /* lui $t2, 0xbf80 */
384 0x354AF400, /* ori $t2, 0xf400 */
385 0x340B4003, /* ori $t3, $zero, 0x4003 */
386 0x340C8000, /* ori $t4, $zero, 0x8000 */
388 0x2CD30080, /* sltiu $s3, $a2, 128 */
389 0x16600008, /* bne $s3, $zero, write_word */
390 0x340D4000, /* ori $t5, $zero, 0x4000 */
391 0xAD450020, /* sw $a1, 32($t2) */
392 0xAD440040, /* sw $a0, 64($t2) */
393 0x04110016, /* bal progflash */
394 0x24840200, /* addiu $a0, $a0, 512 */
395 0x24A50200, /* addiu $a1, $a1, 512 */
396 0x1000FFF7, /* beq $zero, $zero, write_row */
397 0x24C6FF80, /* addiu $a2, $a2, -128 */
399 0x3C15A000, /* lui $s5, 0xa000 */
400 0x36B50000, /* ori $s5, $s5, 0x0 */
401 0x00952025, /* or $a0, $a0, $s5 */
402 0x10000008, /* beq $zero, $zero, next_word */
403 0x340B4001, /* ori $t3, $zero, 0x4001 */
405 0x8C940000, /* lw $s4, 0($a0) */
406 0xAD540030, /* sw $s4, 48($t2) */
407 0xAD450020, /* sw $a1, 32($t2) */
408 0x04110009, /* bal progflash */
409 0x24840004, /* addiu $a0, $a0, 4 */
410 0x24A50004, /* addiu $a1, $a1, 4 */
411 0x24C6FFFF, /* addiu $a2, $a2, -1 */
413 0x14C0FFF8, /* bne $a2, $zero, prog_word */
414 0x00000000, /* nop */
416 0x10000002, /* beq $zero, $zero, exit */
417 0x24040000, /* addiu $a0, $zero, 0 */
419 0x26240000, /* addiu $a0, $s1, 0 */
421 0x7000003F, /* sdbbp */
423 0xAD4B0000, /* sw $t3, 0($t2) */
424 0xAD480010, /* sw $t0, 16($t2) */
425 0xAD490010, /* sw $t1, 16($t2) */
426 0xAD4C0008, /* sw $t4, 8($t2) */
428 0x8D500000, /* lw $s0, 0($t2) */
429 0x020C8024, /* and $s0, $s0, $t4 */
430 0x1600FFFD, /* bne $s0, $zero, waitflash */
431 0x00000000, /* nop */
432 0x00000000, /* nop */
433 0x00000000, /* nop */
434 0x00000000, /* nop */
435 0x00000000, /* nop */
436 0x8D510000, /* lw $s1, 0($t2) */
437 0x30113000, /* andi $s1, $zero, 0x3000 */
438 0x1620FFEF, /* bne $s1, $zero, error */
439 0xAD4D0004, /* sw $t5, 4($t2) */
440 0x03E00008, /* jr $ra */
444 static int pic32mx_write_block(struct flash_bank
*bank
, const uint8_t *buffer
,
445 uint32_t offset
, uint32_t count
)
447 struct target
*target
= bank
->target
;
448 uint32_t buffer_size
= 16384;
449 struct working_area
*write_algorithm
;
450 struct working_area
*source
;
451 uint32_t address
= bank
->base
+ offset
;
452 struct reg_param reg_params
[3];
454 int retval
= ERROR_OK
;
456 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
457 struct mips32_algorithm mips32_info
;
459 /* flash write code */
460 if (target_alloc_working_area(target
, sizeof(pic32mx_flash_write_code
),
461 &write_algorithm
) != ERROR_OK
) {
462 LOG_WARNING("no working area available, can't do block memory writes");
463 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
466 /* Change values for counters and row size, depending on variant */
467 switch (pic32mx_info
->dev_type
) {
471 pic32mx_flash_write_code
[8] = 0x2CD30020;
472 pic32mx_flash_write_code
[14] = 0x24840080;
473 pic32mx_flash_write_code
[15] = 0x24A50080;
474 pic32mx_flash_write_code
[17] = 0x24C6FFE0;
479 pic32mx_flash_write_code
[8] = 0x2CD30080;
480 pic32mx_flash_write_code
[14] = 0x24840200;
481 pic32mx_flash_write_code
[15] = 0x24A50200;
482 pic32mx_flash_write_code
[17] = 0x24C6FF80;
487 uint8_t code
[sizeof(pic32mx_flash_write_code
)];
488 target_buffer_set_u32_array(target
, code
, ARRAY_SIZE(pic32mx_flash_write_code
),
489 pic32mx_flash_write_code
);
490 retval
= target_write_buffer(target
, write_algorithm
->address
, sizeof(code
), code
);
491 if (retval
!= ERROR_OK
)
495 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
497 if (buffer_size
<= 256) {
498 /* we already allocated the writing code, but failed to get a
499 * buffer, free the algorithm */
500 target_free_working_area(target
, write_algorithm
);
502 LOG_WARNING("no large enough working area available, can't do block memory writes");
503 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
507 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
508 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
510 init_reg_param(®_params
[0], "r4", 32, PARAM_IN_OUT
);
511 init_reg_param(®_params
[1], "r5", 32, PARAM_OUT
);
512 init_reg_param(®_params
[2], "r6", 32, PARAM_OUT
);
514 int row_offset
= offset
% row_size
;
515 uint8_t *new_buffer
= NULL
;
516 if (row_offset
&& (count
>= (row_size
/ 4))) {
517 new_buffer
= malloc(buffer_size
);
518 if (new_buffer
== NULL
) {
519 LOG_ERROR("Out of memory");
522 memset(new_buffer
, 0xff, row_offset
);
523 address
-= row_offset
;
529 uint32_t thisrun_count
;
532 thisrun_count
= (count
> ((buffer_size
- row_offset
) / 4)) ?
533 ((buffer_size
- row_offset
) / 4) : count
;
535 memcpy(new_buffer
+ row_offset
, buffer
, thisrun_count
* 4);
537 retval
= target_write_buffer(target
, source
->address
,
538 row_offset
+ thisrun_count
* 4, new_buffer
);
539 if (retval
!= ERROR_OK
)
542 thisrun_count
= (count
> (buffer_size
/ 4)) ?
543 (buffer_size
/ 4) : count
;
545 retval
= target_write_buffer(target
, source
->address
,
546 thisrun_count
* 4, buffer
);
547 if (retval
!= ERROR_OK
)
551 buf_set_u32(reg_params
[0].value
, 0, 32, Virt2Phys(source
->address
));
552 buf_set_u32(reg_params
[1].value
, 0, 32, Virt2Phys(address
));
553 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
+ row_offset
/ 4);
555 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
556 write_algorithm
->address
,
557 0, 10000, &mips32_info
);
558 if (retval
!= ERROR_OK
) {
559 LOG_ERROR("error executing pic32mx flash write algorithm");
560 retval
= ERROR_FLASH_OPERATION_FAILED
;
564 status
= buf_get_u32(reg_params
[0].value
, 0, 32);
566 if (status
& NVMCON_NVMERR
) {
567 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
568 retval
= ERROR_FLASH_OPERATION_FAILED
;
572 if (status
& NVMCON_LVDERR
) {
573 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
574 retval
= ERROR_FLASH_OPERATION_FAILED
;
578 buffer
+= thisrun_count
* 4;
579 address
+= thisrun_count
* 4;
580 count
-= thisrun_count
;
582 address
+= row_offset
;
587 target_free_working_area(target
, source
);
588 target_free_working_area(target
, write_algorithm
);
590 destroy_reg_param(®_params
[0]);
591 destroy_reg_param(®_params
[1]);
592 destroy_reg_param(®_params
[2]);
598 static int pic32mx_write_word(struct flash_bank
*bank
, uint32_t address
, uint32_t word
)
600 struct target
*target
= bank
->target
;
602 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(address
));
603 target_write_u32(target
, PIC32MX_NVMDATA
, word
);
605 return pic32mx_nvm_exec(bank
, NVMCON_OP_WORD_PROG
, 5);
608 static int pic32mx_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
610 uint32_t words_remaining
= (count
/ 4);
611 uint32_t bytes_remaining
= (count
& 0x00000003);
612 uint32_t address
= bank
->base
+ offset
;
613 uint32_t bytes_written
= 0;
617 if (bank
->target
->state
!= TARGET_HALTED
) {
618 LOG_ERROR("Target not halted");
619 return ERROR_TARGET_NOT_HALTED
;
622 LOG_DEBUG("writing to flash at address " TARGET_ADDR_FMT
" at offset 0x%8.8" PRIx32
623 " count: 0x%8.8" PRIx32
"", bank
->base
, offset
, count
);
626 LOG_WARNING("offset 0x%" PRIx32
"breaks required 4-byte alignment", offset
);
627 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
630 /* multiple words (4-byte) to be programmed? */
631 if (words_remaining
> 0) {
632 /* try using a block write */
633 retval
= pic32mx_write_block(bank
, buffer
, offset
, words_remaining
);
634 if (retval
!= ERROR_OK
) {
635 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
636 /* if block write failed (no sufficient working area),
637 * we use normal (slow) single dword accesses */
638 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
639 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
640 LOG_ERROR("flash writing failed");
644 buffer
+= words_remaining
* 4;
645 address
+= words_remaining
* 4;
650 while (words_remaining
> 0) {
652 memcpy(&value
, buffer
+ bytes_written
, sizeof(uint32_t));
654 status
= pic32mx_write_word(bank
, address
, value
);
656 if (status
& NVMCON_NVMERR
) {
657 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
658 return ERROR_FLASH_OPERATION_FAILED
;
661 if (status
& NVMCON_LVDERR
) {
662 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
663 return ERROR_FLASH_OPERATION_FAILED
;
671 if (bytes_remaining
) {
672 uint32_t value
= 0xffffffff;
673 memcpy(&value
, buffer
+ bytes_written
, bytes_remaining
);
675 status
= pic32mx_write_word(bank
, address
, value
);
677 if (status
& NVMCON_NVMERR
) {
678 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
679 return ERROR_FLASH_OPERATION_FAILED
;
682 if (status
& NVMCON_LVDERR
) {
683 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
684 return ERROR_FLASH_OPERATION_FAILED
;
691 static int pic32mx_probe(struct flash_bank
*bank
)
693 struct target
*target
= bank
->target
;
694 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
695 struct mips32_common
*mips32
= target
->arch_info
;
696 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
698 uint32_t num_pages
= 0;
702 pic32mx_info
->probed
= false;
704 device_id
= ejtag_info
->idcode
;
705 LOG_INFO("device id = 0x%08" PRIx32
" (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
707 (unsigned)((device_id
>> 1) & 0x7ff),
708 (unsigned)((device_id
>> 12) & 0xffff),
709 (unsigned)((device_id
>> 28) & 0xf));
711 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
712 LOG_WARNING("Cannot identify target as a PIC32MX family.");
713 return ERROR_FLASH_OPERATION_FAILED
;
716 /* Check for PIC32mx1xx/2xx */
717 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++) {
718 if (pic32mx_devs
[i
].devid
== (device_id
& 0x0fffffff)) {
719 if ((pic32mx_devs
[i
].name
[0] == '1') || (pic32mx_devs
[i
].name
[0] == '2'))
720 pic32mx_info
->dev_type
= (pic32mx_devs
[i
].name
[1] == '7') ? MX_17x_27x
: MX_1xx_2xx
;
725 switch (pic32mx_info
->dev_type
) {
735 if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
736 /* 0x1FC00000: Boot flash size */
738 /* for some reason this register returns 8k for the boot bank size
739 * this does not match the docs, so for now set the boot bank at a
741 if (target_read_u32(target
, PIC32MX_BMXBOOTSZ
, &num_pages
) != ERROR_OK
) {
742 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
743 num_pages
= (12 * 1024);
746 /* fixed 12k boot bank - see comments above */
747 switch (pic32mx_info
->dev_type
) {
750 num_pages
= (3 * 1024);
753 num_pages
= (12 * 1024);
758 /* read the flash size from the device */
759 if (target_read_u32(target
, PIC32MX_BMXPFMSZ
, &num_pages
) != ERROR_OK
) {
760 switch (pic32mx_info
->dev_type
) {
763 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash");
764 num_pages
= (32 * 1024);
767 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
768 num_pages
= (512 * 1024);
774 LOG_INFO("flash size = %" PRIu32
"kbytes", num_pages
/ 1024);
778 /* calculate numbers of pages */
779 num_pages
/= page_size
;
780 bank
->size
= (num_pages
* page_size
);
781 bank
->num_sectors
= num_pages
;
782 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
784 for (i
= 0; i
< (int)num_pages
; i
++) {
785 bank
->sectors
[i
].offset
= i
* page_size
;
786 bank
->sectors
[i
].size
= page_size
;
787 bank
->sectors
[i
].is_erased
= -1;
788 bank
->sectors
[i
].is_protected
= 1;
791 pic32mx_info
->probed
= true;
796 static int pic32mx_auto_probe(struct flash_bank
*bank
)
798 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
799 if (pic32mx_info
->probed
)
801 return pic32mx_probe(bank
);
804 static int pic32mx_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
806 struct target
*target
= bank
->target
;
807 struct mips32_common
*mips32
= target
->arch_info
;
808 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
811 device_id
= ejtag_info
->idcode
;
813 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
814 command_print_sameline(cmd
,
815 "Cannot identify target as a PIC32MX family (manufacturer 0x%03x != 0x%03x)\n",
816 (unsigned)((device_id
>> 1) & 0x7ff),
818 return ERROR_FLASH_OPERATION_FAILED
;
822 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++) {
823 if (pic32mx_devs
[i
].devid
== (device_id
& 0x0fffffff)) {
824 command_print_sameline(cmd
, "PIC32MX%s", pic32mx_devs
[i
].name
);
829 if (pic32mx_devs
[i
].name
== NULL
)
830 command_print_sameline(cmd
, "Unknown");
832 command_print_sameline(cmd
, " Ver: 0x%02x",
833 (unsigned)((device_id
>> 28) & 0xf));
838 COMMAND_HANDLER(pic32mx_handle_pgm_word_command
)
840 uint32_t address
, value
;
844 return ERROR_COMMAND_SYNTAX_ERROR
;
846 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
847 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
849 struct flash_bank
*bank
;
850 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 2, &bank
);
851 if (ERROR_OK
!= retval
)
854 if (address
< bank
->base
|| address
>= (bank
->base
+ bank
->size
)) {
855 command_print(CMD
, "flash address '%s' is out of bounds", CMD_ARGV
[0]);
860 status
= pic32mx_write_word(bank
, address
, value
);
861 if (status
& NVMCON_NVMERR
)
862 res
= ERROR_FLASH_OPERATION_FAILED
;
863 if (status
& NVMCON_LVDERR
)
864 res
= ERROR_FLASH_OPERATION_FAILED
;
867 command_print(CMD
, "pic32mx pgm word complete");
869 command_print(CMD
, "pic32mx pgm word failed (status = 0x%x)", status
);
874 COMMAND_HANDLER(pic32mx_handle_unlock_command
)
876 struct target
*target
= NULL
;
877 struct mips_m4k_common
*mips_m4k
;
878 struct mips_ejtag
*ejtag_info
;
882 command_print(CMD
, "pic32mx unlock <bank>");
883 return ERROR_COMMAND_SYNTAX_ERROR
;
886 struct flash_bank
*bank
;
887 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
888 if (ERROR_OK
!= retval
)
891 target
= bank
->target
;
892 mips_m4k
= target_to_m4k(target
);
893 ejtag_info
= &mips_m4k
->mips32
.ejtag_info
;
895 /* we have to use the MTAP to perform a full erase */
896 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_MTAP
);
897 mips_ejtag_set_instr(ejtag_info
, MTAP_COMMAND
);
899 /* first check status of device */
900 uint8_t mchip_cmd
= MCHP_STATUS
;
901 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
902 if (mchip_cmd
& (1 << 7)) {
903 /* device is not locked */
904 command_print(CMD
, "pic32mx is already unlocked, erasing anyway");
907 /* unlock/erase device */
908 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ASERT_RST
);
911 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ERASE
);
914 mchip_cmd
= MCHP_STATUS
;
915 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
916 if (timeout
-- == 0) {
917 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx8
"", mchip_cmd
);
921 } while ((mchip_cmd
& (1 << 2)) || (!(mchip_cmd
& (1 << 3))));
923 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_DE_ASSERT_RST
);
925 /* select ejtag tap */
926 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_ETAP
);
928 command_print(CMD
, "pic32mx unlocked.\n"
929 "INFO: a reset or power cycle is required "
930 "for the new settings to take effect.");
935 static const struct command_registration pic32mx_exec_command_handlers
[] = {
938 .usage
= "<addr> <value> <bank>",
939 .handler
= pic32mx_handle_pgm_word_command
,
940 .mode
= COMMAND_EXEC
,
941 .help
= "program a word",
945 .handler
= pic32mx_handle_unlock_command
,
946 .mode
= COMMAND_EXEC
,
947 .usage
= "[bank_id]",
948 .help
= "Unlock/Erase entire device.",
950 COMMAND_REGISTRATION_DONE
953 static const struct command_registration pic32mx_command_handlers
[] = {
957 .help
= "pic32mx flash command group",
959 .chain
= pic32mx_exec_command_handlers
,
961 COMMAND_REGISTRATION_DONE
964 const struct flash_driver pic32mx_flash
= {
966 .commands
= pic32mx_command_handlers
,
967 .flash_bank_command
= pic32mx_flash_bank_command
,
968 .erase
= pic32mx_erase
,
969 .protect
= pic32mx_protect
,
970 .write
= pic32mx_write
,
971 .read
= default_flash_read
,
972 .probe
= pic32mx_probe
,
973 .auto_probe
= pic32mx_auto_probe
,
974 .erase_check
= default_flash_blank_check
,
975 .protect_check
= pic32mx_protect_check
,
976 .info
= pic32mx_info
,
977 .free_driver_priv
= default_flash_free_driver_priv
,
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)