John McCarthy <jgmcc@magma.ca> pic32mx flash fixups and speedups
[openocd.git] / src / flash / 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 "replacements.h"
31
32 #include "pic32mx.h"
33 #include "flash.h"
34 #include "target.h"
35 #include "log.h"
36 #include "mips32.h"
37 #include "algorithm.h"
38 #include "binarybuffer.h"
39
40 #include <stdlib.h>
41 #include <string.h>
42
43 static
44 struct pic32mx_devs_s {
45 u8 devid;
46 char *name;
47 u32 pfm_size;
48 } pic32mx_devs[] = {
49 { 0x78, "460F512L USB", 512 },
50 { 0x74, "460F256L USB", 256 },
51 { 0x6D, "440F128L USB", 128 },
52 { 0x56, "440F512H USB", 512 },
53 { 0x52, "440F256H USB", 256 },
54 { 0x4D, "440F128H USB", 128 },
55 { 0x42, "420F032H USB", 32 },
56 { 0x38, "360F512L", 512 },
57 { 0x34, "360F256L", 256 },
58 { 0x2D, "340F128L", 128 },
59 { 0x2A, "320F128L", 128 },
60 { 0x16, "340F512H", 512 },
61 { 0x12, "340F256H", 256 },
62 { 0x0D, "340F128H", 128 },
63 { 0x0A, "320F128H", 128 },
64 { 0x06, "320F064H", 64 },
65 { 0x02, "320F032H", 32 },
66 { 0x00, NULL, 0 }
67 };
68
69 int pic32mx_register_commands(struct command_context_s *cmd_ctx);
70 int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
71 int pic32mx_erase(struct flash_bank_s *bank, int first, int last);
72 int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last);
73 int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
74 int pic32mx_write_row(struct flash_bank_s *bank, u32 address, u32 srcaddr);
75 int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word);
76 int pic32mx_probe(struct flash_bank_s *bank);
77 int pic32mx_auto_probe(struct flash_bank_s *bank);
78 int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
79 int pic32mx_protect_check(struct flash_bank_s *bank);
80 int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size);
81
82 #if 0
83 int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
84 int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
85 #endif
86 int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
87 int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
88 int pic32mx_chip_erase(struct flash_bank_s *bank);
89
90 flash_driver_t pic32mx_flash =
91 {
92 .name = "pic32mx",
93 .register_commands = pic32mx_register_commands,
94 .flash_bank_command = pic32mx_flash_bank_command,
95 .erase = pic32mx_erase,
96 .protect = pic32mx_protect,
97 .write = pic32mx_write,
98 .probe = pic32mx_probe,
99 .auto_probe = pic32mx_auto_probe,
100 .erase_check = default_flash_mem_blank_check,
101 .protect_check = pic32mx_protect_check,
102 .info = pic32mx_info
103 };
104
105 int pic32mx_register_commands(struct command_context_s *cmd_ctx)
106 {
107 command_t *pic32mx_cmd = register_command(cmd_ctx, NULL, "pic32mx", NULL, COMMAND_ANY, "pic32mx flash specific commands");
108
109 #if 0
110 register_command(cmd_ctx, pic32mx_cmd, "lock", pic32mx_handle_lock_command, COMMAND_EXEC,
111 "lock device");
112 register_command(cmd_ctx, pic32mx_cmd, "unlock", pic32mx_handle_unlock_command, COMMAND_EXEC,
113 "unlock protected device");
114 #endif
115 register_command(cmd_ctx, pic32mx_cmd, "chip_erase", pic32mx_handle_chip_erase_command, COMMAND_EXEC,
116 "erase device");
117 register_command(cmd_ctx, pic32mx_cmd, "pgm_word", pic32mx_handle_pgm_word_command, COMMAND_EXEC,
118 "program a word");
119 return ERROR_OK;
120 }
121
122 /* flash bank pic32mx <base> <size> 0 0 <target#>
123 */
124 int pic32mx_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
125 {
126 pic32mx_flash_bank_t *pic32mx_info;
127
128 if (argc < 6)
129 {
130 LOG_WARNING("incomplete flash_bank pic32mx configuration");
131 return ERROR_FLASH_BANK_INVALID;
132 }
133
134 pic32mx_info = malloc(sizeof(pic32mx_flash_bank_t));
135 bank->driver_priv = pic32mx_info;
136
137 pic32mx_info->write_algorithm = NULL;
138 pic32mx_info->probed = 0;
139
140 return ERROR_OK;
141 }
142
143 u32 pic32mx_get_flash_status(flash_bank_t *bank)
144 {
145 target_t *target = bank->target;
146 u32 status;
147
148 target_read_u32(target, PIC32MX_NVMCON, &status);
149
150 return status;
151 }
152
153 u32 pic32mx_wait_status_busy(flash_bank_t *bank, int timeout)
154 {
155 u32 status;
156
157 /* wait for busy to clear */
158 while (((status = pic32mx_get_flash_status(bank)) & NVMCON_NVMWR) && (timeout-- > 0))
159 {
160 LOG_DEBUG("status: 0x%x", status);
161 alive_sleep(1);
162 }
163 if(timeout <= 0)
164 LOG_DEBUG("timeout: status: 0x%x", status);
165
166 return status;
167 }
168
169 int pic32mx_nvm_exec(struct flash_bank_s *bank, u32 op, u32 timeout)
170 {
171 target_t *target = bank->target;
172 u32 status;
173
174 target_write_u32(target, PIC32MX_NVMCON, NVMCON_NVMWREN|op);
175
176 /* unlock flash registers */
177 target_write_u32(target, PIC32MX_NVMKEY, NVMKEY1);
178 target_write_u32(target, PIC32MX_NVMKEY, NVMKEY2);
179
180 /* start operation */
181 target_write_u32(target, PIC32MX_NVMCONSET, NVMCON_NVMWR);
182
183 status = pic32mx_wait_status_busy(bank, timeout);
184
185 /* lock flash registers */
186 target_write_u32(target, PIC32MX_NVMCONCLR, NVMCON_NVMWREN);
187
188 return status;
189 }
190
191 int pic32mx_protect_check(struct flash_bank_s *bank)
192 {
193 target_t *target = bank->target;
194
195 u32 devcfg0;
196 int s;
197 int num_pages;
198
199 if (target->state != TARGET_HALTED)
200 {
201 LOG_ERROR("Target not halted");
202 return ERROR_TARGET_NOT_HALTED;
203 }
204
205 target_read_u32(target, PIC32MX_DEVCFG0, &devcfg0);
206 if((devcfg0 & (1<<28)) == 0) /* code protect bit */
207 num_pages = 0xffff; /* All pages protected */
208 else if(bank->base == PIC32MX_KSEG1_BOOT_FLASH)
209 {
210 if(devcfg0 & (1<<24))
211 num_pages = 0; /* All pages unprotected */
212 else
213 num_pages = 0xffff; /* All pages protected */
214 }
215 else /* pgm flash */
216 num_pages = (~devcfg0 >> 12) & 0xff;
217 for (s = 0; s < bank->num_sectors && s < num_pages; s++)
218 bank->sectors[s].is_protected = 1;
219 for (; s < bank->num_sectors; s++)
220 bank->sectors[s].is_protected = 0;
221
222 return ERROR_OK;
223 }
224
225 int pic32mx_erase(struct flash_bank_s *bank, int first, int last)
226 {
227 target_t *target = bank->target;
228 int i;
229 u32 status;
230
231 if (bank->target->state != TARGET_HALTED)
232 {
233 LOG_ERROR("Target not halted");
234 return ERROR_TARGET_NOT_HALTED;
235 }
236
237 if ((first == 0) && (last == (bank->num_sectors - 1)) && (bank->base == PIC32MX_KSEG0_PGM_FLASH || bank->base == PIC32MX_KSEG1_PGM_FLASH))
238 {
239 LOG_DEBUG("Erasing entire program flash");
240 status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50);
241 if( status & NVMCON_NVMERR )
242 return ERROR_FLASH_OPERATION_FAILED;
243 if( status & NVMCON_LVDERR )
244 return ERROR_FLASH_OPERATION_FAILED;
245 return ERROR_OK;
246 }
247
248 for (i = first; i <= last; i++)
249 {
250 if(bank->base >= PIC32MX_KSEG1_PGM_FLASH)
251 target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(bank->base + bank->sectors[i].offset));
252 else
253 target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(bank->base + bank->sectors[i].offset));
254
255 status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
256
257 if( status & NVMCON_NVMERR )
258 return ERROR_FLASH_OPERATION_FAILED;
259 if( status & NVMCON_LVDERR )
260 return ERROR_FLASH_OPERATION_FAILED;
261 bank->sectors[i].is_erased = 1;
262 }
263
264 return ERROR_OK;
265 }
266
267 int pic32mx_protect(struct flash_bank_s *bank, int set, int first, int last)
268 {
269 pic32mx_flash_bank_t *pic32mx_info = NULL;
270 target_t *target = bank->target;
271 u16 prot_reg[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
272 int i, reg, bit;
273 int status;
274 u32 protection;
275
276 pic32mx_info = bank->driver_priv;
277
278 if (target->state != TARGET_HALTED)
279 {
280 LOG_ERROR("Target not halted");
281 return ERROR_TARGET_NOT_HALTED;
282 }
283
284 #if 0
285 if ((first && (first % pic32mx_info->ppage_size)) || ((last + 1) && (last + 1) % pic32mx_info->ppage_size))
286 {
287 LOG_WARNING("sector start/end incorrect - stm32 has %dK sector protection", pic32mx_info->ppage_size);
288 return ERROR_FLASH_SECTOR_INVALID;
289 }
290
291 /* medium density - each bit refers to a 4bank protection
292 * high density - each bit refers to a 2bank protection */
293 target_read_u32(target, PIC32MX_FLASH_WRPR, &protection);
294
295 prot_reg[0] = (u16)protection;
296 prot_reg[1] = (u16)(protection >> 8);
297 prot_reg[2] = (u16)(protection >> 16);
298 prot_reg[3] = (u16)(protection >> 24);
299
300 if (pic32mx_info->ppage_size == 2)
301 {
302 /* high density flash */
303
304 /* bit 7 controls sector 62 - 255 protection */
305 if (last > 61)
306 {
307 if (set)
308 prot_reg[3] &= ~(1 << 7);
309 else
310 prot_reg[3] |= (1 << 7);
311 }
312
313 if (first > 61)
314 first = 62;
315 if (last > 61)
316 last = 61;
317
318 for (i = first; i <= last; i++)
319 {
320 reg = (i / pic32mx_info->ppage_size) / 8;
321 bit = (i / pic32mx_info->ppage_size) - (reg * 8);
322
323 if( set )
324 prot_reg[reg] &= ~(1 << bit);
325 else
326 prot_reg[reg] |= (1 << bit);
327 }
328 }
329 else
330 {
331 /* medium density flash */
332 for (i = first; i <= last; i++)
333 {
334 reg = (i / pic32mx_info->ppage_size) / 8;
335 bit = (i / pic32mx_info->ppage_size) - (reg * 8);
336
337 if( set )
338 prot_reg[reg] &= ~(1 << bit);
339 else
340 prot_reg[reg] |= (1 << bit);
341 }
342 }
343
344 if ((status = pic32mx_erase_options(bank)) != ERROR_OK)
345 return status;
346
347 pic32mx_info->option_bytes.protection[0] = prot_reg[0];
348 pic32mx_info->option_bytes.protection[1] = prot_reg[1];
349 pic32mx_info->option_bytes.protection[2] = prot_reg[2];
350 pic32mx_info->option_bytes.protection[3] = prot_reg[3];
351
352 return pic32mx_write_options(bank);
353 #else
354 return ERROR_OK;
355 #endif
356 }
357
358 int pic32mx_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
359 {
360 target_t *target = bank->target;
361 u32 buffer_size = 512;
362 working_area_t *source;
363 u32 address = bank->base + offset;
364 int retval = ERROR_OK;
365 #if 0
366 pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv;
367 armv7m_algorithm_t armv7m_info;
368
369 u8 pic32mx_flash_write_code[] = {
370 /* write: */
371 0xDF, 0xF8, 0x24, 0x40, /* ldr r4, PIC32MX_FLASH_CR */
372 0x09, 0x4D, /* ldr r5, PIC32MX_FLASH_SR */
373 0x4F, 0xF0, 0x01, 0x03, /* mov r3, #1 */
374 0x23, 0x60, /* str r3, [r4, #0] */
375 0x30, 0xF8, 0x02, 0x3B, /* ldrh r3, [r0], #2 */
376 0x21, 0xF8, 0x02, 0x3B, /* strh r3, [r1], #2 */
377 /* busy: */
378 0x2B, 0x68, /* ldr r3, [r5, #0] */
379 0x13, 0xF0, 0x01, 0x0F, /* tst r3, #0x01 */
380 0xFB, 0xD0, /* beq busy */
381 0x13, 0xF0, 0x14, 0x0F, /* tst r3, #0x14 */
382 0x01, 0xD1, /* bne exit */
383 0x01, 0x3A, /* subs r2, r2, #1 */
384 0xED, 0xD1, /* bne write */
385 /* exit: */
386 0xFE, 0xE7, /* b exit */
387 0x10, 0x20, 0x02, 0x40, /* PIC32MX_FLASH_CR: .word 0x40022010 */
388 0x0C, 0x20, 0x02, 0x40 /* PIC32MX_FLASH_SR: .word 0x4002200C */
389 };
390
391 /* flash write code */
392 if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code), &pic32mx_info->write_algorithm) != ERROR_OK)
393 {
394 LOG_WARNING("no working area available, can't do block memory writes");
395 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
396 };
397
398 if ((retval=target_write_buffer(target, pic32mx_info->write_algorithm->address, sizeof(pic32mx_flash_write_code), pic32mx_flash_write_code))!=ERROR_OK)
399 return retval;
400 #endif
401
402 /* memory buffer */
403 if (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
404 {
405 #if 0
406 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
407 if (pic32mx_info->write_algorithm)
408 target_free_working_area(target, pic32mx_info->write_algorithm);
409 #endif
410
411 LOG_WARNING("no large enough working area available, can't do block memory writes");
412 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
413 }
414
415 while (count >= buffer_size/4)
416 {
417 u32 status;
418
419 if ((retval = target_write_buffer(target, source->address, buffer_size, buffer))!=ERROR_OK) {
420 LOG_ERROR("Failed to write row buffer (%d words) to RAM", buffer_size/4);
421 break;
422 }
423
424 #if 0
425 buf_set_u32(reg_params[0].value, 0, 32, source->address);
426 buf_set_u32(reg_params[1].value, 0, 32, address);
427 buf_set_u32(reg_params[2].value, 0, 32, buffer_size/4);
428
429 if ((retval = target->type->run_algorithm(target, 0, NULL, 4, reg_params, pic32mx_info->write_algorithm->address, \
430 pic32mx_info->write_algorithm->address + (sizeof(pic32mx_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK)
431 {
432 LOG_ERROR("error executing pic32mx flash write algorithm");
433 retval = ERROR_FLASH_OPERATION_FAILED;
434 break;
435 }
436
437 if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14)
438 {
439 retval = ERROR_FLASH_OPERATION_FAILED;
440 break;
441 }
442 #endif
443 status = pic32mx_write_row(bank, address, source->address);
444 if( status & NVMCON_NVMERR ) {
445 LOG_ERROR("Flash write error NVMERR (status=0x%08x)", status);
446 retval = ERROR_FLASH_OPERATION_FAILED;
447 break;
448 }
449 if( status & NVMCON_LVDERR ) {
450 LOG_ERROR("Flash write error LVDERR (status=0x%08x)", status);
451 retval = ERROR_FLASH_OPERATION_FAILED;
452 break;
453 }
454
455 buffer += buffer_size;
456 address += buffer_size;
457 count -= buffer_size/4;
458 }
459
460 target_free_working_area(target, source);
461
462 while(count > 0)
463 {
464 u32 status;
465
466 status = pic32mx_write_word(bank, address, *(u32*)buffer);
467 if( status & NVMCON_NVMERR ) {
468 LOG_ERROR("Flash write error NVMERR (status=0x%08x)", status);
469 retval = ERROR_FLASH_OPERATION_FAILED;
470 break;
471 }
472 if( status & NVMCON_LVDERR ) {
473 LOG_ERROR("Flash write error LVDERR (status=0x%08x)", status);
474 retval = ERROR_FLASH_OPERATION_FAILED;
475 break;
476 }
477
478 buffer += 4;
479 address += 4;
480 count--;
481 }
482
483 return retval;
484 }
485
486 int pic32mx_write_word(struct flash_bank_s *bank, u32 address, u32 word)
487 {
488 target_t *target = bank->target;
489
490 if(bank->base >= PIC32MX_KSEG1_PGM_FLASH)
491 target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(address));
492 else
493 target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(address));
494 target_write_u32(target, PIC32MX_NVMDATA, word);
495
496 return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5);
497 }
498
499 /*
500 * Write a 128 word (512 byte) row to flash address from RAM srcaddr.
501 */
502 int pic32mx_write_row(struct flash_bank_s *bank, u32 address, u32 srcaddr)
503 {
504 target_t *target = bank->target;
505
506 LOG_DEBUG("addr: 0x%08x srcaddr: 0x%08x", address, srcaddr);
507
508 if(address >= PIC32MX_KSEG1_PGM_FLASH)
509 target_write_u32(target, PIC32MX_NVMADDR, KS1Virt2Phys(address));
510 else
511 target_write_u32(target, PIC32MX_NVMADDR, KS0Virt2Phys(address));
512 if(srcaddr >= PIC32MX_KSEG1_RAM)
513 target_write_u32(target, PIC32MX_NVMSRCADDR, KS1Virt2Phys(srcaddr));
514 else
515 target_write_u32(target, PIC32MX_NVMSRCADDR, KS0Virt2Phys(srcaddr));
516
517 return pic32mx_nvm_exec(bank, NVMCON_OP_ROW_PROG, 100);
518 }
519
520 int pic32mx_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
521 {
522 u32 words_remaining = (count / 4);
523 u32 bytes_remaining = (count & 0x00000003);
524 u32 address = bank->base + offset;
525 u32 bytes_written = 0;
526 u32 status;
527 u32 retval;
528
529 if (bank->target->state != TARGET_HALTED)
530 {
531 LOG_ERROR("Target not halted");
532 return ERROR_TARGET_NOT_HALTED;
533 }
534
535 if (offset & 0x3)
536 {
537 LOG_WARNING("offset 0x%x breaks required 4-byte alignment", offset);
538 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
539 }
540
541 /* multiple words (4-byte) to be programmed? */
542 if (words_remaining > 0)
543 {
544 /* try using a block write */
545 if ((retval = pic32mx_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
546 {
547 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
548 {
549 /* if block write failed (no sufficient working area),
550 * we use normal (slow) single dword accesses */
551 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
552 }
553 else if (retval == ERROR_FLASH_OPERATION_FAILED)
554 {
555 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
556 return ERROR_FLASH_OPERATION_FAILED;
557 }
558 }
559 else
560 {
561 buffer += words_remaining * 4;
562 address += words_remaining * 4;
563 words_remaining = 0;
564 }
565 }
566
567 while (words_remaining > 0)
568 {
569 status = pic32mx_write_word(bank, address, *(u32*)(buffer + bytes_written));
570
571 if( status & NVMCON_NVMERR )
572 return ERROR_FLASH_OPERATION_FAILED;
573 if( status & NVMCON_LVDERR )
574 return ERROR_FLASH_OPERATION_FAILED;
575
576 bytes_written += 4;
577 words_remaining--;
578 address += 4;
579 }
580
581 if (bytes_remaining)
582 {
583 u8 last_word[4] = {0xff, 0xff, 0xff, 0xff};
584 int i = 0;
585
586 while(bytes_remaining > 0)
587 {
588 /* Assumes little endian */
589 last_word[i++] = *(buffer + bytes_written);
590 bytes_remaining--;
591 bytes_written++;
592 }
593
594 status = pic32mx_write_word(bank, address, *(u32*)last_word);
595
596 if( status & NVMCON_NVMERR )
597 return ERROR_FLASH_OPERATION_FAILED;
598 if( status & NVMCON_LVDERR )
599 return ERROR_FLASH_OPERATION_FAILED;
600 }
601
602 return ERROR_OK;
603 }
604
605 int pic32mx_probe(struct flash_bank_s *bank)
606 {
607 target_t *target = bank->target;
608 pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv;
609 mips32_common_t *mips32 = target->arch_info;
610 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
611 int i;
612 u16 num_pages;
613 u32 device_id;
614 int page_size;
615
616 pic32mx_info->probed = 0;
617
618 device_id = ejtag_info->idcode;
619 LOG_INFO( "device id = 0x%08x (manuf 0x%03x dev 0x%02x, ver 0x%03x)", device_id, (device_id>>1)&0x7ff, (device_id>>12)&0xff, (device_id>>20)&0xfff );
620
621 if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) {
622 LOG_WARNING( "Cannot identify target as a PIC32MX family." );
623 return ERROR_FLASH_OPERATION_FAILED;
624 }
625
626 page_size = 4096;
627 if(bank->base == PIC32MX_KSEG1_BOOT_FLASH || bank->base == 1) {
628 /* 0xBFC00000: Boot flash size fixed at 12k */
629 num_pages = 12;
630 } else {
631 /* 0xBD000000: Program flash size varies with device */
632 for(i=0; pic32mx_devs[i].name != NULL; i++)
633 if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
634 num_pages = pic32mx_devs[i].pfm_size;
635 break;
636 }
637 if(pic32mx_devs[i].name == NULL) {
638 LOG_WARNING( "Cannot identify target as a PIC32MX family." );
639 return ERROR_FLASH_OPERATION_FAILED;
640 }
641 }
642
643 #if 0
644 if (bank->target->state != TARGET_HALTED)
645 {
646 LOG_ERROR("Target not halted");
647 return ERROR_TARGET_NOT_HALTED;
648 }
649
650 /* get flash size from target */
651 if (target_read_u16(target, 0x1FFFF7E0, &num_pages) != ERROR_OK)
652 {
653 /* failed reading flash size, default to max target family */
654 num_pages = 0xffff;
655 }
656 #endif
657
658 LOG_INFO( "flash size = %dkbytes", num_pages );
659
660 /* calculate numbers of pages */
661 num_pages /= (page_size / 1024);
662
663 if(bank->base == 0) bank->base = PIC32MX_KSEG1_PGM_FLASH;
664 if(bank->base == 1) bank->base = PIC32MX_KSEG1_BOOT_FLASH;
665 bank->size = (num_pages * page_size);
666 bank->num_sectors = num_pages;
667 bank->chip_width = 4;
668 bank->bus_width = 4;
669 bank->sectors = malloc(sizeof(flash_sector_t) * num_pages);
670
671 for (i = 0; i < num_pages; i++)
672 {
673 bank->sectors[i].offset = i * page_size;
674 bank->sectors[i].size = page_size;
675 bank->sectors[i].is_erased = -1;
676 bank->sectors[i].is_protected = 1;
677 }
678
679 pic32mx_info->probed = 1;
680
681 return ERROR_OK;
682 }
683
684 int pic32mx_auto_probe(struct flash_bank_s *bank)
685 {
686 pic32mx_flash_bank_t *pic32mx_info = bank->driver_priv;
687 if (pic32mx_info->probed)
688 return ERROR_OK;
689 return pic32mx_probe(bank);
690 }
691
692 int pic32mx_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
693 {
694 return ERROR_OK;
695 }
696
697 int pic32mx_info(struct flash_bank_s *bank, char *buf, int buf_size)
698 {
699 target_t *target = bank->target;
700 mips32_common_t *mips32 = target->arch_info;
701 mips_ejtag_t *ejtag_info = &mips32->ejtag_info;
702 u32 device_id;
703 int printed, i;
704
705 device_id = ejtag_info->idcode;
706
707 if(((device_id>>1)&0x7ff) != PIC32MX_MANUF_ID) {
708 snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family (manufacturer 0x%03d != 0x%03d)\n", (device_id>>1)&0x7ff, PIC32MX_MANUF_ID);
709 return ERROR_FLASH_OPERATION_FAILED;
710 }
711 for(i=0; pic32mx_devs[i].name != NULL; i++)
712 if(pic32mx_devs[i].devid == ((device_id >> 12) & 0xff)) {
713 printed = snprintf(buf, buf_size, "PIC32MX%s", pic32mx_devs[i].name);
714 break;
715 }
716 if(pic32mx_devs[i].name == NULL) {
717 snprintf(buf, buf_size, "Cannot identify target as a PIC32MX family\n");
718 return ERROR_FLASH_OPERATION_FAILED;
719 }
720 buf += printed;
721 buf_size -= printed;
722 printed = snprintf(buf, buf_size, " Ver: 0x%03x", (device_id>>20)&0xfff);
723
724 return ERROR_OK;
725 }
726
727 #if 0
728 int pic32mx_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
729 {
730 flash_bank_t *bank;
731 target_t *target = NULL;
732 pic32mx_flash_bank_t *pic32mx_info = NULL;
733
734 if (argc < 1)
735 {
736 command_print(cmd_ctx, "pic32mx lock <bank>");
737 return ERROR_OK;
738 }
739
740 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
741 if (!bank)
742 {
743 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
744 return ERROR_OK;
745 }
746
747 pic32mx_info = bank->driver_priv;
748
749 target = bank->target;
750
751 if (target->state != TARGET_HALTED)
752 {
753 LOG_ERROR("Target not halted");
754 return ERROR_TARGET_NOT_HALTED;
755 }
756
757 if (pic32mx_erase_options(bank) != ERROR_OK)
758 {
759 command_print(cmd_ctx, "pic32mx failed to erase options");
760 return ERROR_OK;
761 }
762
763 /* set readout protection */
764 pic32mx_info->option_bytes.RDP = 0;
765
766 if (pic32mx_write_options(bank) != ERROR_OK)
767 {
768 command_print(cmd_ctx, "pic32mx failed to lock device");
769 return ERROR_OK;
770 }
771
772 command_print(cmd_ctx, "pic32mx locked");
773
774 return ERROR_OK;
775 }
776
777 int pic32mx_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
778 {
779 flash_bank_t *bank;
780 target_t *target = NULL;
781 pic32mx_flash_bank_t *pic32mx_info = NULL;
782
783 if (argc < 1)
784 {
785 command_print(cmd_ctx, "pic32mx unlock <bank>");
786 return ERROR_OK;
787 }
788
789 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
790 if (!bank)
791 {
792 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
793 return ERROR_OK;
794 }
795
796 pic32mx_info = bank->driver_priv;
797
798 target = bank->target;
799
800 if (target->state != TARGET_HALTED)
801 {
802 LOG_ERROR("Target not halted");
803 return ERROR_TARGET_NOT_HALTED;
804 }
805
806 if (pic32mx_erase_options(bank) != ERROR_OK)
807 {
808 command_print(cmd_ctx, "pic32mx failed to unlock device");
809 return ERROR_OK;
810 }
811
812 if (pic32mx_write_options(bank) != ERROR_OK)
813 {
814 command_print(cmd_ctx, "pic32mx failed to lock device");
815 return ERROR_OK;
816 }
817
818 command_print(cmd_ctx, "pic32mx unlocked");
819
820 return ERROR_OK;
821 }
822 #endif
823
824 int pic32mx_chip_erase(struct flash_bank_s *bank)
825 {
826 target_t *target = bank->target;
827 u32 status;
828
829 if (target->state != TARGET_HALTED)
830 {
831 LOG_ERROR("Target not halted");
832 return ERROR_TARGET_NOT_HALTED;
833 }
834
835 LOG_INFO("PIC32MX chip erase called");
836
837 #if 0
838 /* unlock option flash registers */
839 target_write_u32(target, PIC32MX_FLASH_KEYR, KEY1);
840 target_write_u32(target, PIC32MX_FLASH_KEYR, KEY2);
841
842 /* chip erase flash memory */
843 target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER);
844 target_write_u32(target, PIC32MX_FLASH_CR, FLASH_MER|FLASH_STRT);
845
846 status = pic32mx_wait_status_busy(bank, 10);
847
848 target_write_u32(target, PIC32MX_FLASH_CR, FLASH_LOCK);
849
850 if( status & FLASH_WRPRTERR )
851 {
852 LOG_ERROR("pic32mx device protected");
853 return ERROR_OK;
854 }
855
856 if( status & FLASH_PGERR )
857 {
858 LOG_ERROR("pic32mx device programming failed");
859 return ERROR_OK;
860 }
861 #endif
862
863 return ERROR_OK;
864 }
865
866 int pic32mx_handle_chip_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
867 {
868 flash_bank_t *bank;
869 int i;
870
871 #if 0
872 if (argc != 0)
873 {
874 command_print(cmd_ctx, "pic32mx chip_erase");
875 return ERROR_OK;
876 }
877
878 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
879 if (!bank)
880 {
881 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
882 return ERROR_OK;
883 }
884
885 if (pic32mx_chip_erase(bank) == ERROR_OK)
886 {
887 /* set all sectors as erased */
888 for (i = 0; i < bank->num_sectors; i++)
889 {
890 bank->sectors[i].is_erased = 1;
891 }
892
893 command_print(cmd_ctx, "pic32mx chip erase complete");
894 }
895 else
896 {
897 command_print(cmd_ctx, "pic32mx chip erase failed");
898 }
899 #endif
900
901 return ERROR_OK;
902 }
903
904 int pic32mx_handle_pgm_word_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
905 {
906 flash_bank_t *bank;
907 u32 address, value;
908 int status, res;
909
910 if (argc != 3)
911 {
912 command_print(cmd_ctx, "pic32mx pgm_word <addr> <value> <bank>");
913 return ERROR_OK;
914 }
915
916 address = strtoul(args[0], NULL, 0);
917 value = strtoul(args[1], NULL, 0);
918
919 bank = get_flash_bank_by_num(strtoul(args[2], NULL, 0));
920 if (!bank)
921 {
922 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[2]);
923 return ERROR_OK;
924 }
925 if (address < bank->base || address >= (bank->base+bank->size))
926 {
927 command_print(cmd_ctx, "flash address '%s' is out of bounds", args[0]);
928 return ERROR_OK;
929 }
930
931 res = ERROR_OK;
932 status = pic32mx_write_word(bank, address, value);
933 if( status & NVMCON_NVMERR )
934 res = ERROR_FLASH_OPERATION_FAILED;
935 if( status & NVMCON_LVDERR )
936 res = ERROR_FLASH_OPERATION_FAILED;
937
938 if (res == ERROR_OK)
939 command_print(cmd_ctx, "pic32mx pgm word complete");
940 else
941 command_print(cmd_ctx, "pic32mx pgm word failed (status=0x%x)", status);
942
943 return ERROR_OK;
944 }

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)