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

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)