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

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)