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

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)