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

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)