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

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)