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

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)