1 /***************************************************************************
2 * Copyright (C) 2011 by James K. Larson *
3 * jlarson@pacifier.com *
5 * Copyright (C) 2013 Nemui Trinomius *
6 * nemuisan_kawausogasuki@live.jp *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
30 /* nuc1x register locations */
31 #define NUC1X_SYS_BASE 0x50000000
32 #define NUC1X_SYS_WRPROT 0x50000100
33 #define NUC1X_SYS_IPRSTC1 0x50000008
35 #define NUC1X_SYSCLK_BASE 0x50000200
36 #define NUC1X_SYSCLK_PWRCON 0x50000200
37 #define NUC1X_SYSCLK_CLKSEL0 0x50000210
38 #define NUC1X_SYSCLK_CLKDIV 0x50000218
39 #define NUC1X_SYSCLK_AHBCLK 0x50000204
41 #define NUC1X_FLASH_BASE 0x5000C000
42 #define NUC1X_FLASH_ISPCON 0x5000C000
43 #define NUC1X_FLASH_ISPCMD 0x5000C00C
44 #define NUC1X_FLASH_ISPADR 0x5000C004
45 #define NUC1X_FLASH_ISPDAT 0x5000C008
46 #define NUC1X_FLASH_ISPTRG 0x5000C010
48 /* Command register bits */
49 #define PWRCON_OSC22M (1 << 2)
50 #define PWRCON_XTL12M (1 << 0)
52 #define IPRSTC1_CPU_RST (1<<1)
53 #define IPRSTC1_CHIP_RST (1<<0)
55 #define AHBCLK_ISP_EN (1 << 2)
57 #define ISPCON_ISPEN (1 << 0)
58 #define ISPCON_BS_AP (0 << 1)
59 #define ISPCON_BS_LP (1 << 1)
60 #define ISPCON_CFGUEN (1 << 4)
61 #define ISPCON_LDUEN (1 << 5)
62 #define ISPCON_ISPFF (1 << 6)
65 #define ISPCMD_FCTRL (0x2)
66 #define ISPCMD_FCEN (1 << 4)
67 #define ISPCMD_FOEN (1 << 5)
68 #define ISPCMD_ERASE (0x2 | ISPCMD_FOEN)
69 #define ISPCMD_WRITE (0x1 | ISPCMD_FOEN)
70 #define ISPTRG_ISPGO (1 << 0)
72 /* access unlock keys */
85 /*PART NO*/ /*PART ID*/ /*NUM PAGE*/
86 {"NUC100LC1", 0x00010008, 64},
87 {"NUC100LD1", 0x00010005, 128},
88 {"NUC100LD2", 0x00010004, 128},
89 {"NUC100RC1", 0x00010017, 64},
90 {"NUC100RD1", 0x00010014, 128},
91 {"NUC100RD2", 0x00010013, 128},
93 {"NUC100LD3", 0x00010003, 128},
94 {"NUC100LE3", 0x00010000, 256},
95 {"NUC100RD3", 0x00010012, 128},
96 {"NUC100RE3", 0x00010009, 256},
97 {"NUC100VD2", 0x00010022, 128},
98 {"NUC100VD3", 0x00010021, 128},
99 {"NUC100VE3", 0x00010018, 256},
101 {"NUC120LC1", 0x00012008, 64},
102 {"NUC120LD1", 0x00012005, 128},
103 {"NUC120LD2", 0x00012004, 128},
104 {"NUC120RC1", 0x00012017, 64},
105 {"NUC120RD1", 0x00012014, 128},
106 {"NUC120RD2", 0x00012013, 128},
108 {"NUC120LD3", 0x00012003, 128},
109 {"NUC120LE3", 0x00012000, 256},
110 {"NUC120RD3", 0x00012012, 128},
111 {"NUC120RE3", 0x00012009, 256},
112 {"NUC120VD2", 0x00012022, 128},
113 {"NUC120VD3", 0x00012021, 128},
114 {"NUC120VE3", 0x00012018, 256},
116 {"NUC122ZD2", 0x00012231, 128},
117 {"NUC122ZC1", 0x00012235, 64},
118 {"NUC122LD2", 0x00012204, 128},
119 {"NUC122LC1", 0x00012208, 64},
120 {"NUC122RD2", 0x00012213, 128},
121 {"NUC122RC1", 0x00012217, 64},
123 {"NUC123ZD4", 0x00012255, 136},
124 {"NUC123ZC2", 0x00012245, 68},
125 {"NUC123LD4", 0x00012235, 136},
126 {"NUC123LC2", 0x00012225, 68},
127 {"NUC123SD4", 0x00012215, 136},
128 {"NUC123SC2", 0x00012205, 68},
130 {"NUC130LC1", 0x00013008, 64},
131 {"NUC130LD2", 0x00013004, 128},
132 {"NUC130LE3", 0x00013000, 256},
133 {"NUC130RC1", 0x00013017, 64},
134 {"NUC130RD2", 0x00013013, 128},
135 {"NUC130RE3", 0x00013009, 256},
136 {"NUC130VE3", 0x00013018, 256},
138 {"M052L", 0x00005200, 16},
139 {"M052Z", 0x00005203, 16},
140 {"M054L", 0x00005400, 32},
141 {"M054Z", 0x00005403, 32},
142 {"M058L", 0x00005800, 64},
143 {"M058Z", 0x00005803, 64},
144 {"M0516L", 0x00005A00, 128},
145 {"M0516Z", 0x00005A03, 128},
147 {"MINI51L", 0x00205100, 8},
148 {"MINI51Z", 0x00205103, 8},
149 {"MINI52L", 0x00205200, 16},
150 {"MINI52Z", 0x00205203, 16},
151 {"MINI54L", 0x00205400, 32},
152 {"MINI54Z", 0x00205403, 32},
154 {"UNKNOWN", 0x00000000, 256},
157 static int nuc1x_unlock(struct flash_bank
*bank
)
159 uint32_t is_protected
;
160 struct target
*target
= bank
->target
;
162 /* Check to see if Nuc is unlocked or not */
163 int retval
= target_read_u32(target
, NUC1X_SYS_WRPROT
, &is_protected
);
164 if (retval
!= ERROR_OK
)
167 LOG_DEBUG("protected = 0x%08" PRIx32
"", is_protected
);
168 if (is_protected
== 0) { /* means protected - so unlock it */
169 /* unlock flash registers */
170 retval
= target_write_u32(target
, NUC1X_SYS_WRPROT
, KEY1
);
171 if (retval
!= ERROR_OK
)
173 retval
= target_write_u32(target
, NUC1X_SYS_WRPROT
, KEY2
);
174 if (retval
!= ERROR_OK
)
176 retval
= target_write_u32(target
, NUC1X_SYS_WRPROT
, KEY3
);
177 if (retval
!= ERROR_OK
)
180 /* Check that unlock worked */
181 retval
= target_read_u32(target
, NUC1X_SYS_WRPROT
, &is_protected
);
182 if (retval
!= ERROR_OK
)
185 if (is_protected
== 1) { /* means unprotected */
186 LOG_DEBUG("protection removed");
188 LOG_DEBUG("still protected!!");
194 static int nuc1x_reset(struct flash_bank
*bank
)
196 struct target
*target
= bank
->target
;
200 int retval
= target_write_u32(target
, NUC1X_SYS_IPRSTC1
, IPRSTC1_CPU_RST
);
201 if (retval
!= ERROR_OK
)
207 static int nuc1x_reset2lprom(struct flash_bank
*bank
)
209 struct target
*target
= bank
->target
;
212 int retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_BS_LP
);
213 if (retval
!= ERROR_OK
)
221 static int nuc1x_init_iap(struct flash_bank
*bank
)
223 struct target
*target
= bank
->target
;
225 if (target
->state
!= TARGET_HALTED
) {
226 LOG_ERROR("Target not halted");
227 return ERROR_TARGET_NOT_HALTED
;
230 int retval
= nuc1x_unlock(bank
);
231 if (retval
!= ERROR_OK
)
234 /* enable isp clock and ispen bit */
235 retval
= target_write_u32(target
, NUC1X_SYSCLK_AHBCLK
, AHBCLK_ISP_EN
);
236 if (retval
!= ERROR_OK
)
239 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_ISPFF
| ISPCON_LDUEN
| ISPCON_CFGUEN
| ISPCON_ISPEN
);
240 if (retval
!= ERROR_OK
)
246 /* Private bank information for nuc1x. */
247 struct nuc1x_flash_bank
{
248 struct working_area
*write_algorithm
;
252 /* This is the function called in the config file. */
253 FLASH_BANK_COMMAND_HANDLER(nuc1x_flash_bank_command
)
255 struct nuc1x_flash_bank
*bank_info
;
258 return ERROR_COMMAND_SYNTAX_ERROR
;
260 LOG_INFO("add flash_bank nuc1x %s", bank
->name
);
262 bank_info
= malloc(sizeof(struct nuc1x_flash_bank
));
264 memset(bank_info
, 0, sizeof(struct nuc1x_flash_bank
));
266 bank
->driver_priv
= bank_info
;
272 /* Protection checking - examines the lock bit. */
273 static int nuc1x_protect_check(struct flash_bank
*bank
)
275 uint32_t is_protected
, set
;
276 struct target
*target
= bank
->target
;
279 if (target
->state
!= TARGET_HALTED
) {
280 LOG_ERROR("Target not halted");
281 return ERROR_TARGET_NOT_HALTED
;
284 /* Check to see if Nuc is unlocked or not */
285 int retval
= target_read_u32(target
, NUC1X_SYS_WRPROT
, &is_protected
);
286 if (retval
!= ERROR_OK
)
289 LOG_INFO("is_protected = 0x%08" PRIx32
"", is_protected
);
290 if (is_protected
== 0) { /* means protected */
295 for (i
= 0; i
< bank
->num_sectors
; i
++)
296 bank
->sectors
[i
].is_protected
= set
;
301 static int nuc1x_erase(struct flash_bank
*bank
, int first
, int last
)
303 struct target
*target
= bank
->target
;
304 uint32_t timeout
, status
;
307 if (bank
->target
->state
!= TARGET_HALTED
) {
308 LOG_ERROR("Target not halted");
309 return ERROR_TARGET_NOT_HALTED
;
312 LOG_INFO("Nuvoton NUC: Sector Erase ... (%d to %d)", first
, last
);
314 int retval
= nuc1x_reset2lprom(bank
);
315 if (retval
!= ERROR_OK
)
318 retval
= nuc1x_init_iap(bank
);
319 if (retval
!= ERROR_OK
)
322 retval
= nuc1x_unlock(bank
);
323 if (retval
!= ERROR_OK
)
326 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCMD
, ISPCMD_ERASE
);
327 if (retval
!= ERROR_OK
)
330 for (i
= first
; i
<= last
; i
++) {
331 LOG_DEBUG("erasing sector %d at addresss 0x%" PRIx32
"", i
, bank
->base
+ bank
->sectors
[i
].offset
);
332 retval
= target_write_u32(target
, NUC1X_FLASH_ISPADR
, bank
->base
+ bank
->sectors
[i
].offset
);
333 if (retval
!= ERROR_OK
)
335 retval
= target_write_u32(target
, NUC1X_FLASH_ISPTRG
, ISPTRG_ISPGO
); /* This is the only bit available */
336 if (retval
!= ERROR_OK
)
339 /* wait for busy to clear - check the GO flag */
342 retval
= target_read_u32(target
, NUC1X_FLASH_ISPTRG
, &status
);
343 if (retval
!= ERROR_OK
)
345 LOG_DEBUG("status: 0x%" PRIx32
"", status
);
348 if (timeout
-- <= 0) {
349 LOG_DEBUG("timed out waiting for flash");
352 busy_sleep(1); /* can use busy sleep for short times. */
355 /* check for failure */
356 retval
= target_read_u32(target
, NUC1X_FLASH_ISPCON
, &status
);
357 if (retval
!= ERROR_OK
)
359 if ((status
& ISPCON_ISPFF
) != 0) {
360 LOG_DEBUG("failure: 0x%" PRIx32
"", status
);
361 /* if bit is set, then must write to it to clear it. */
362 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_ISPFF
);
363 if (retval
!= ERROR_OK
)
366 bank
->sectors
[i
].is_erased
= 1;
370 retval
= nuc1x_reset(bank
);
371 if (retval
!= ERROR_OK
)
375 LOG_DEBUG("Erase done.");
380 /* The write routine stub. */
381 static int nuc1x_write(struct flash_bank
*bank
, const uint8_t *buffer
,
382 uint32_t offset
, uint32_t count
)
384 struct target
*target
= bank
->target
;
385 uint32_t i
, timeout
, status
;
387 if (bank
->target
->state
!= TARGET_HALTED
) {
388 LOG_ERROR("Target not halted");
389 return ERROR_TARGET_NOT_HALTED
;
392 LOG_INFO("Novoton NUC: FLASH Write ...");
394 int retval
= nuc1x_reset2lprom(bank
);
395 if (retval
!= ERROR_OK
)
398 retval
= nuc1x_init_iap(bank
);
399 if (retval
!= ERROR_OK
)
402 retval
= nuc1x_unlock(bank
);
403 if (retval
!= ERROR_OK
)
406 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCMD
, ISPCMD_WRITE
);
407 if (retval
!= ERROR_OK
)
410 /* program command */
411 for (i
= 0; i
< count
; i
+= 4) {
413 LOG_DEBUG("write longword @ %08" PRIX32
, (uint32_t)(offset
+ i
));
415 uint8_t padding
[4] = {0xff, 0xff, 0xff, 0xff};
416 memcpy(padding
, buffer
+ i
, MIN(4, count
-i
));
418 retval
= target_write_u32(target
, NUC1X_FLASH_ISPADR
, bank
->base
+ offset
+ i
);
419 if (retval
!= ERROR_OK
)
421 retval
= target_write_memory(target
, NUC1X_FLASH_ISPDAT
, 4, 1, padding
);
422 if (retval
!= ERROR_OK
)
424 retval
= target_write_u32(target
, NUC1X_FLASH_ISPTRG
, ISPTRG_ISPGO
);
425 if (retval
!= ERROR_OK
)
428 /* wait for busy to clear - check the GO flag */
431 retval
= target_read_u32(target
, NUC1X_FLASH_ISPTRG
, &status
);
432 if (retval
!= ERROR_OK
)
434 LOG_DEBUG("status: 0x%" PRIx32
"", status
);
437 if (timeout
-- <= 0) {
438 LOG_DEBUG("timed out waiting for flash");
441 busy_sleep(1); /* can use busy sleep for short times. */
444 /* check for failure */
445 retval
= target_read_u32(target
, NUC1X_FLASH_ISPCON
, &status
);
446 if (retval
!= ERROR_OK
)
448 if ((status
& ISPCON_ISPFF
) != 0) {
449 LOG_DEBUG("failure: 0x%" PRIx32
"", status
);
450 /* if bit is set, then must write to it to clear it. */
451 retval
= target_write_u32(target
, NUC1X_FLASH_ISPCON
, ISPCON_ISPFF
);
452 if (retval
!= ERROR_OK
)
455 LOG_DEBUG("writed OK");
459 retval
= nuc1x_reset(bank
);
460 if (retval
!= ERROR_OK
)
464 LOG_DEBUG("Write done.");
469 /* The probe routine for the nuc. Only recognizes the nuc120 right now. */
470 static int nuc1x_probe(struct flash_bank
*bank
)
472 struct target
*target
= bank
->target
;
473 struct nuc1x_flash_bank
*nuc1x_info
= bank
->driver_priv
;
478 uint32_t base_address
= 0x00000000;
480 nuc1x_info
->probed
= 0;
482 /* read nuc1x device id register */
483 int retval
= target_read_u32(target
, 0x50000000, &device_id
);
484 if (retval
!= ERROR_OK
)
487 page_size
= 512; /* all nuc parts has 512 byte per sector */
489 /* search part numbers */
490 for (i
= 0; NuMicroParts
[i
].partno
; i
++) {
491 if (NuMicroParts
[i
].partno
== (device_id
& 0x0FFFFFFF)) {
492 num_pages
= NuMicroParts
[i
].num_page
;
496 if (!(NuMicroParts
[i
].partno
== 0x00000000)) {
497 LOG_INFO("DeviceID : 0x%08" PRIx32
"", device_id
);
498 LOG_INFO("Detect %s%cN!", NuMicroParts
[i
].partname
, (char)('A'+(device_id
>>28)));
500 LOG_INFO("No NUC Device Detected...");
506 bank
->sectors
= NULL
;
509 bank
->base
= base_address
;
510 bank
->size
= (num_pages
* page_size
);
511 bank
->num_sectors
= num_pages
;
512 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_pages
);
514 for (i
= 0; i
< num_pages
; i
++) {
515 bank
->sectors
[i
].offset
= i
* page_size
;
516 bank
->sectors
[i
].size
= page_size
;
517 bank
->sectors
[i
].is_erased
= -1;
518 bank
->sectors
[i
].is_protected
= 1;
521 nuc1x_info
->probed
= 1;
523 LOG_DEBUG("Novoton NUC: Probed ...");
528 /* Standard approach to autoprobing. */
529 static int nuc1x_auto_probe(struct flash_bank
*bank
)
531 struct nuc1x_flash_bank
*nuc1x_info
= bank
->driver_priv
;
532 if (nuc1x_info
->probed
)
534 return nuc1x_probe(bank
);
537 /* Info doesn't really add much, but works correctly. */
538 static int get_nuc1x_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
540 struct target
*target
= bank
->target
;
541 uint32_t i
, device_id
;
543 /* read nuc1x device id register */
544 int retval
= target_read_u32(target
, 0x50000000, &device_id
);
545 if (retval
!= ERROR_OK
)
548 /* search part numbers */
549 for (i
= 0; NuMicroParts
[i
].partno
; i
++) {
550 if (NuMicroParts
[i
].partno
== (device_id
& 0x0FFFFFFF))
553 if (!(NuMicroParts
[i
].partno
== 0x00000000)) {
554 LOG_INFO("DeviceID : 0x%08" PRIx32
"", device_id
);
555 LOG_INFO("Detect %s%cN!", NuMicroParts
[i
].partname
, (char)('A'+(device_id
>>28)));
557 LOG_INFO("No NUC Device Detected...");
564 /* The nuc120 doesn't support mass erase, so this will probably be removed soon.
565 * The structure is left for now until I am sure I don't want to add any custom
567 static int nuc1x_mass_erase(struct flash_bank
*bank
)
569 struct target
*target
= bank
->target
;
570 int retval
= ERROR_OK
;
572 if (target
->state
!= TARGET_HALTED
) {
573 LOG_ERROR("Target not halted");
574 return ERROR_TARGET_NOT_HALTED
;
577 LOG_INFO("Novoton NUC: Chip Erase ... (may take several seconds)");
582 COMMAND_HANDLER(nuc1x_handle_mass_erase_command
)
584 int i
; /* for erasing sectors */
586 command_print(CMD_CTX
, "nuc1x mass_erase <bank>");
590 struct flash_bank
*bank
;
591 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
592 if (ERROR_OK
!= retval
)
595 retval
= nuc1x_mass_erase(bank
);
596 if (retval
== ERROR_OK
) {
597 /* set all sectors as erased */
598 for (i
= 0; i
< bank
->num_sectors
; i
++)
599 bank
->sectors
[i
].is_erased
= 1;
601 command_print(CMD_CTX
, "nuc1x mass erase complete");
603 command_print(CMD_CTX
, "nuc1x mass erase failed");
608 static const struct command_registration nuc1x_exec_command_handlers
[] = {
610 .name
= "mass_erase",
611 .handler
= nuc1x_handle_mass_erase_command
,
612 .mode
= COMMAND_EXEC
,
614 .help
= "Erase entire Flash device.",
616 COMMAND_REGISTRATION_DONE
619 static const struct command_registration nuc1x_command_handlers
[] = {
623 .help
= "nuc1x Flash command group",
624 .chain
= nuc1x_exec_command_handlers
,
626 COMMAND_REGISTRATION_DONE
628 struct flash_driver nuc1x_flash
= {
630 .commands
= nuc1x_command_handlers
,
631 .flash_bank_command
= nuc1x_flash_bank_command
,
632 .erase
= nuc1x_erase
,
633 .write
= nuc1x_write
,
634 .read
= default_flash_read
,
635 .probe
= nuc1x_probe
,
636 .auto_probe
= nuc1x_auto_probe
,
637 .erase_check
= default_flash_blank_check
,
638 .protect_check
= nuc1x_protect_check
,
639 .info
= get_nuc1x_info
,
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)