jtag: linuxgpiod: drop extra parenthesis
[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 bool 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 = false;
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 unsigned int s, num_pages;
275
276 if (target->state != TARGET_HALTED) {
277 LOG_ERROR("Target not halted");
278 return ERROR_TARGET_NOT_HALTED;
279 }
280
281 switch (pic32mx_info->dev_type) {
282 case MX_1XX_2XX:
283 case MX_17X_27X:
284 config0_address = PIC32MX_DEVCFG0_1XX_2XX;
285 break;
286 default:
287 config0_address = PIC32MX_DEVCFG0;
288 break;
289 }
290
291 target_read_u32(target, config0_address, &devcfg0);
292
293 if ((devcfg0 & (1 << 28)) == 0) /* code protect bit */
294 num_pages = 0xffff; /* All pages protected */
295 else if (virt2phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
296 if (devcfg0 & (1 << 24))
297 num_pages = 0; /* All pages unprotected */
298 else
299 num_pages = 0xffff; /* All pages protected */
300 } else {
301 /* pgm flash */
302 switch (pic32mx_info->dev_type) {
303 case MX_1XX_2XX:
304 num_pages = (~devcfg0 >> 10) & 0x7f;
305 break;
306 case MX_17X_27X:
307 num_pages = (~devcfg0 >> 10) & 0x1ff;
308 break;
309 default:
310 num_pages = (~devcfg0 >> 12) & 0xff;
311 break;
312 }
313 }
314
315 for (s = 0; s < bank->num_sectors && s < num_pages; s++)
316 bank->sectors[s].is_protected = 1;
317 for (; s < bank->num_sectors; s++)
318 bank->sectors[s].is_protected = 0;
319
320 return ERROR_OK;
321 }
322
323 static int pic32mx_erase(struct flash_bank *bank, unsigned int first,
324 unsigned int last)
325 {
326 struct target *target = bank->target;
327 uint32_t status;
328
329 if (bank->target->state != TARGET_HALTED) {
330 LOG_ERROR("Target not halted");
331 return ERROR_TARGET_NOT_HALTED;
332 }
333
334 if ((first == 0) && (last == (bank->num_sectors - 1))
335 && (virt2phys(bank->base) == PIC32MX_PHYS_PGM_FLASH)) {
336 /* this will only erase the Program Flash (PFM), not the Boot Flash (BFM)
337 * we need to use the MTAP to perform a full erase */
338 LOG_DEBUG("Erasing entire program flash");
339 status = pic32mx_nvm_exec(bank, NVMCON_OP_PFM_ERASE, 50);
340 if (status & NVMCON_NVMERR)
341 return ERROR_FLASH_OPERATION_FAILED;
342 if (status & NVMCON_LVDERR)
343 return ERROR_FLASH_OPERATION_FAILED;
344 return ERROR_OK;
345 }
346
347 for (unsigned int i = first; i <= last; i++) {
348 target_write_u32(target, PIC32MX_NVMADDR, virt2phys(bank->base + bank->sectors[i].offset));
349
350 status = pic32mx_nvm_exec(bank, NVMCON_OP_PAGE_ERASE, 10);
351
352 if (status & NVMCON_NVMERR)
353 return ERROR_FLASH_OPERATION_FAILED;
354 if (status & NVMCON_LVDERR)
355 return ERROR_FLASH_OPERATION_FAILED;
356 }
357
358 return ERROR_OK;
359 }
360
361 static int pic32mx_protect(struct flash_bank *bank, int set, unsigned int first,
362 unsigned int last)
363 {
364 struct target *target = bank->target;
365
366 if (target->state != TARGET_HALTED) {
367 LOG_ERROR("Target not halted");
368 return ERROR_TARGET_NOT_HALTED;
369 }
370
371 return ERROR_OK;
372 }
373
374 /* see contrib/loaders/flash/pic32mx.s for src */
375
376 static uint32_t pic32mx_flash_write_code[] = {
377 /* write: */
378 0x3C08AA99, /* lui $t0, 0xaa99 */
379 0x35086655, /* ori $t0, 0x6655 */
380 0x3C095566, /* lui $t1, 0x5566 */
381 0x352999AA, /* ori $t1, 0x99aa */
382 0x3C0ABF80, /* lui $t2, 0xbf80 */
383 0x354AF400, /* ori $t2, 0xf400 */
384 0x340B4003, /* ori $t3, $zero, 0x4003 */
385 0x340C8000, /* ori $t4, $zero, 0x8000 */
386 /* write_row: */
387 0x2CD30080, /* sltiu $s3, $a2, 128 */
388 0x16600008, /* bne $s3, $zero, write_word */
389 0x340D4000, /* ori $t5, $zero, 0x4000 */
390 0xAD450020, /* sw $a1, 32($t2) */
391 0xAD440040, /* sw $a0, 64($t2) */
392 0x04110016, /* bal progflash */
393 0x24840200, /* addiu $a0, $a0, 512 */
394 0x24A50200, /* addiu $a1, $a1, 512 */
395 0x1000FFF7, /* beq $zero, $zero, write_row */
396 0x24C6FF80, /* addiu $a2, $a2, -128 */
397 /* write_word: */
398 0x3C15A000, /* lui $s5, 0xa000 */
399 0x36B50000, /* ori $s5, $s5, 0x0 */
400 0x00952025, /* or $a0, $a0, $s5 */
401 0x10000008, /* beq $zero, $zero, next_word */
402 0x340B4001, /* ori $t3, $zero, 0x4001 */
403 /* prog_word: */
404 0x8C940000, /* lw $s4, 0($a0) */
405 0xAD540030, /* sw $s4, 48($t2) */
406 0xAD450020, /* sw $a1, 32($t2) */
407 0x04110009, /* bal progflash */
408 0x24840004, /* addiu $a0, $a0, 4 */
409 0x24A50004, /* addiu $a1, $a1, 4 */
410 0x24C6FFFF, /* addiu $a2, $a2, -1 */
411 /* next_word: */
412 0x14C0FFF8, /* bne $a2, $zero, prog_word */
413 0x00000000, /* nop */
414 /* done: */
415 0x10000002, /* beq $zero, $zero, exit */
416 0x24040000, /* addiu $a0, $zero, 0 */
417 /* error: */
418 0x26240000, /* addiu $a0, $s1, 0 */
419 /* exit: */
420 0x7000003F, /* sdbbp */
421 /* progflash: */
422 0xAD4B0000, /* sw $t3, 0($t2) */
423 0xAD480010, /* sw $t0, 16($t2) */
424 0xAD490010, /* sw $t1, 16($t2) */
425 0xAD4C0008, /* sw $t4, 8($t2) */
426 /* waitflash: */
427 0x8D500000, /* lw $s0, 0($t2) */
428 0x020C8024, /* and $s0, $s0, $t4 */
429 0x1600FFFD, /* bne $s0, $zero, waitflash */
430 0x00000000, /* nop */
431 0x00000000, /* nop */
432 0x00000000, /* nop */
433 0x00000000, /* nop */
434 0x00000000, /* nop */
435 0x8D510000, /* lw $s1, 0($t2) */
436 0x30113000, /* andi $s1, $zero, 0x3000 */
437 0x1620FFEF, /* bne $s1, $zero, error */
438 0xAD4D0004, /* sw $t5, 4($t2) */
439 0x03E00008, /* jr $ra */
440 0x00000000 /* nop */
441 };
442
443 static int pic32mx_write_block(struct flash_bank *bank, const uint8_t *buffer,
444 uint32_t offset, uint32_t count)
445 {
446 struct target *target = bank->target;
447 uint32_t buffer_size = 16384;
448 struct working_area *write_algorithm;
449 struct working_area *source;
450 uint32_t address = bank->base + offset;
451 struct reg_param reg_params[3];
452 uint32_t row_size;
453 int retval = ERROR_OK;
454
455 struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
456 struct mips32_algorithm mips32_info;
457
458 /* flash write code */
459 if (target_alloc_working_area(target, sizeof(pic32mx_flash_write_code),
460 &write_algorithm) != ERROR_OK) {
461 LOG_WARNING("no working area available, can't do block memory writes");
462 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
463 }
464
465 /* Change values for counters and row size, depending on variant */
466 switch (pic32mx_info->dev_type) {
467 case MX_1XX_2XX:
468 case MX_17X_27X:
469 /* 128 byte row */
470 pic32mx_flash_write_code[8] = 0x2CD30020;
471 pic32mx_flash_write_code[14] = 0x24840080;
472 pic32mx_flash_write_code[15] = 0x24A50080;
473 pic32mx_flash_write_code[17] = 0x24C6FFE0;
474 row_size = 128;
475 break;
476 default:
477 /* 512 byte row */
478 pic32mx_flash_write_code[8] = 0x2CD30080;
479 pic32mx_flash_write_code[14] = 0x24840200;
480 pic32mx_flash_write_code[15] = 0x24A50200;
481 pic32mx_flash_write_code[17] = 0x24C6FF80;
482 row_size = 512;
483 break;
484 }
485
486 uint8_t code[sizeof(pic32mx_flash_write_code)];
487 target_buffer_set_u32_array(target, code, ARRAY_SIZE(pic32mx_flash_write_code),
488 pic32mx_flash_write_code);
489 retval = target_write_buffer(target, write_algorithm->address, sizeof(code), code);
490 if (retval != ERROR_OK)
491 return retval;
492
493 /* memory buffer */
494 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
495 buffer_size /= 2;
496 if (buffer_size <= 256) {
497 /* we already allocated the writing code, but failed to get a
498 * buffer, free the algorithm */
499 target_free_working_area(target, write_algorithm);
500
501 LOG_WARNING("no large enough working area available, can't do block memory writes");
502 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
503 }
504 }
505
506 mips32_info.common_magic = MIPS32_COMMON_MAGIC;
507 mips32_info.isa_mode = MIPS32_ISA_MIPS32;
508
509 init_reg_param(&reg_params[0], "r4", 32, PARAM_IN_OUT);
510 init_reg_param(&reg_params[1], "r5", 32, PARAM_OUT);
511 init_reg_param(&reg_params[2], "r6", 32, PARAM_OUT);
512
513 int row_offset = offset % row_size;
514 uint8_t *new_buffer = NULL;
515 if (row_offset && (count >= (row_size / 4))) {
516 new_buffer = malloc(buffer_size);
517 if (!new_buffer) {
518 LOG_ERROR("Out of memory");
519 return ERROR_FAIL;
520 }
521 memset(new_buffer, 0xff, row_offset);
522 address -= row_offset;
523 } else
524 row_offset = 0;
525
526 while (count > 0) {
527 uint32_t status;
528 uint32_t thisrun_count;
529
530 if (row_offset) {
531 thisrun_count = (count > ((buffer_size - row_offset) / 4)) ?
532 ((buffer_size - row_offset) / 4) : count;
533
534 memcpy(new_buffer + row_offset, buffer, thisrun_count * 4);
535
536 retval = target_write_buffer(target, source->address,
537 row_offset + thisrun_count * 4, new_buffer);
538 if (retval != ERROR_OK)
539 break;
540 } else {
541 thisrun_count = (count > (buffer_size / 4)) ?
542 (buffer_size / 4) : count;
543
544 retval = target_write_buffer(target, source->address,
545 thisrun_count * 4, buffer);
546 if (retval != ERROR_OK)
547 break;
548 }
549
550 buf_set_u32(reg_params[0].value, 0, 32, virt2phys(source->address));
551 buf_set_u32(reg_params[1].value, 0, 32, virt2phys(address));
552 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count + row_offset / 4);
553
554 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
555 write_algorithm->address,
556 0, 10000, &mips32_info);
557 if (retval != ERROR_OK) {
558 LOG_ERROR("error executing pic32mx flash write algorithm");
559 retval = ERROR_FLASH_OPERATION_FAILED;
560 break;
561 }
562
563 status = buf_get_u32(reg_params[0].value, 0, 32);
564
565 if (status & NVMCON_NVMERR) {
566 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
567 retval = ERROR_FLASH_OPERATION_FAILED;
568 break;
569 }
570
571 if (status & NVMCON_LVDERR) {
572 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
573 retval = ERROR_FLASH_OPERATION_FAILED;
574 break;
575 }
576
577 buffer += thisrun_count * 4;
578 address += thisrun_count * 4;
579 count -= thisrun_count;
580 if (row_offset) {
581 address += row_offset;
582 row_offset = 0;
583 }
584 }
585
586 target_free_working_area(target, source);
587 target_free_working_area(target, write_algorithm);
588
589 destroy_reg_param(&reg_params[0]);
590 destroy_reg_param(&reg_params[1]);
591 destroy_reg_param(&reg_params[2]);
592
593 free(new_buffer);
594 return retval;
595 }
596
597 static int pic32mx_write_word(struct flash_bank *bank, uint32_t address, uint32_t word)
598 {
599 struct target *target = bank->target;
600
601 target_write_u32(target, PIC32MX_NVMADDR, virt2phys(address));
602 target_write_u32(target, PIC32MX_NVMDATA, word);
603
604 return pic32mx_nvm_exec(bank, NVMCON_OP_WORD_PROG, 5);
605 }
606
607 static int pic32mx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
608 {
609 uint32_t words_remaining = (count / 4);
610 uint32_t bytes_remaining = (count & 0x00000003);
611 uint32_t address = bank->base + offset;
612 uint32_t bytes_written = 0;
613 uint32_t status;
614 int retval;
615
616 if (bank->target->state != TARGET_HALTED) {
617 LOG_ERROR("Target not halted");
618 return ERROR_TARGET_NOT_HALTED;
619 }
620
621 LOG_DEBUG("writing to flash at address " TARGET_ADDR_FMT " at offset 0x%8.8" PRIx32
622 " count: 0x%8.8" PRIx32 "", bank->base, offset, count);
623
624 if (offset & 0x3) {
625 LOG_WARNING("offset 0x%" PRIx32 "breaks required 4-byte alignment", offset);
626 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
627 }
628
629 /* multiple words (4-byte) to be programmed? */
630 if (words_remaining > 0) {
631 /* try using a block write */
632 retval = pic32mx_write_block(bank, buffer, offset, words_remaining);
633 if (retval != ERROR_OK) {
634 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
635 /* if block write failed (no sufficient working area),
636 * we use normal (slow) single dword accesses */
637 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
638 } else if (retval == ERROR_FLASH_OPERATION_FAILED) {
639 LOG_ERROR("flash writing failed");
640 return retval;
641 }
642 } else {
643 buffer += words_remaining * 4;
644 address += words_remaining * 4;
645 words_remaining = 0;
646 }
647 }
648
649 while (words_remaining > 0) {
650 uint32_t value;
651 memcpy(&value, buffer + bytes_written, sizeof(uint32_t));
652
653 status = pic32mx_write_word(bank, address, value);
654
655 if (status & NVMCON_NVMERR) {
656 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
657 return ERROR_FLASH_OPERATION_FAILED;
658 }
659
660 if (status & NVMCON_LVDERR) {
661 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
662 return ERROR_FLASH_OPERATION_FAILED;
663 }
664
665 bytes_written += 4;
666 words_remaining--;
667 address += 4;
668 }
669
670 if (bytes_remaining) {
671 uint32_t value = 0xffffffff;
672 memcpy(&value, buffer + bytes_written, bytes_remaining);
673
674 status = pic32mx_write_word(bank, address, value);
675
676 if (status & NVMCON_NVMERR) {
677 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32 ")", status);
678 return ERROR_FLASH_OPERATION_FAILED;
679 }
680
681 if (status & NVMCON_LVDERR) {
682 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32 ")", status);
683 return ERROR_FLASH_OPERATION_FAILED;
684 }
685 }
686
687 return ERROR_OK;
688 }
689
690 static int pic32mx_probe(struct flash_bank *bank)
691 {
692 struct target *target = bank->target;
693 struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
694 struct mips32_common *mips32 = target->arch_info;
695 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
696 int i;
697 uint32_t num_pages = 0;
698 uint32_t device_id;
699 int page_size;
700
701 pic32mx_info->probed = false;
702
703 device_id = ejtag_info->idcode;
704 LOG_INFO("device id = 0x%08" PRIx32 " (manuf 0x%03x dev 0x%04x, ver 0x%02x)",
705 device_id,
706 (unsigned)((device_id >> 1) & 0x7ff),
707 (unsigned)((device_id >> 12) & 0xffff),
708 (unsigned)((device_id >> 28) & 0xf));
709
710 if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
711 LOG_WARNING("Cannot identify target as a PIC32MX family.");
712 return ERROR_FLASH_OPERATION_FAILED;
713 }
714
715 /* Check for PIC32mx1xx/2xx */
716 for (i = 0; pic32mx_devs[i].name; i++) {
717 if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
718 if ((pic32mx_devs[i].name[0] == '1') || (pic32mx_devs[i].name[0] == '2'))
719 pic32mx_info->dev_type = (pic32mx_devs[i].name[1] == '7') ? MX_17X_27X : MX_1XX_2XX;
720 break;
721 }
722 }
723
724 switch (pic32mx_info->dev_type) {
725 case MX_1XX_2XX:
726 case MX_17X_27X:
727 page_size = 1024;
728 break;
729 default:
730 page_size = 4096;
731 break;
732 }
733
734 if (virt2phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) {
735 /* 0x1FC00000: Boot flash size */
736 #if 0
737 /* for some reason this register returns 8k for the boot bank size
738 * this does not match the docs, so for now set the boot bank at a
739 * fixed 12k */
740 if (target_read_u32(target, PIC32MX_BMXBOOTSZ, &num_pages) != ERROR_OK) {
741 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 12k flash");
742 num_pages = (12 * 1024);
743 }
744 #else
745 /* fixed 12k boot bank - see comments above */
746 switch (pic32mx_info->dev_type) {
747 case MX_1XX_2XX:
748 case MX_17X_27X:
749 num_pages = (3 * 1024);
750 break;
751 default:
752 num_pages = (12 * 1024);
753 break;
754 }
755 #endif
756 } else {
757 /* read the flash size from the device */
758 if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) {
759 switch (pic32mx_info->dev_type) {
760 case MX_1XX_2XX:
761 case MX_17X_27X:
762 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash");
763 num_pages = (32 * 1024);
764 break;
765 default:
766 LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash");
767 num_pages = (512 * 1024);
768 break;
769 }
770 }
771 }
772
773 LOG_INFO("flash size = %" PRIu32 "kbytes", num_pages / 1024);
774
775 free(bank->sectors);
776
777 /* calculate numbers of pages */
778 num_pages /= page_size;
779 bank->size = (num_pages * page_size);
780 bank->num_sectors = num_pages;
781 bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
782
783 for (i = 0; i < (int)num_pages; i++) {
784 bank->sectors[i].offset = i * page_size;
785 bank->sectors[i].size = page_size;
786 bank->sectors[i].is_erased = -1;
787 bank->sectors[i].is_protected = 1;
788 }
789
790 pic32mx_info->probed = true;
791
792 return ERROR_OK;
793 }
794
795 static int pic32mx_auto_probe(struct flash_bank *bank)
796 {
797 struct pic32mx_flash_bank *pic32mx_info = bank->driver_priv;
798 if (pic32mx_info->probed)
799 return ERROR_OK;
800 return pic32mx_probe(bank);
801 }
802
803 static int pic32mx_info(struct flash_bank *bank, struct command_invocation *cmd)
804 {
805 struct target *target = bank->target;
806 struct mips32_common *mips32 = target->arch_info;
807 struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
808 uint32_t device_id;
809
810 device_id = ejtag_info->idcode;
811
812 if (((device_id >> 1) & 0x7ff) != PIC32MX_MANUF_ID) {
813 command_print_sameline(cmd,
814 "Cannot identify target as a PIC32MX family (manufacturer 0x%03x != 0x%03x)\n",
815 (unsigned)((device_id >> 1) & 0x7ff),
816 PIC32MX_MANUF_ID);
817 return ERROR_FLASH_OPERATION_FAILED;
818 }
819
820 int i;
821 for (i = 0; pic32mx_devs[i].name; i++) {
822 if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) {
823 command_print_sameline(cmd, "PIC32MX%s", pic32mx_devs[i].name);
824 break;
825 }
826 }
827
828 if (!pic32mx_devs[i].name)
829 command_print_sameline(cmd, "Unknown");
830
831 command_print_sameline(cmd, " Ver: 0x%02x",
832 (unsigned)((device_id >> 28) & 0xf));
833
834 return ERROR_OK;
835 }
836
837 COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
838 {
839 uint32_t address, value;
840 int status, res;
841
842 if (CMD_ARGC != 3)
843 return ERROR_COMMAND_SYNTAX_ERROR;
844
845 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
846 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
847
848 struct flash_bank *bank;
849 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 2, &bank);
850 if (retval != ERROR_OK)
851 return retval;
852
853 if (address < bank->base || address >= (bank->base + bank->size)) {
854 command_print(CMD, "flash address '%s' is out of bounds", CMD_ARGV[0]);
855 return ERROR_OK;
856 }
857
858 res = ERROR_OK;
859 status = pic32mx_write_word(bank, address, value);
860 if (status & NVMCON_NVMERR)
861 res = ERROR_FLASH_OPERATION_FAILED;
862 if (status & NVMCON_LVDERR)
863 res = ERROR_FLASH_OPERATION_FAILED;
864
865 if (res == ERROR_OK)
866 command_print(CMD, "pic32mx pgm word complete");
867 else
868 command_print(CMD, "pic32mx pgm word failed (status = 0x%x)", status);
869
870 return ERROR_OK;
871 }
872
873 COMMAND_HANDLER(pic32mx_handle_unlock_command)
874 {
875 struct target *target = NULL;
876 struct mips_m4k_common *mips_m4k;
877 struct mips_ejtag *ejtag_info;
878 int timeout = 10;
879
880 if (CMD_ARGC < 1) {
881 command_print(CMD, "pic32mx unlock <bank>");
882 return ERROR_COMMAND_SYNTAX_ERROR;
883 }
884
885 struct flash_bank *bank;
886 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
887 if (retval != ERROR_OK)
888 return retval;
889
890 target = bank->target;
891 mips_m4k = target_to_m4k(target);
892 ejtag_info = &mips_m4k->mips32.ejtag_info;
893
894 /* we have to use the MTAP to perform a full erase */
895 mips_ejtag_set_instr(ejtag_info, MTAP_SW_MTAP);
896 mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND);
897
898 /* first check status of device */
899 uint8_t mchip_cmd = MCHP_STATUS;
900 mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
901 if (mchip_cmd & (1 << 7)) {
902 /* device is not locked */
903 command_print(CMD, "pic32mx is already unlocked, erasing anyway");
904 }
905
906 /* unlock/erase device */
907 mips_ejtag_drscan_8_out(ejtag_info, MCHP_ASERT_RST);
908 jtag_add_sleep(200);
909
910 mips_ejtag_drscan_8_out(ejtag_info, MCHP_ERASE);
911
912 do {
913 mchip_cmd = MCHP_STATUS;
914 mips_ejtag_drscan_8(ejtag_info, &mchip_cmd);
915 if (timeout-- == 0) {
916 LOG_DEBUG("timeout waiting for unlock: 0x%" PRIx8 "", mchip_cmd);
917 break;
918 }
919 alive_sleep(1);
920 } while ((mchip_cmd & (1 << 2)) || (!(mchip_cmd & (1 << 3))));
921
922 mips_ejtag_drscan_8_out(ejtag_info, MCHP_DE_ASSERT_RST);
923
924 /* select ejtag tap */
925 mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP);
926
927 command_print(CMD, "pic32mx unlocked.\n"
928 "INFO: a reset or power cycle is required "
929 "for the new settings to take effect.");
930
931 return ERROR_OK;
932 }
933
934 static const struct command_registration pic32mx_exec_command_handlers[] = {
935 {
936 .name = "pgm_word",
937 .usage = "<addr> <value> <bank>",
938 .handler = pic32mx_handle_pgm_word_command,
939 .mode = COMMAND_EXEC,
940 .help = "program a word",
941 },
942 {
943 .name = "unlock",
944 .handler = pic32mx_handle_unlock_command,
945 .mode = COMMAND_EXEC,
946 .usage = "[bank_id]",
947 .help = "Unlock/Erase entire device.",
948 },
949 COMMAND_REGISTRATION_DONE
950 };
951
952 static const struct command_registration pic32mx_command_handlers[] = {
953 {
954 .name = "pic32mx",
955 .mode = COMMAND_ANY,
956 .help = "pic32mx flash command group",
957 .usage = "",
958 .chain = pic32mx_exec_command_handlers,
959 },
960 COMMAND_REGISTRATION_DONE
961 };
962
963 const struct flash_driver pic32mx_flash = {
964 .name = "pic32mx",
965 .commands = pic32mx_command_handlers,
966 .flash_bank_command = pic32mx_flash_bank_command,
967 .erase = pic32mx_erase,
968 .protect = pic32mx_protect,
969 .write = pic32mx_write,
970 .read = default_flash_read,
971 .probe = pic32mx_probe,
972 .auto_probe = pic32mx_auto_probe,
973 .erase_check = default_flash_blank_check,
974 .protect_check = pic32mx_protect_check,
975 .info = pic32mx_info,
976 .free_driver_priv = default_flash_free_driver_priv,
977 };

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)