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

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)