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

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)