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 J
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 {0x04D07053, "130F064B"},
114 {0x04D09053, "130F064C"},
115 {0x04D0B053, "130F064D"},
116 {0x04D06053, "150F128B"},
117 {0x04D08053, "150F128C"},
118 {0x04D0A053, "150F128D"},
119 {0x04A01053, "210F016B"},
120 {0x04A03053, "210F016C"},
121 {0x04A05053, "210F016D"},
122 {0x04A00053, "220F032B"},
123 {0x04A02053, "220F032C"},
124 {0x04A04053, "220F032D"},
125 {0x04D01053, "230F064B"},
126 {0x04D03053, "230F064C"},
127 {0x04D05053, "230F064D"},
128 {0x04D00053, "250F128B"},
129 {0x04D02053, "250F128C"},
130 {0x04D04053, "250F128D"},
131 {0x00938053, "360F512L"},
132 {0x00934053, "360F256L"},
133 {0x0092D053, "340F128L"},
134 {0x0092A053, "320F128L"},
135 {0x00916053, "340F512H"},
136 {0x00912053, "340F256H"},
137 {0x0090D053, "340F128H"},
138 {0x0090A053, "320F128H"},
139 {0x00906053, "320F064H"},
140 {0x00902053, "320F032H"},
141 {0x00978053, "460F512L"},
142 {0x00974053, "460F256L"},
143 {0x0096D053, "440F128L"},
144 {0x00952053, "440F256H"},
145 {0x00956053, "440F512H"},
146 {0x0094D053, "440F128H"},
147 {0x00942053, "420F032H"},
148 {0x04307053, "795F512L"},
149 {0x0430E053, "795F512H"},
150 {0x04306053, "775F512L"},
151 {0x0430D053, "775F512H"},
152 {0x04312053, "775F256L"},
153 {0x04303053, "775F256H"},
154 {0x04417053, "764F128L"},
155 {0x0440B053, "764F128H"},
156 {0x04341053, "695F512L"},
157 {0x04325053, "695F512H"},
158 {0x04311053, "675F512L"},
159 {0x0430C053, "675F512H"},
160 {0x04305053, "675F256L"},
161 {0x0430B053, "675F256H"},
162 {0x04413053, "664F128L"},
163 {0x04407053, "664F128H"},
164 {0x04411053, "664F064L"},
165 {0x04405053, "664F064H"},
166 {0x0430F053, "575F512L"},
167 {0x04309053, "575F512H"},
168 {0x04333053, "575F256L"},
169 {0x04317053, "575F256H"},
170 {0x0440F053, "564F128L"},
171 {0x04403053, "564F128H"},
172 {0x0440D053, "564F064L"},
173 {0x04401053, "564F064H"},
174 {0x04400053, "534F064H"},
175 {0x0440C053, "534F064L"},
179 /* flash bank pic32mx <base> <size> 0 0 <target#>
181 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command
)
183 struct pic32mx_flash_bank
*pic32mx_info
;
186 return ERROR_COMMAND_SYNTAX_ERROR
;
188 pic32mx_info
= malloc(sizeof(struct pic32mx_flash_bank
));
189 bank
->driver_priv
= pic32mx_info
;
191 pic32mx_info
->write_algorithm
= NULL
;
192 pic32mx_info
->probed
= 0;
197 static uint32_t pic32mx_get_flash_status(struct flash_bank
*bank
)
199 struct target
*target
= bank
->target
;
202 target_read_u32(target
, PIC32MX_NVMCON
, &status
);
207 static uint32_t pic32mx_wait_status_busy(struct flash_bank
*bank
, int timeout
)
211 /* wait for busy to clear */
212 while (((status
= pic32mx_get_flash_status(bank
)) & NVMCON_NVMWR
) && (timeout
-- > 0)) {
213 LOG_DEBUG("status: 0x%" PRIx32
, status
);
217 LOG_DEBUG("timeout: status: 0x%" PRIx32
, status
);
222 static int pic32mx_nvm_exec(struct flash_bank
*bank
, uint32_t op
, uint32_t timeout
)
224 struct target
*target
= bank
->target
;
227 target_write_u32(target
, PIC32MX_NVMCON
, NVMCON_NVMWREN
| op
);
229 /* unlock flash registers */
230 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY1
);
231 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY2
);
233 /* start operation */
234 target_write_u32(target
, PIC32MX_NVMCONSET
, NVMCON_NVMWR
);
236 status
= pic32mx_wait_status_busy(bank
, timeout
);
238 /* lock flash registers */
239 target_write_u32(target
, PIC32MX_NVMCONCLR
, NVMCON_NVMWREN
);
244 static int pic32mx_protect_check(struct flash_bank
*bank
)
246 struct target
*target
= bank
->target
;
252 if (target
->state
!= TARGET_HALTED
) {
253 LOG_ERROR("Target not halted");
254 return ERROR_TARGET_NOT_HALTED
;
257 target_read_u32(target
, PIC32MX_DEVCFG0
, &devcfg0
);
259 if ((devcfg0
& (1 << 28)) == 0) /* code protect bit */
260 num_pages
= 0xffff; /* All pages protected */
261 else if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
262 if (devcfg0
& (1 << 24))
263 num_pages
= 0; /* All pages unprotected */
265 num_pages
= 0xffff; /* All pages protected */
266 } else /* pgm flash */
267 num_pages
= (~devcfg0
>> 12) & 0xff;
269 for (s
= 0; s
< bank
->num_sectors
&& s
< num_pages
; s
++)
270 bank
->sectors
[s
].is_protected
= 1;
271 for (; s
< bank
->num_sectors
; s
++)
272 bank
->sectors
[s
].is_protected
= 0;
277 static int pic32mx_erase(struct flash_bank
*bank
, int first
, int last
)
279 struct target
*target
= bank
->target
;
283 if (bank
->target
->state
!= TARGET_HALTED
) {
284 LOG_ERROR("Target not halted");
285 return ERROR_TARGET_NOT_HALTED
;
288 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))
289 && (Virt2Phys(bank
->base
) == PIC32MX_PHYS_PGM_FLASH
)) {
290 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
291 * we need to use the MTAP to perform a full erase */
292 LOG_DEBUG("Erasing entire program flash");
293 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PFM_ERASE
, 50);
294 if (status
& NVMCON_NVMERR
)
295 return ERROR_FLASH_OPERATION_FAILED
;
296 if (status
& NVMCON_LVDERR
)
297 return ERROR_FLASH_OPERATION_FAILED
;
301 for (i
= first
; i
<= last
; i
++) {
302 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(bank
->base
+ bank
->sectors
[i
].offset
));
304 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PAGE_ERASE
, 10);
306 if (status
& NVMCON_NVMERR
)
307 return ERROR_FLASH_OPERATION_FAILED
;
308 if (status
& NVMCON_LVDERR
)
309 return ERROR_FLASH_OPERATION_FAILED
;
310 bank
->sectors
[i
].is_erased
= 1;
316 static int pic32mx_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
318 struct target
*target
= bank
->target
;
320 if (target
->state
!= TARGET_HALTED
) {
321 LOG_ERROR("Target not halted");
322 return ERROR_TARGET_NOT_HALTED
;
328 /* see contib/loaders/flash/pic32mx.s for src */
330 static const uint32_t pic32mx_flash_write_code
[] = {
332 0x3C08AA99, /* lui $t0, 0xaa99 */
333 0x35086655, /* ori $t0, 0x6655 */
334 0x3C095566, /* lui $t1, 0x5566 */
335 0x352999AA, /* ori $t1, 0x99aa */
336 0x3C0ABF80, /* lui $t2, 0xbf80 */
337 0x354AF400, /* ori $t2, 0xf400 */
338 0x340B4003, /* ori $t3, $zero, 0x4003 */
339 0x340C8000, /* ori $t4, $zero, 0x8000 */
341 0x2CD30080, /* sltiu $s3, $a2, 128 */
342 0x16600008, /* bne $s3, $zero, write_word */
343 0x340D4000, /* ori $t5, $zero, 0x4000 */
344 0xAD450020, /* sw $a1, 32($t2) */
345 0xAD440040, /* sw $a0, 64($t2) */
346 0x04110016, /* bal progflash */
347 0x24840200, /* addiu $a0, $a0, 512 */
348 0x24A50200, /* addiu $a1, $a1, 512 */
349 0x1000FFF7, /* beq $zero, $zero, write_row */
350 0x24C6FF80, /* addiu $a2, $a2, -128 */
352 0x3C15A000, /* lui $s5, 0xa000 */
353 0x36B50000, /* ori $s5, $s5, 0x0 */
354 0x00952025, /* or $a0, $a0, $s5 */
355 0x10000008, /* beq $zero, $zero, next_word */
356 0x340B4001, /* ori $t3, $zero, 0x4001 */
358 0x8C940000, /* lw $s4, 0($a0) */
359 0xAD540030, /* sw $s4, 48($t2) */
360 0xAD450020, /* sw $a1, 32($t2) */
361 0x04110009, /* bal progflash */
362 0x24840004, /* addiu $a0, $a0, 4 */
363 0x24A50004, /* addiu $a1, $a1, 4 */
364 0x24C6FFFF, /* addiu $a2, $a2, -1 */
366 0x14C0FFF8, /* bne $a2, $zero, prog_word */
367 0x00000000, /* nop */
369 0x10000002, /* beq $zero, $zero, exit */
370 0x24040000, /* addiu $a0, $zero, 0 */
372 0x26240000, /* addiu $a0, $s1, 0 */
374 0x7000003F, /* sdbbp */
376 0xAD4B0000, /* sw $t3, 0($t2) */
377 0xAD480010, /* sw $t0, 16($t2) */
378 0xAD490010, /* sw $t1, 16($t2) */
379 0xAD4C0008, /* sw $t4, 8($t2) */
381 0x8D500000, /* lw $s0, 0($t2) */
382 0x020C8024, /* and $s0, $s0, $t4 */
383 0x1600FFFD, /* bne $s0, $zero, waitflash */
384 0x00000000, /* nop */
385 0x00000000, /* nop */
386 0x00000000, /* nop */
387 0x00000000, /* nop */
388 0x00000000, /* nop */
389 0x8D510000, /* lw $s1, 0($t2) */
390 0x30113000, /* andi $s1, $zero, 0x3000 */
391 0x1620FFEF, /* bne $s1, $zero, error */
392 0xAD4D0004, /* sw $t5, 4($t2) */
393 0x03E00008, /* jr $ra */
397 static int pic32mx_write_block(struct flash_bank
*bank
, uint8_t *buffer
,
398 uint32_t offset
, uint32_t count
)
400 struct target
*target
= bank
->target
;
401 uint32_t buffer_size
= 16384;
402 struct working_area
*source
;
403 uint32_t address
= bank
->base
+ offset
;
404 struct reg_param reg_params
[3];
405 int retval
= ERROR_OK
;
407 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
408 struct mips32_algorithm mips32_info
;
410 /* flash write code */
411 if (target_alloc_working_area(target
, sizeof(pic32mx_flash_write_code
),
412 &pic32mx_info
->write_algorithm
) != ERROR_OK
) {
413 LOG_WARNING("no working area available, can't do block memory writes");
414 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
417 retval
= target_write_buffer(target
, pic32mx_info
->write_algorithm
->address
,
418 sizeof(pic32mx_flash_write_code
), (uint8_t *)pic32mx_flash_write_code
);
419 if (retval
!= ERROR_OK
)
423 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
425 if (buffer_size
<= 256) {
426 /* if we already allocated the writing code, but failed to get a
427 * buffer, free the algorithm */
428 if (pic32mx_info
->write_algorithm
)
429 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
431 LOG_WARNING("no large enough working area available, can't do block memory writes");
432 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
436 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
437 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
439 init_reg_param(®_params
[0], "a0", 32, PARAM_IN_OUT
);
440 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
441 init_reg_param(®_params
[2], "a2", 32, PARAM_OUT
);
445 uint32_t thisrun_count
= (count
> (buffer_size
/ 4)) ?
446 (buffer_size
/ 4) : count
;
448 retval
= target_write_buffer(target
, source
->address
,
449 thisrun_count
* 4, buffer
);
450 if (retval
!= ERROR_OK
)
453 buf_set_u32(reg_params
[0].value
, 0, 32, Virt2Phys(source
->address
));
454 buf_set_u32(reg_params
[1].value
, 0, 32, Virt2Phys(address
));
455 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
457 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
458 pic32mx_info
->write_algorithm
->address
,
459 0, 10000, &mips32_info
);
460 if (retval
!= ERROR_OK
) {
461 LOG_ERROR("error executing pic32mx flash write algorithm");
462 retval
= ERROR_FLASH_OPERATION_FAILED
;
466 status
= buf_get_u32(reg_params
[0].value
, 0, 32);
468 if (status
& NVMCON_NVMERR
) {
469 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
470 retval
= ERROR_FLASH_OPERATION_FAILED
;
474 if (status
& NVMCON_LVDERR
) {
475 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
476 retval
= ERROR_FLASH_OPERATION_FAILED
;
480 buffer
+= thisrun_count
* 4;
481 address
+= thisrun_count
* 4;
482 count
-= thisrun_count
;
485 target_free_working_area(target
, source
);
486 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
488 destroy_reg_param(®_params
[0]);
489 destroy_reg_param(®_params
[1]);
490 destroy_reg_param(®_params
[2]);
495 static int pic32mx_write_word(struct flash_bank
*bank
, uint32_t address
, uint32_t word
)
497 struct target
*target
= bank
->target
;
499 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(address
));
500 target_write_u32(target
, PIC32MX_NVMDATA
, word
);
502 return pic32mx_nvm_exec(bank
, NVMCON_OP_WORD_PROG
, 5);
505 static int pic32mx_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
507 uint32_t words_remaining
= (count
/ 4);
508 uint32_t bytes_remaining
= (count
& 0x00000003);
509 uint32_t address
= bank
->base
+ offset
;
510 uint32_t bytes_written
= 0;
514 if (bank
->target
->state
!= TARGET_HALTED
) {
515 LOG_ERROR("Target not halted");
516 return ERROR_TARGET_NOT_HALTED
;
519 LOG_DEBUG("writing to flash at address 0x%08" PRIx32
" at offset 0x%8.8" PRIx32
520 " count: 0x%8.8" PRIx32
"", bank
->base
, offset
, count
);
523 LOG_WARNING("offset 0x%" PRIx32
"breaks required 4-byte alignment", offset
);
524 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
527 /* multiple words (4-byte) to be programmed? */
528 if (words_remaining
> 0) {
529 /* try using a block write */
530 retval
= pic32mx_write_block(bank
, buffer
, offset
, words_remaining
);
531 if (retval
!= ERROR_OK
) {
532 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
533 /* if block write failed (no sufficient working area),
534 * we use normal (slow) single dword accesses */
535 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
536 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
537 LOG_ERROR("flash writing failed");
541 buffer
+= words_remaining
* 4;
542 address
+= words_remaining
* 4;
547 while (words_remaining
> 0) {
549 memcpy(&value
, buffer
+ bytes_written
, sizeof(uint32_t));
551 status
= pic32mx_write_word(bank
, address
, value
);
553 if (status
& NVMCON_NVMERR
) {
554 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
555 return ERROR_FLASH_OPERATION_FAILED
;
558 if (status
& NVMCON_LVDERR
) {
559 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
560 return ERROR_FLASH_OPERATION_FAILED
;
568 if (bytes_remaining
) {
569 uint32_t value
= 0xffffffff;
570 memcpy(&value
, buffer
+ bytes_written
, bytes_remaining
);
572 status
= pic32mx_write_word(bank
, address
, value
);
574 if (status
& NVMCON_NVMERR
) {
575 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
576 return ERROR_FLASH_OPERATION_FAILED
;
579 if (status
& NVMCON_LVDERR
) {
580 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
581 return ERROR_FLASH_OPERATION_FAILED
;
588 static int pic32mx_probe(struct flash_bank
*bank
)
590 struct target
*target
= bank
->target
;
591 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
592 struct mips32_common
*mips32
= target
->arch_info
;
593 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
595 uint32_t num_pages
= 0;
599 pic32mx_info
->probed
= 0;
601 device_id
= ejtag_info
->idcode
;
602 LOG_INFO("device id = 0x%08" PRIx32
" (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
604 (unsigned)((device_id
>> 1) & 0x7ff),
605 (unsigned)((device_id
>> 12) & 0xffff),
606 (unsigned)((device_id
>> 28) & 0xf));
608 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
609 LOG_WARNING("Cannot identify target as a PIC32MX family.");
610 return ERROR_FLASH_OPERATION_FAILED
;
615 if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
) {
616 /* 0x1FC00000: Boot flash size */
618 /* for some reason this register returns 8k for the boot bank size
619 * this does not match the docs, so for now set the boot bank at a
621 if (target_read_u32(target
, PIC32MX_BMXBOOTSZ
, &num_pages
) != ERROR_OK
) {
622 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
623 num_pages
= (12 * 1024);
626 /* fixed 12k boot bank - see comments above */
627 num_pages
= (12 * 1024);
630 /* read the flash size from the device */
631 if (target_read_u32(target
, PIC32MX_BMXPFMSZ
, &num_pages
) != ERROR_OK
) {
632 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
633 num_pages
= (512 * 1024);
637 LOG_INFO("flash size = %" PRId32
"kbytes", num_pages
/ 1024);
641 bank
->sectors
= NULL
;
644 /* calculate numbers of pages */
645 num_pages
/= page_size
;
646 bank
->size
= (num_pages
* page_size
);
647 bank
->num_sectors
= num_pages
;
648 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
650 for (i
= 0; i
< (int)num_pages
; i
++) {
651 bank
->sectors
[i
].offset
= i
* page_size
;
652 bank
->sectors
[i
].size
= page_size
;
653 bank
->sectors
[i
].is_erased
= -1;
654 bank
->sectors
[i
].is_protected
= 1;
657 pic32mx_info
->probed
= 1;
662 static int pic32mx_auto_probe(struct flash_bank
*bank
)
664 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
665 if (pic32mx_info
->probed
)
667 return pic32mx_probe(bank
);
670 static int pic32mx_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
672 struct target
*target
= bank
->target
;
673 struct mips32_common
*mips32
= target
->arch_info
;
674 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
678 device_id
= ejtag_info
->idcode
;
680 if (((device_id
>> 1) & 0x7ff) != PIC32MX_MANUF_ID
) {
681 snprintf(buf
, buf_size
,
682 "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
683 (unsigned)((device_id
>> 1) & 0x7ff),
685 return ERROR_FLASH_OPERATION_FAILED
;
688 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++) {
689 if (pic32mx_devs
[i
].devid
== (device_id
& 0x0fffffff)) {
690 printed
= snprintf(buf
, buf_size
, "PIC32MX%s", pic32mx_devs
[i
].name
);
695 if (pic32mx_devs
[i
].name
== NULL
)
696 printed
= snprintf(buf
, buf_size
, "Unknown");
700 snprintf(buf
, buf_size
, " Ver: 0x%02x",
701 (unsigned)((device_id
>> 28) & 0xf));
706 COMMAND_HANDLER(pic32mx_handle_pgm_word_command
)
708 uint32_t address
, value
;
712 return ERROR_COMMAND_SYNTAX_ERROR
;
714 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
715 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
717 struct flash_bank
*bank
;
718 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 2, &bank
);
719 if (ERROR_OK
!= retval
)
722 if (address
< bank
->base
|| address
>= (bank
->base
+ bank
->size
)) {
723 command_print(CMD_CTX
, "flash address '%s' is out of bounds", CMD_ARGV
[0]);
728 status
= pic32mx_write_word(bank
, address
, value
);
729 if (status
& NVMCON_NVMERR
)
730 res
= ERROR_FLASH_OPERATION_FAILED
;
731 if (status
& NVMCON_LVDERR
)
732 res
= ERROR_FLASH_OPERATION_FAILED
;
735 command_print(CMD_CTX
, "pic32mx pgm word complete");
737 command_print(CMD_CTX
, "pic32mx pgm word failed (status = 0x%x)", status
);
742 COMMAND_HANDLER(pic32mx_handle_unlock_command
)
745 struct target
*target
= NULL
;
746 struct mips_m4k_common
*mips_m4k
;
747 struct mips_ejtag
*ejtag_info
;
751 command_print(CMD_CTX
, "pic32mx unlock <bank>");
752 return ERROR_COMMAND_SYNTAX_ERROR
;
755 struct flash_bank
*bank
;
756 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
757 if (ERROR_OK
!= retval
)
760 target
= bank
->target
;
761 mips_m4k
= target_to_m4k(target
);
762 ejtag_info
= &mips_m4k
->mips32
.ejtag_info
;
764 /* we have to use the MTAP to perform a full erase */
765 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_MTAP
);
766 mips_ejtag_set_instr(ejtag_info
, MTAP_COMMAND
);
768 /* first check status of device */
769 mchip_cmd
= MCHP_STATUS
;
770 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
771 if (mchip_cmd
& (1 << 7)) {
772 /* device is not locked */
773 command_print(CMD_CTX
, "pic32mx is already unlocked, erasing anyway");
776 /* unlock/erase device */
777 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ASERT_RST
);
779 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_ERASE
);
782 mchip_cmd
= MCHP_STATUS
;
783 mips_ejtag_drscan_8(ejtag_info
, &mchip_cmd
);
784 if (timeout
-- == 0) {
785 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32
"", mchip_cmd
);
789 } while ((mchip_cmd
& (1 << 2)) || (!(mchip_cmd
& (1 << 3))));
791 mips_ejtag_drscan_8_out(ejtag_info
, MCHP_DE_ASSERT_RST
);
793 /* select ejtag tap */
794 mips_ejtag_set_instr(ejtag_info
, MTAP_SW_ETAP
);
796 command_print(CMD_CTX
, "pic32mx unlocked.\n"
797 "INFO: a reset or power cycle is required "
798 "for the new settings to take effect.");
803 static const struct command_registration pic32mx_exec_command_handlers
[] = {
806 .usage
= "<addr> <value> <bank>",
807 .handler
= pic32mx_handle_pgm_word_command
,
808 .mode
= COMMAND_EXEC
,
809 .help
= "program a word",
813 .handler
= pic32mx_handle_unlock_command
,
814 .mode
= COMMAND_EXEC
,
815 .usage
= "[bank_id]",
816 .help
= "Unlock/Erase entire device.",
818 COMMAND_REGISTRATION_DONE
821 static const struct command_registration pic32mx_command_handlers
[] = {
825 .help
= "pic32mx flash command group",
827 .chain
= pic32mx_exec_command_handlers
,
829 COMMAND_REGISTRATION_DONE
832 struct flash_driver pic32mx_flash
= {
834 .commands
= pic32mx_command_handlers
,
835 .flash_bank_command
= pic32mx_flash_bank_command
,
836 .erase
= pic32mx_erase
,
837 .protect
= pic32mx_protect
,
838 .write
= pic32mx_write
,
839 .read
= default_flash_read
,
840 .probe
= pic32mx_probe
,
841 .auto_probe
= pic32mx_auto_probe
,
842 .erase_check
= default_flash_mem_blank_check
,
843 .protect_check
= pic32mx_protect_check
,
844 .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)