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

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)