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

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)