957bfc2a5153b86a90c7c736c1e87b9a16118762
[openocd.git] / src / flash / nor / pic32mx.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2008 by John McCarthy *
9 * jgmcc@magma.ca *
10 * *
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. *
15 * *
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. *
20 * *
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 ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "imp.h"
31 #include <target/algorithm.h>
32 #include <target/mips32.h>
33 #include <target/mips_m4k.h>
34
35 #define PIC32MX_MANUF_ID 0x029
36
37 /* pic32mx memory locations */
38
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
43
44 /*
45 * Translate Virtual and Physical addresses.
46 * Note: These macros only work for KSEG0/KSEG1 addresses.
47 */
48
49 #define Virt2Phys(v) ((v) & 0x1FFFFFFF)
50
51 /* pic32mx configuration register locations */
52
53 #define PIC32MX_DEVCFG0 0xBFC02FFC
54 #define PIC32MX_DEVCFG1 0xBFC02FF8
55 #define PIC32MX_DEVCFG2 0xBFC02FF4
56 #define PIC32MX_DEVCFG3 0xBFC02FF0
57 #define PIC32MX_DEVID 0xBF80F220
58
59 #define PIC32MX_BMXPFMSZ 0xBF882060
60 #define PIC32MX_BMXBOOTSZ 0xBF882070
61 #define PIC32MX_BMXDRMSZ 0xBF882040
62
63 /* pic32mx flash controller register locations */
64
65 #define PIC32MX_NVMCON 0xBF80F400
66 #define PIC32MX_NVMCONCLR 0xBF80F404
67 #define PIC32MX_NVMCONSET 0xBF80F408
68 #define PIC32MX_NVMCONINV 0xBF80F40C
69 #define NVMCON_NVMWR (1 << 15)
70 #define NVMCON_NVMWREN (1 << 14)
71 #define NVMCON_NVMERR (1 << 13)
72 #define NVMCON_LVDERR (1 << 12)
73 #define NVMCON_LVDSTAT (1 << 11)
74 #define NVMCON_OP_PFM_ERASE 0x5
75 #define NVMCON_OP_PAGE_ERASE 0x4
76 #define NVMCON_OP_ROW_PROG 0x3
77 #define NVMCON_OP_WORD_PROG 0x1
78 #define NVMCON_OP_NOP 0x0
79
80 #define PIC32MX_NVMKEY 0xBF80F410
81 #define PIC32MX_NVMADDR 0xBF80F420
82 #define PIC32MX_NVMADDRCLR 0xBF80F424
83 #define PIC32MX_NVMADDRSET 0xBF80F428
84 #define PIC32MX_NVMADDRINV 0xBF80F42C
85 #define PIC32MX_NVMDATA 0xBF80F430
86 #define PIC32MX_NVMSRCADDR 0xBF80F440
87
88 /* flash unlock keys */
89
90 #define NVMKEY1 0xAA996655
91 #define NVMKEY2 0x556699AA
92
93 struct pic32mx_flash_bank
94 {
95 struct working_area *write_algorithm;
96 int probed;
97 };
98
99 /*
100 * DEVID values as per PIC32MX Flash Programming Specification Rev H
101 */
102
103 static const struct pic32mx_devs_s {
104 uint32_t devid;
105 const char *name;
106 } pic32mx_devs[] = {
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"},
164 {0x00000000, NULL}
165 };
166
167 /* flash bank pic32mx <base> <size> 0 0 <target#>
168 */
169 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command)
170 {
171 struct pic32mx_flash_bank *pic32mx_info;
172
173 if (CMD_ARGC < 6)
174 {
175 return ERROR_COMMAND_SYNTAX_ERROR;
176 }
177
178 pic32mx_info = malloc(sizeof(struct pic32mx_flash_bank));
179 bank->driver_priv = pic32mx_info;
180
181 pic32mx_info->write_algorithm = NULL;
182 pic32mx_info->probed = 0;
183
184 return ERROR_OK;
185 }
186
187 static uint32_t pic32mx_get_flash_status(struct flash_bank *bank)
188 {
189 struct target *target = bank->target;
190 uint32_t status;
191
192 target_read_u32(target, PIC32MX_NVMCON, &status);
193
194 return status;
195 }
196
197 static uint32_t pic32mx_wait_status_busy(struct flash_bank *bank, int timeout)
198 {
199 uint32_t status;
200
201 /* wait for busy to clear */
202 while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0))
203 {
204 LOG_DEBUG("status: 0x%" PRIx32, status);
205 alive_sleep(1);
206 }
207 if (timeout <= 0)
208 LOG_DEBUG("timeout: status: 0x%" PRIx32, status);
209
210 return status;
211 }
212
213 static int pic32mx_nvm_exec(struct flash_bank *bank, uint32_t op, uint32_t timeout)
214 {
215 struct target *target = bank->target;
216 uint32_t status;
217
218 target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN | op);
219
220 /* unlock flash registers */
221 target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1);
222 target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2);
223
224 /* start operation */
225 target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR);
226
227 status = pic32mx_wait_status_busy(bank, timeout);
228
229 /* lock flash registers */
230 target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN);
231
232 return status;
233 }
234
235 static int pic32mx_protect_check(struct flash_bank *bank)
236 {
237 struct target *target = bank->target;
238
239 uint32_t devcfg0;
240 int s;
241 int num_pages;
242
243 if (target->state != TARGET_HALTED)
244 {
245 LOG_ERROR("Target not halted");
246 return ERROR_TARGET_NOT_HALTED;
247 }
248
249 target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0);
250
251 if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
252 num_pages = 0xffff; /* All pages protected */
253 else if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH)
254 {
255 if (devcfg0 & (1 << 24))
256 num_pages = 0; /* All pages unprotected */
257 else
258 num_pages = 0xffff; /* All pages protected */
259 }
260 else /* pgm flash */
261 num_pages = (~devcfg0 >> 12) & 0xff;
262
263 for (s = 0; s < bank->num_sectors && s < num_pages; s++)
264 bank->sectors[s].is_protected = 1;
265 for (; s < bank->num_sectors; s++)
266 bank->sectors[s].is_protected = 0;
267
268 return ERROR_OK;
269 }
270
271 static int pic32mx_erase(struct flash_bank *bank, int first, int last)
272 {
273 struct target *target = bank->target;
274 int i;
275 uint32_t status;
276
277 if (bank->target->state != TARGET_HALTED)
278 {
279 LOG_ERROR("Target not halted");
280 return ERROR_TARGET_NOT_HALTED;
281 }
282
283 if ((first == 0) && (last == (bank->num_sectors - 1))
284 && (Virt2Phys(bank->base) == PIC32MX_PHYS_PGM_FLASH))
285 {
286 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
287 * we need to use the MTAP to perform a full erase */
288 LOG_DEBUG("Erasing entire program flash");
289 status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50);
290 if (status & NVMCON_NVMERR)
291 return ERROR_FLASH_OPERATION_FAILED;
292 if (status & NVMCON_LVDERR)
293 return ERROR_FLASH_OPERATION_FAILED;
294 return ERROR_OK;
295 }
296
297 for (i = first; i <= last; i++)
298 {
299 target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(bank->base + bank->sectors[i].offset));
300
301 status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
302
303 if (status & NVMCON_NVMERR)
304 return ERROR_FLASH_OPERATION_FAILED;
305 if (status & NVMCON_LVDERR)
306 return ERROR_FLASH_OPERATION_FAILED;
307 bank->sectors[i].is_erased = 1;
308 }
309
310 return ERROR_OK;
311 }
312
313 static int pic32mx_protect(struct flash_bank *bank, int set, int first, int last)
314 {
315 struct target *target = bank->target;
316
317 if (target->state != TARGET_HALTED)
318 {
319 LOG_ERROR("Target not halted");
320 return ERROR_TARGET_NOT_HALTED;
321 }
322
323 return ERROR_OK;
324 }
325
326 /* see contib/loaders/flash/pic32mx.s for src */
327
328 static const uint32_t pic32mx_flash_write_code[] = {
329 /* write: */
330 0x3C08AA99, /* lui $t0, 0xaa99 */
331 0x35086655, /* ori $t0, 0x6655 */
332 0x3C095566, /* lui $t1, 0x5566 */
333 0x352999AA, /* ori $t1, 0x99aa */
334 0x3C0ABF80, /* lui $t2, 0xbf80 */
335 0x354AF400, /* ori $t2, 0xf400 */
336 0x340B4003, /* ori $t3, $zero, 0x4003 */
337 0x340C8000, /* ori $t4, $zero, 0x8000 */
338 /* write_row: */
339 0x2CD30080, /* sltiu $s3, $a2, 128 */
340 0x16600008, /* bne $s3, $zero, write_word */
341 0x340D4000, /* ori $t5, $zero, 0x4000 */
342 0xAD450020, /* sw $a1, 32($t2) */
343 0xAD440040, /* sw $a0, 64($t2) */
344 0x04110016, /* bal progflash */
345 0x24840200, /* addiu $a0, $a0, 512 */
346 0x24A50200, /* addiu $a1, $a1, 512 */
347 0x1000FFF7, /* beq $zero, $zero, write_row */
348 0x24C6FF80, /* addiu $a2, $a2, -128 */
349 /* write_word: */
350 0x3C15A000, /* lui $s5, 0xa000 */
351 0x36B50000, /* ori $s5, $s5, 0x0 */
352 0x00952025, /* or $a0, $a0, $s5 */
353 0x10000008, /* beq $zero, $zero, next_word */
354 0x340B4001, /* ori $t3, $zero, 0x4001 */
355 /* prog_word: */
356 0x8C940000, /* lw $s4, 0($a0) */
357 0xAD540030, /* sw $s4, 48($t2) */
358 0xAD450020, /* sw $a1, 32($t2) */
359 0x04110009, /* bal progflash */
360 0x24840004, /* addiu $a0, $a0, 4 */
361 0x24A50004, /* addiu $a1, $a1, 4 */
362 0x24C6FFFF, /* addiu $a2, $a2, -1 */
363 /* next_word: */
364 0x14C0FFF8, /* bne $a2, $zero, prog_word */
365 0x00000000, /* nop */
366 /* done: */
367 0x10000002, /* beq $zero, $zero, exit */
368 0x24040000, /* addiu $a0, $zero, 0 */
369 /* error: */
370 0x26240000, /* addiu $a0, $s1, 0 */
371 /* exit: */
372 0x7000003F, /* sdbbp */
373 /* progflash: */
374 0xAD4B0000, /* sw $t3, 0($t2) */
375 0xAD480010, /* sw $t0, 16($t2) */
376 0xAD490010, /* sw $t1, 16($t2) */
377 0xAD4C0008, /* sw $t4, 8($t2) */
378 /* waitflash: */
379 0x8D500000, /* lw $s0, 0($t2) */
380 0x020C8024, /* and $s0, $s0, $t4 */
381 0x1600FFFD, /* bne $s0, $zero, waitflash */
382 0x00000000, /* nop */
383 0x00000000, /* nop */
384 0x00000000, /* nop */
385 0x00000000, /* nop */
386 0x00000000, /* nop */
387 0x8D510000, /* lw $s1, 0($t2) */
388 0x30113000, /* andi $s1, $zero, 0x3000 */
389 0x1620FFEF, /* bne $s1, $zero, error */
390 0xAD4D0004, /* sw $t5, 4($t2) */
391 0x03E00008, /* jr $ra */
392 0x00000000 /* nop */
393 };
394
395 static int pic32mx_write_block(struct flash_bank *bank, uint8_t *buffer,
396 uint32_t offset, uint32_t count)
397 {
398 struct target *target = bank->target;
399 uint32_t buffer_size = 16384;
400 struct working_area *source;
401 uint32_t address = bank->base + offset;
402 struct reg_param reg_params[3];
403 int retval = ERROR_OK;
404
405 struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
406 struct mips32_algorithm mips32_info;
407
408 /* flash write code */
409 if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code),
410 &pic32mx_info->write_algorithm) != ERROR_OK)
411 {
412 LOG_WARNING("no working area available, can't do block memory writes");
413 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
414 };
415
416 if ((retval = target_write_buffer(target,
417 pic32mx_info->write_algorithm->address,
418 sizeof(pic32mx_flash_write_code),
419 (uint8_t*)pic32mx_flash_write_code)) != ERROR_OK)
420 return retval;
421
422 /* memory buffer */
423 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK)
424 {
425 buffer_size /= 2;
426 if (buffer_size <= 256)
427 {
428 /* if we already allocated the writing code, but failed to get a
429 * buffer, free the algorithm */
430 if (pic32mx_info->write_algorithm)
431 target_free_working_area(target, pic32mx_info->write_algorithm);
432
433 LOG_WARNING("no large enough working area available, can't do block memory writes");
434 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
435 }
436 };
437
438 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
439 mips32_info.isa_mode = MIPS32_ISA_MIPS32;
440
441 init_reg_param(&reg_params[0], "a0", 32, PARAM_IN_OUT);
442 init_reg_param(&reg_params[1], "a1", 32, PARAM_OUT);
443 init_reg_param(&reg_params[2], "a2", 32, PARAM_OUT);
444
445 while (count > 0)
446 {
447 uint32_t status;
448 uint32_t thisrun_count = (count > (buffer_size / 4)) ?
449 (buffer_size / 4) : count;
450
451 if ((retval = target_write_buffer(target, source->address,
452 thisrun_count * 4, buffer)) != ERROR_OK)
453 break;
454
455 buf_set_u32(reg_params[0].value, 0, 32, Virt2Phys(source->address));
456 buf_set_u32(reg_params[1].value, 0, 32, Virt2Phys(address));
457 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
458
459 if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
460 pic32mx_info->write_algorithm->address,
461 0,
462 10000, &mips32_info)) != ERROR_OK)
463 {
464 LOG_ERROR("error executing pic32mx flash write algorithm");
465 retval = ERROR_FLASH_OPERATION_FAILED;
466 break;
467 }
468
469 status = buf_get_u32(reg_params[0].value, 0, 32);
470
471 if (status & NVMCON_NVMERR)
472 {
473 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
474 retval = ERROR_FLASH_OPERATION_FAILED;
475 break;
476 }
477
478 if (status & NVMCON_LVDERR)
479 {
480 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
481 retval = ERROR_FLASH_OPERATION_FAILED;
482 break;
483 }
484
485 buffer += thisrun_count * 4;
486 address += thisrun_count * 4;
487 count -= thisrun_count;
488 }
489
490 target_free_working_area(target, source);
491 target_free_working_area(target, pic32mx_info->write_algorithm);
492
493 destroy_reg_param(&reg_params[0]);
494 destroy_reg_param(&reg_params[1]);
495 destroy_reg_param(&reg_params[2]);
496
497 return retval;
498 }
499
500 static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_t word)
501 {
502 struct target *target = bank->target;
503
504 target_write_u32(target, PIC32MX_NVMADDR, Virt2Phys(address));
505 target_write_u32(target, PIC32MX_NVMDATA, word);
506
507 return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5);
508 }
509
510 static int pic32mx_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
511 {
512 uint32_t words_remaining = (count / 4);
513 uint32_t bytes_remaining = (count & 0x00000003);
514 uint32_t address = bank->base + offset;
515 uint32_t bytes_written = 0;
516 uint32_t status;
517 int retval;
518
519 if (bank->target->state != TARGET_HALTED)
520 {
521 LOG_ERROR("Target not halted");
522 return ERROR_TARGET_NOT_HALTED;
523 }
524
525 LOG_DEBUG("writing to flash at address 0x%08" PRIx32 " at offset 0x%8.8" PRIx32
526 " count: 0x%8.8" PRIx32 "", bank->base, offset, count);
527
528 if (offset & 0x3)
529 {
530 LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
531 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
532 }
533
534 /* multiple words (4-byte) to be programmed? */
535 if (words_remaining > 0)
536 {
537 /* try using a block write */
538 if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
539 {
540 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
541 {
542 /* if block write failed (no sufficient working area),
543 * we use normal (slow) single dword accesses */
544 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
545 }
546 else if (retval == ERROR_FLASH_OPERATION_FAILED)
547 {
548 LOG_ERROR("flash writing failed");
549 return retval;
550 }
551 }
552 else
553 {
554 buffer += words_remaining * 4;
555 address += words_remaining * 4;
556 words_remaining = 0;
557 }
558 }
559
560 while (words_remaining > 0)
561 {
562 uint32_t value;
563 memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
564
565 status = pic32mx_write_word(bank, address, value);
566
567 if (status & NVMCON_NVMERR)
568 {
569 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
570 return ERROR_FLASH_OPERATION_FAILED;
571 }
572
573 if (status & NVMCON_LVDERR)
574 {
575 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
576 return ERROR_FLASH_OPERATION_FAILED;
577 }
578
579 bytes_written += 4;
580 words_remaining--;
581 address += 4;
582 }
583
584 if (bytes_remaining)
585 {
586 uint32_t value = 0xffffffff;
587 memcpy(&value, buffer + bytes_written, bytes_remaining);
588
589 status = pic32mx_write_word(bank, address, value);
590
591 if (status & NVMCON_NVMERR)
592 {
593 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
594 return ERROR_FLASH_OPERATION_FAILED;
595 }
596
597 if (status & NVMCON_LVDERR)
598 {
599 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
600 return ERROR_FLASH_OPERATION_FAILED;
601 }
602 }
603
604 return ERROR_OK;
605 }
606
607 static int pic32mx_probe(struct flash_bank *bank)
608 {
609 struct target *target = bank->target;
610 struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
611 struct mips32_common *mips32 = target->arch_info;
612 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
613 int i;
614 uint32_t num_pages = 0;
615 uint32_t device_id;
616 int page_size;
617
618 pic32mx_info->probed = 0;
619
620 device_id = ejtag_info->idcode;
621 LOG_INFO("device id = 0x%08" PRIx32 " (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
622 device_id,
623 (unsigned)((device_id >> 1) & 0x7ff),
624 (unsigned)((device_id >> 12) & 0xffff),
625 (unsigned)((device_id >> 28) & 0xf));
626
627 if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
628 LOG_WARNING("Cannot identify target as a PIC32MX family.");
629 return ERROR_FLASH_OPERATION_FAILED;
630 }
631
632 page_size = 4096;
633
634 if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH)
635 {
636 /* 0x1FC00000: Boot flash size */
637 #if 0
638 /* for some reason this register returns 8k for the boot bank size
639 * this does not match the docs, so for now set the boot bank at a
640 * fixed 12k */
641 if (target_read_u32(target, PIC32MX_BMXBOOTSZ, &num_pages) != ERROR_OK) {
642 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
643 num_pages = (12 * 1024);
644 }
645 #else
646 /* fixed 12k boot bank - see comments above */
647 num_pages = (12 * 1024);
648 #endif
649 }
650 else
651 {
652 /* read the flash size from the device */
653 if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
654 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
655 num_pages = (512 * 1024);
656 }
657 }
658
659 LOG_INFO("flash size = %" PRId32 "kbytes", num_pages / 1024);
660
661 if (bank->sectors)
662 {
663 free(bank->sectors);
664 bank->sectors = NULL;
665 }
666
667 /* calculate numbers of pages */
668 num_pages /= page_size;
669 bank->size = (num_pages * page_size);
670 bank->num_sectors = num_pages;
671 bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
672
673 for (i = 0; i < (int)num_pages; i++)
674 {
675 bank->sectors[i].offset = i * page_size;
676 bank->sectors[i].size = page_size;
677 bank->sectors[i].is_erased = -1;
678 bank->sectors[i].is_protected = 1;
679 }
680
681 pic32mx_info->probed = 1;
682
683 return ERROR_OK;
684 }
685
686 static int pic32mx_auto_probe(struct flash_bank *bank)
687 {
688 struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
689 if (pic32mx_info->probed)
690 return ERROR_OK;
691 return pic32mx_probe(bank);
692 }
693
694 static int pic32mx_info(struct flash_bank *bank, char *buf, int buf_size)
695 {
696 struct target *target = bank->target;
697 struct mips32_common *mips32 = target->arch_info;
698 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
699 uint32_t device_id;
700 int printed = 0, i;
701
702 device_id = ejtag_info->idcode;
703
704 if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
705 snprintf(buf, buf_size,
706 "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n",
707 (unsigned)((device_id >> 1) & 0x7ff),
708 PIC32MX_MANUF_ID);
709 return ERROR_FLASH_OPERATION_FAILED;
710 }
711
712 for (i = 0; pic32mx_devs[i].name != NULL; i++)
713 {
714 if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
715 printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
716 break;
717 }
718 }
719
720 if (pic32mx_devs[i].name == NULL) {
721 printed = snprintf(buf, buf_size, "Unknown");
722 }
723
724 buf += printed;
725 buf_size -= printed;
726 snprintf(buf, buf_size, " Ver: 0x%02x",
727 (unsigned)((device_id >> 28) & 0xf));
728
729 return ERROR_OK;
730 }
731
732 COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
733 {
734 uint32_t address, value;
735 int status, res;
736
737 if (CMD_ARGC != 3)
738 {
739 return ERROR_COMMAND_SYNTAX_ERROR;
740 }
741
742 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
743 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
744
745 struct flash_bank *bank;
746 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 2, &bank);
747 if (ERROR_OK != retval)
748 return retval;
749
750 if (address < bank->base || address >= (bank->base + bank->size))
751 {
752 command_print(CMD_CTX, "flash address '%s' is out of bounds", CMD_ARGV[0]);
753 return ERROR_OK;
754 }
755
756 res = ERROR_OK;
757 status = pic32mx_write_word(bank, address, value);
758 if (status & NVMCON_NVMERR)
759 res = ERROR_FLASH_OPERATION_FAILED;
760 if (status & NVMCON_LVDERR)
761 res = ERROR_FLASH_OPERATION_FAILED;
762
763 if (res == ERROR_OK)
764 command_print(CMD_CTX, "pic32mx pgm word complete");
765 else
766 command_print(CMD_CTX, "pic32mx pgm word failed (status = 0x%x)", status);
767
768 return ERROR_OK;
769 }
770
771 COMMAND_HANDLER(pic32mx_handle_unlock_command)
772 {
773 uint32_t mchip_cmd;
774 struct target *target = NULL;
775 struct mips_m4k_common *mips_m4k;
776 struct mips_ejtag *ejtag_info;
777 int timeout = 10;
778
779 if (CMD_ARGC < 1)
780 {
781 command_print(CMD_CTX, "pic32mx unlock <bank>");
782 return ERROR_COMMAND_SYNTAX_ERROR;
783 }
784
785 struct flash_bank *bank;
786 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
787 if (ERROR_OK != retval)
788 return retval;
789
790 target = bank->target;
791 mips_m4k = target_to_m4k(target);
792 ejtag_info = &mips_m4k->mips32.ejtag_info;
793
794 /* we have to use the MTAP to perform a full erase */
795 mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
796 mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
797
798 /* first check status of device */
799 mchip_cmd = MCHP_STATUS;
800 mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
801 if (mchip_cmd & (1 << 7))
802 {
803 /* device is not locked */
804 command_print(CMD_CTX, "pic32mx is already unlocked, erasing anyway");
805 }
806
807 /* unlock/erase device */
808 mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
809
810 mips_ejtag_drscan_8_out(ejtag_info, MCHP_ERASE);
811
812 do {
813 mchip_cmd = MCHP_STATUS;
814 mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
815 if (timeout-- == 0)
816 {
817 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx32 "", mchip_cmd);
818 break;
819 }
820 alive_sleep(1);
821 } while ((mchip_cmd & (1 << 2)) || (!(mchip_cmd & (1 << 3))));
822
823 mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
824
825 /* select ejtag tap */
826 mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
827
828 command_print(CMD_CTX, "pic32mx unlocked.\n"
829 "INFO: a reset or power cycle is required "
830 "for the new settings to take effect.");
831
832 return ERROR_OK;
833 }
834
835 static const struct command_registration pic32mx_exec_command_handlers[] = {
836 {
837 .name = "pgm_word",
838 .usage = "<addr> <value> <bank>",
839 .handler = pic32mx_handle_pgm_word_command,
840 .mode = COMMAND_EXEC,
841 .help = "program a word",
842 },
843 {
844 .name = "unlock",
845 .handler = pic32mx_handle_unlock_command,
846 .mode = COMMAND_EXEC,
847 .usage = "[bank_id]",
848 .help = "Unlock/Erase entire device.",
849 },
850 COMMAND_REGISTRATION_DONE
851 };
852
853 static const struct command_registration pic32mx_command_handlers[] = {
854 {
855 .name = "pic32mx",
856 .mode = COMMAND_ANY,
857 .help = "pic32mx flash command group",
858 .chain = pic32mx_exec_command_handlers,
859 },
860 COMMAND_REGISTRATION_DONE
861 };
862
863 struct flash_driver pic32mx_flash = {
864 .name = "pic32mx",
865 .commands = pic32mx_command_handlers,
866 .flash_bank_command = pic32mx_flash_bank_command,
867 .erase = pic32mx_erase,
868 .protect = pic32mx_protect,
869 .write = pic32mx_write,
870 .read = default_flash_read,
871 .probe = pic32mx_probe,
872 .auto_probe = pic32mx_auto_probe,
873 .erase_check = default_flash_mem_blank_check,
874 .protect_check = pic32mx_protect_check,
875 .info = pic32mx_info,
876 };

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)