1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2008 by John McCarthy *
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. *
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. *
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 ***************************************************************************/
32 #include <target/algorithm.h>
33 #include <target/mips32.h>
35 static const struct pic32mx_devs_s
{
66 /* flash bank pic32mx <base> <size> 0 0 <target#>
68 FLASH_BANK_COMMAND_HANDLER(pic32mx_flash_bank_command
)
70 struct pic32mx_flash_bank
*pic32mx_info
;
74 LOG_WARNING("incomplete flash_bank pic32mx configuration");
75 return ERROR_FLASH_BANK_INVALID
;
78 pic32mx_info
= malloc(sizeof(struct pic32mx_flash_bank
));
79 bank
->driver_priv
= pic32mx_info
;
81 pic32mx_info
->write_algorithm
= NULL
;
82 pic32mx_info
->probed
= 0;
87 static uint32_t pic32mx_get_flash_status(struct flash_bank
*bank
)
89 struct target
*target
= bank
->target
;
92 target_read_u32(target
, PIC32MX_NVMCON
, &status
);
97 static uint32_t pic32mx_wait_status_busy(struct flash_bank
*bank
, int timeout
)
101 /* wait for busy to clear */
102 while (((status
= pic32mx_get_flash_status(bank
)) & NVMCON_NVMWR
) && (timeout
-- > 0))
104 LOG_DEBUG("status: 0x%" PRIx32
, status
);
108 LOG_DEBUG("timeout: status: 0x%" PRIx32
, status
);
113 static int pic32mx_nvm_exec(struct flash_bank
*bank
, uint32_t op
, uint32_t timeout
)
115 struct target
*target
= bank
->target
;
118 target_write_u32(target
, PIC32MX_NVMCON
, NVMCON_NVMWREN
| op
);
120 /* unlock flash registers */
121 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY1
);
122 target_write_u32(target
, PIC32MX_NVMKEY
, NVMKEY2
);
124 /* start operation */
125 target_write_u32(target
, PIC32MX_NVMCONSET
, NVMCON_NVMWR
);
127 status
= pic32mx_wait_status_busy(bank
, timeout
);
129 /* lock flash registers */
130 target_write_u32(target
, PIC32MX_NVMCONCLR
, NVMCON_NVMWREN
);
135 static int pic32mx_protect_check(struct flash_bank
*bank
)
137 struct target
*target
= bank
->target
;
143 if (target
->state
!= TARGET_HALTED
)
145 LOG_ERROR("Target not halted");
146 return ERROR_TARGET_NOT_HALTED
;
149 target_read_u32(target
, PIC32MX_DEVCFG0
, &devcfg0
);
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
)
155 if (devcfg0
& (1 << 24))
156 num_pages
= 0; /* All pages unprotected */
158 num_pages
= 0xffff; /* All pages protected */
161 num_pages
= (~devcfg0
>> 12) & 0xff;
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;
171 static int pic32mx_erase(struct flash_bank
*bank
, int first
, int last
)
173 struct target
*target
= bank
->target
;
177 if (bank
->target
->state
!= TARGET_HALTED
)
179 LOG_ERROR("Target not halted");
180 return ERROR_TARGET_NOT_HALTED
;
183 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))
184 && (Virt2Phys(bank
->base
) == PIC32MX_PHYS_PGM_FLASH
))
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
;
197 for (i
= first
; i
<= last
; i
++)
199 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(bank
->base
+ bank
->sectors
[i
].offset
));
201 status
= pic32mx_nvm_exec(bank
, NVMCON_OP_PAGE_ERASE
, 10);
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;
213 static int pic32mx_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
215 struct pic32mx_flash_bank
*pic32mx_info
= NULL
;
216 struct target
*target
= bank
->target
;
218 pic32mx_info
= bank
->driver_priv
;
220 if (target
->state
!= TARGET_HALTED
)
222 LOG_ERROR("Target not halted");
223 return ERROR_TARGET_NOT_HALTED
;
229 static const uint32_t pic32mx_flash_write_code
[] = {
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 */
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 */
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 */
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 */
265 0x14C0FFF8, /* bne $a2, $zero, prog_word */
266 0x00000000, /* nop */
268 0x10000002, /* beq $zero, $zero, exit */
269 0x24040000, /* addiu $a0, $zero, 0 */
271 0x26240000, /* addiu $a0, $s1, 0 */
273 0x7000003F, /* sdbbp */
275 0xAD4B0000, /* sw $t3, 0($t2) */
276 0xAD480010, /* sw $t0, 16($t2) */
277 0xAD490010, /* sw $t1, 16($t2) */
278 0xAD4C0008, /* sw $t4, 8($t2) */
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 */
296 static int pic32mx_write_block(struct flash_bank
*bank
, uint8_t *buffer
,
297 uint32_t offset
, uint32_t count
)
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
;
306 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
307 struct mips32_algorithm mips32_info
;
309 /* flash write code */
310 if (target_alloc_working_area(target
, sizeof(pic32mx_flash_write_code
),
311 &pic32mx_info
->write_algorithm
) != ERROR_OK
)
313 LOG_WARNING("no working area available, can't do block memory writes");
314 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
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
)
324 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
327 if (buffer_size
<= 256)
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
);
334 LOG_WARNING("no large enough working area available, can't do block memory writes");
335 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
339 mips32_info
.common_magic
= MIPS32_COMMON_MAGIC
;
340 mips32_info
.isa_mode
= MIPS32_ISA_MIPS32
;
342 init_reg_param(®_params
[0], "a0", 32, PARAM_IN_OUT
);
343 init_reg_param(®_params
[1], "a1", 32, PARAM_OUT
);
344 init_reg_param(®_params
[2], "a2", 32, PARAM_OUT
);
349 uint32_t thisrun_count
= (count
> (buffer_size
/ 4)) ?
350 (buffer_size
/ 4) : count
;
352 if ((retval
= target_write_buffer(target
, source
->address
,
353 thisrun_count
* 4, buffer
)) != ERROR_OK
)
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
);
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
)
365 LOG_ERROR("error executing pic32mx flash write algorithm");
366 retval
= ERROR_FLASH_OPERATION_FAILED
;
370 status
= buf_get_u32(reg_params
[0].value
, 0, 32);
372 if (status
& NVMCON_NVMERR
)
374 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
375 retval
= ERROR_FLASH_OPERATION_FAILED
;
379 if (status
& NVMCON_LVDERR
)
381 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
382 retval
= ERROR_FLASH_OPERATION_FAILED
;
386 buffer
+= thisrun_count
* 4;
387 address
+= thisrun_count
* 4;
388 count
-= thisrun_count
;
391 target_free_working_area(target
, source
);
392 target_free_working_area(target
, pic32mx_info
->write_algorithm
);
394 destroy_reg_param(®_params
[0]);
395 destroy_reg_param(®_params
[1]);
396 destroy_reg_param(®_params
[2]);
401 static int pic32mx_write_word(struct flash_bank
*bank
, uint32_t address
, uint32_t word
)
403 struct target
*target
= bank
->target
;
405 target_write_u32(target
, PIC32MX_NVMADDR
, Virt2Phys(address
));
406 target_write_u32(target
, PIC32MX_NVMDATA
, word
);
408 return pic32mx_nvm_exec(bank
, NVMCON_OP_WORD_PROG
, 5);
411 static int pic32mx_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
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;
420 if (bank
->target
->state
!= TARGET_HALTED
)
422 LOG_ERROR("Target not halted");
423 return ERROR_TARGET_NOT_HALTED
;
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
);
431 LOG_WARNING("offset 0x%" PRIx32
"breaks required 4-byte alignment", offset
);
432 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
435 /* multiple words (4-byte) to be programmed? */
436 if (words_remaining
> 0)
438 /* try using a block write */
439 if ((retval
= pic32mx_write_block(bank
, buffer
, offset
, words_remaining
)) != ERROR_OK
)
441 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
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");
447 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
449 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
450 return ERROR_FLASH_OPERATION_FAILED
;
455 buffer
+= words_remaining
* 4;
456 address
+= words_remaining
* 4;
461 while (words_remaining
> 0)
464 memcpy(&value
, buffer
+ bytes_written
, sizeof(uint32_t));
466 status
= pic32mx_write_word(bank
, address
, value
);
468 if (status
& NVMCON_NVMERR
)
470 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
471 return ERROR_FLASH_OPERATION_FAILED
;
474 if (status
& NVMCON_LVDERR
)
476 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
477 return ERROR_FLASH_OPERATION_FAILED
;
487 uint32_t value
= 0xffffffff;
488 memcpy(&value
, buffer
+ bytes_written
, bytes_remaining
);
490 status
= pic32mx_write_word(bank
, address
, value
);
492 if (status
& NVMCON_NVMERR
)
494 LOG_ERROR("Flash write error NVMERR (status = 0x%08" PRIx32
")", status
);
495 return ERROR_FLASH_OPERATION_FAILED
;
498 if (status
& NVMCON_LVDERR
)
500 LOG_ERROR("Flash write error LVDERR (status = 0x%08" PRIx32
")", status
);
501 return ERROR_FLASH_OPERATION_FAILED
;
508 static int pic32mx_probe(struct flash_bank
*bank
)
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
;
515 uint32_t num_pages
= 0;
519 pic32mx_info
->probed
= 0;
521 device_id
= ejtag_info
->idcode
;
522 LOG_INFO("device id = 0x%08" PRIx32
" (manuf 0x%03x dev 0x%02x, ver 0x%02x)",
524 (unsigned)((device_id
>> 1) & 0x7ff),
525 (unsigned)((device_id
>> 12) & 0xff),
526 (unsigned)((device_id
>> 28) & 0xf));
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
;
535 if (Virt2Phys(bank
->base
) == PIC32MX_PHYS_BOOT_FLASH
)
537 /* 0x1FC00000: Boot flash size */
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
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);
547 /* fixed 12k boot bank - see comments above */
548 num_pages
= (12 * 1024);
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);
560 LOG_INFO("flash size = %dkbytes", num_pages
/ 1024);
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
);
568 for (i
= 0; i
< (int)num_pages
; i
++)
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;
576 pic32mx_info
->probed
= 1;
581 static int pic32mx_auto_probe(struct flash_bank
*bank
)
583 struct pic32mx_flash_bank
*pic32mx_info
= bank
->driver_priv
;
584 if (pic32mx_info
->probed
)
586 return pic32mx_probe(bank
);
589 static int pic32mx_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
591 struct target
*target
= bank
->target
;
592 struct mips32_common
*mips32
= target
->arch_info
;
593 struct mips_ejtag
*ejtag_info
= &mips32
->ejtag_info
;
597 device_id
= ejtag_info
->idcode
;
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),
604 return ERROR_FLASH_OPERATION_FAILED
;
607 for (i
= 0; pic32mx_devs
[i
].name
!= NULL
; i
++)
609 if (pic32mx_devs
[i
].devid
== ((device_id
>> 12) & 0xff)) {
610 printed
= snprintf(buf
, buf_size
, "PIC32MX%s", pic32mx_devs
[i
].name
);
615 if (pic32mx_devs
[i
].name
== NULL
) {
616 printed
= snprintf(buf
, buf_size
, "Unknown");
621 printed
= snprintf(buf
, buf_size
, " Ver: 0x%02x",
622 (unsigned)((device_id
>> 28) & 0xf));
627 COMMAND_HANDLER(pic32mx_handle_pgm_word_command
)
629 uint32_t address
, value
;
634 command_print(CMD_CTX
, "pic32mx pgm_word <addr> <value> <bank>");
638 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
639 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
641 struct flash_bank
*bank
;
642 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 2, &bank
);
643 if (ERROR_OK
!= retval
)
646 if (address
< bank
->base
|| address
>= (bank
->base
+ bank
->size
))
648 command_print(CMD_CTX
, "flash address '%s' is out of bounds", CMD_ARGV
[0]);
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
;
660 command_print(CMD_CTX
, "pic32mx pgm word complete");
662 command_print(CMD_CTX
, "pic32mx pgm word failed (status = 0x%x)", status
);
667 static const struct command_registration pic32mx_exec_command_handlers
[] = {
670 .handler
= pic32mx_handle_pgm_word_command
,
671 .mode
= COMMAND_EXEC
,
672 .help
= "program a word",
674 COMMAND_REGISTRATION_DONE
677 static const struct command_registration pic32mx_command_handlers
[] = {
681 .help
= "pic32mx flash command group",
682 .chain
= pic32mx_exec_command_handlers
,
684 COMMAND_REGISTRATION_DONE
687 struct flash_driver pic32mx_flash
= {
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
,