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

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)