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

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)