OpenOCD
numicro.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2011 by James K. Larson *
5  * jlarson@pacifier.com *
6  * *
7  * Copyright (C) 2013 Cosmin Gorgovan *
8  * cosmin [at] linux-geek [dot] org *
9  * *
10  * Copyright (C) 2014 Pawel Si *
11  * stawel+openocd@gmail.com *
12  * *
13  * Copyright (C) 2015 Nemui Trinomius *
14  * nemuisan_kawausogasuki@live.jp *
15  * *
16  * Copyright (C) 2017 Zale Yu *
17  * CYYU@nuvoton.com *
18  * *
19  * Copyright (C) 2022 Jian-Hong Pan *
20  * chienhung.pan@gmail.com *
21  ***************************************************************************/
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include "imp.h"
28 #include <helper/binarybuffer.h>
29 #include <target/algorithm.h>
30 #include <target/armv7m.h>
31 #include <target/cortex_m.h>
32 
33 /* Nuvoton NuMicro Flash Version */
34 #define NUMICRO_M0_FLASH_VERSION 0x40003FFC
35 #define NUMICRO_M0_FLASH_FMC2017 0x20171011 /* This version's FMC_BA should be 0x4000C000 */
36 
37 /* Nuvoton NuMicro register locations */
38 #define NUMICRO_SYS_BASE 0x50000000
39 #define NUMICRO_SYS_WRPROT 0x50000100
40 #define NUMICRO_SYS_IPRSTC1 0x50000008
41 
42 #define NUMICRO_SYSCLK_BASE 0x50000200
43 #define NUMICRO_SYSCLK_PWRCON 0x50000200
44 #define NUMICRO_SYSCLK_CLKSEL0 0x50000210
45 #define NUMICRO_SYSCLK_CLKDIV 0x50000218
46 #define NUMICRO_SYSCLK_AHBCLK 0x50000204
47 
48 #define NUMICRO_FLASH_BASE 0x5000C000
49 #define NUMICRO_FLASH_ISPCON 0x5000C000
50 #define NUMICRO_FLASH_ISPADR 0x5000C004
51 #define NUMICRO_FLASH_ISPDAT 0x5000C008
52 #define NUMICRO_FLASH_ISPCMD 0x5000C00C
53 #define NUMICRO_FLASH_ISPTRG 0x5000C010
54 #define NUMICRO_FLASH_CHEAT 0x5000C01C /* Undocumented isp register(may be cheat register) */
55 
56 #define NUMICRO_SCS_BASE 0xE000E000
57 #define NUMICRO_SCS_AIRCR 0xE000ED0C
58 #define NUMICRO_SCS_DHCSR 0xE000EDF0
59 #define NUMICRO_SCS_DEMCR 0xE000EDFC
60 
61 #define NUMICRO_APROM_BASE 0x00000000
62 #define NUMICRO_DATA_BASE 0x0001F000
63 #define NUMICRO_LDROM_BASE 0x00100000
64 #define NUMICRO_CONFIG_BASE 0x00300000
65 
66 #define NUMICRO_CONFIG0 0x5000C000
67 #define NUMICRO_CONFIG1 0x5000C004
68 
69 /* Command register bits */
70 #define PWRCON_OSC22M (1 << 2)
71 #define PWRCON_XTL12M (1 << 0)
72 
73 #define IPRSTC1_CPU_RST (1 << 1)
74 #define IPRSTC1_CHIP_RST (1 << 0)
75 
76 #define AHBCLK_ISP_EN (1 << 2)
77 #define AHBCLK_SRAM_EN (1 << 4)
78 #define AHBCLK_TICK_EN (1 << 5)
79 
80 #define ISPCON_ISPEN (1 << 0)
81 #define ISPCON_BS_AP (0 << 1)
82 #define ISPCON_BS_LP (1 << 1)
83 #define ISPCON_BS_MASK (1 << 1)
84 #define ISPCON_APUEN (1 << 3)
85 #define ISPCON_CFGUEN (1 << 4)
86 #define ISPCON_LDUEN (1 << 5)
87 #define ISPCON_ISPFF (1 << 6)
88 
89 #define CONFIG0_LOCK_MASK (1 << 1)
90 
91 /* isp commands */
92 #define ISPCMD_READ 0x00
93 #define ISPCMD_WRITE 0x21
94 #define ISPCMD_ERASE 0x22
95 #define ISPCMD_CHIPERASE 0x26 /* Undocumented isp "Chip-Erase" command */
96 #define ISPCMD_READ_CID 0x0B
97 #define ISPCMD_READ_DID 0x0C
98 #define ISPCMD_READ_UID 0x04
99 #define ISPCMD_VECMAP 0x2E
100 #define ISPTRG_ISPGO (1 << 0)
101 
102 /* access unlock keys */
103 #define REG_KEY1 0x59
104 #define REG_KEY2 0x16
105 #define REG_KEY3 0x88
106 #define REG_LOCK 0x00
107 
108 /* flash pagesizes */
109 #define NUMICRO_PAGESIZE 512
110 /* flash MAX banks */
111 #define NUMICRO_MAX_FLASH_BANKS 4
112 
113 /* flash bank structs */
115  uint32_t base;
116  uint32_t size;
117 };
118 
119 /* part structs */
121  char *partname;
122  uint32_t partid;
123  unsigned int n_banks;
125 };
126 
127 /* If DataFlash size equals zero, it means the actual size depends on config settings. */
128 #define NUMICRO_BANKS_GENERAL(aprom_size, data_size, ldrom_size, config_size) \
129  .n_banks = 4, \
130  {{NUMICRO_APROM_BASE, (aprom_size)}, \
131  {NUMICRO_DATA_BASE, (data_size)}, \
132  {NUMICRO_LDROM_BASE, (ldrom_size)}, \
133  {NUMICRO_CONFIG_BASE, (config_size)}}
134 
135 static const struct numicro_cpu_type numicro_parts[] = {
136  /*PART NO*/ /*PART ID*/ /*Banks*/
137  /* M031 */
138  {"M031EB0AE", 0x01131BA0, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 12)},
139  {"M031EC1AE", 0x01131CA0, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 2 * 1024, 12)},
140  {"M031FB0AE", 0x01131BB0, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 12)},
141  {"M031FC1AE", 0x01131CB0, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 2 * 1024, 12)},
142  {"M031LC2AE", 0x01131D01, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 2 * 1024, 12)},
143  {"M031LD2AE", 0x01131D00, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 2 * 1024, 12)},
144  {"M031LE3AE", 0x01131E00, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 12)},
145  {"M031SC2AE", 0x01131D11, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 2 * 1024, 12)},
146  {"M031SD2AE", 0x01131D10, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 2 * 1024, 12)},
147  {"M031SE3AE", 0x01131E10, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 12)},
148  {"M031TB0AE", 0x01131BE0, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 12)},
149  {"M031TC1AE", 0x01131CE0, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 2 * 1024, 12)},
150  {"M031TD2AE", 0x01131DE0, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 2 * 1024, 12)},
151  {"M032LE3AE", 0x01132E00, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 12)},
152  {"M032SE3AE", 0x01132E10, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 12)},
153 
154  /* M051AN */
155  {"M052LAN", 0x00005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
156  {"M054LAN", 0x00005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
157  {"M058LAN", 0x00005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
158  {"M0516LAN", 0x00005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
159  {"M052ZAN", 0x00005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
160  {"M054ZAN", 0x00005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
161  {"M058ZAN", 0x00005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
162  {"M0516ZAN", 0x00005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
163 
164  /* M051BN */
165  {"M052LBN", 0x10005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
166  {"M054LBN", 0x10005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
167  {"M058LBN", 0x10005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
168  {"M0516LBN", 0x10005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
169  {"M052ZBN", 0x10005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
170  {"M054ZBN", 0x10005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
171  {"M058ZBN", 0x10005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
172  {"M0516ZBN", 0x10005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
173 
174  /* M051DN */
175  {"M0516LDN", 0x20005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
176  {"M0516ZDN", 0x20005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
177  {"M052LDN", 0x20005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
178  {"M052ZDN", 0x20005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
179  {"M054LDN", 0x20005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
180  {"M054ZDN", 0x20005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
181  {"M058LDN", 0x20005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
182  {"M058ZDN", 0x20005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
183 
184  /* M051DE */
185  {"M0516LDE", 0x30005A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
186  {"M0516ZDE", 0x30005A03, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
187  {"M052LDE", 0x30005200, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
188  {"M052ZDE", 0x30005203, NUMICRO_BANKS_GENERAL(8 * 1024, 4 * 1024, 4 * 1024, 4)},
189  {"M054LDE", 0x30005400, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
190  {"M054ZDE", 0x30005403, NUMICRO_BANKS_GENERAL(16 * 1024, 4 * 1024, 4 * 1024, 4)},
191  {"M058LDE", 0x30005800, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
192  {"M058ZDE", 0x30005803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
193 
194  /* M0518 */
195  {"M0518LC2AE", 0x10051803, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
196  {"M0518LD2AE", 0x10051800, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
197  {"M0518SC2AE", 0x10051813, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
198  {"M0518SD2AE", 0x10051810, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
199 
200  /* M0519 */
201  {"M0519LD3AE", 0x00051902, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
202  {"M0519LE3AE", 0x00051900, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
203  {"M0519SD3AE", 0x00051922, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
204  {"M0519SE3AE", 0x00051920, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
205  {"M0519VE3AE", 0x00051930, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
206 
207  /* M058S */
208  {"M058SFAN", 0x00005818, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
209  {"M058SLAN", 0x00005810, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
210  {"M058SSAN", 0x00005816, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
211  {"M058SZAN", 0x00005813, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
212 
213  /* MINI51AN */
214  {"MINI51LAN", 0x00205100, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
215  {"MINI51TAN", 0x00205104, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
216  {"MINI51ZAN", 0x00205103, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
217  {"MINI52LAN", 0x00205200, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
218  {"MINI52TAN", 0x00205204, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
219  {"MINI52ZAN", 0x00205203, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
220  {"MINI54LAN", 0x00205400, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
221  {"MINI54TAN", 0x00205404, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
222  {"MINI54ZAN", 0x00205403, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
223 
224  /* MINI51DE */
225  {"MINI51FDE", 0x20205105, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
226  {"MINI51LDE", 0x20205100, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
227  {"MINI51TDE", 0x20205104, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
228  {"MINI51ZDE", 0x20205103, NUMICRO_BANKS_GENERAL(4 * 1024, 0 * 1024, 2 * 1024, 8)},
229  {"MINI52FDE", 0x20205205, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
230  {"MINI52LDE", 0x20205200, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
231  {"MINI52TDE", 0x20205204, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
232  {"MINI52ZDE", 0x20205203, NUMICRO_BANKS_GENERAL(8 * 1024, 0 * 1024, 2 * 1024, 8)},
233  {"MINI54FDE", 0x20205405, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
234  {"MINI54LDE", 0x20205400, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
235  {"MINI54TDE", 0x20205404, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
236  {"MINI54ZDE", 0x20205403, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
237 
238  /* MINI55 */
239  {"MINI55LDE", 0x00505500, NUMICRO_BANKS_GENERAL(35 * 512, 0 * 1024, 2 * 1024, 8)},
240  {"MINI55ZDE", 0x00505503, NUMICRO_BANKS_GENERAL(35 * 512, 0 * 1024, 2 * 1024, 8)},
241 
242  /* MINI58 */
243  {"MINI58FDE", 0x00A05805, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
244  {"MINI58LDE", 0x00A05800, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
245  {"MINI58TDE", 0x00A05804, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
246  {"MINI58ZDE", 0x00A05803, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 5 * 512, 8)},
247 
248  /* NANO100AN */
249  {"NANO100LC2AN", 0x00110025, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
250  {"NANO100LD2AN", 0x00110019, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
251  {"NANO100LD3AN", 0x00110018, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
252  {"NANO100SC2AN", 0x00110023, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
253  {"NANO100SD2AN", 0x00110016, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
254  {"NANO100SD3AN", 0x00110015, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
255  {"NANO100VD2AN", 0x00110013, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
256  {"NANO100VD3AN", 0x00110012, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
257  {"NANO100ZC2AN", 0x00110029, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
258  {"NANO100ZD2AN", 0x00110028, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
259  {"NANO100ZD3AN", 0x00110027, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
260  {"NANO120LC2AN", 0x00112025, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
261  {"NANO120LD2AN", 0x00112019, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
262  {"NANO120LD3AN", 0x00112018, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
263  {"NANO120SC2AN", 0x00112023, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
264  {"NANO120SD2AN", 0x00112016, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
265  {"NANO120SD3AN", 0x00112015, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
266  {"NANO120VD2AN", 0x00112013, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
267  {"NANO120VD3AN", 0x00112012, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
268  {"NANO120ZC2AN", 0x00112029, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
269  {"NANO120ZD2AN", 0x00112028, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
270  {"NANO120ZD3AN", 0x00112027, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
271 
272  /* NANO100BN */
273  {"NANO100KC2BN", 0x00110040, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
274  {"NANO100KD2BN", 0x00110039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
275  {"NANO100KD3BN", 0x00110038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
276  {"NANO100KE3BN", 0x00110030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
277  {"NANO100LC2BN", 0x00110043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
278  {"NANO100LD2BN", 0x0011003F, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
279  {"NANO100LD3BN", 0x0011003E, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
280  {"NANO100LE3BN", 0x00110036, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
281  {"NANO100ND2BN", 0x00110046, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
282  {"NANO100ND3BN", 0x00110045, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
283  {"NANO100NE3BN", 0x00110044, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
284  {"NANO100SC2BN", 0x00110042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
285  {"NANO100SD2BN", 0x0011003D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
286  {"NANO100SD3BN", 0x0011003C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
287  {"NANO100SE3BN", 0x00110034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
288  {"NANO110KC2BN", 0x00111040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
289  {"NANO110KD2BN", 0x00111039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
290  {"NANO110KD3BN", 0x00111038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
291  {"NANO110KE3BN", 0x00111030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
292  {"NANO110RC2BN", 0x00111043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
293  {"NANO110RD2BN", 0x00111044, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
294  {"NANO110RD3BN", 0x00111045, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
295  {"NANO110SC2BN", 0x00111042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
296  {"NANO110SD2BN", 0x0011103D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
297  {"NANO110SD3BN", 0x0011103C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
298  {"NANO110SE3BN", 0x00111034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
299  {"NANO120KC2BN", 0x00112040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
300  {"NANO120KD2BN", 0x00112039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
301  {"NANO120KD3BN", 0x00112038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
302  {"NANO120KE3BN", 0x00112030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
303  {"NANO120LC2BN", 0x00112043, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
304  {"NANO120LD2BN", 0x0011203F, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
305  {"NANO120LD3BN", 0x0011203E, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
306  {"NANO120LE3BN", 0x00112036, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
307  {"NANO120SC2BN", 0x00112042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
308  {"NANO120SD2BN", 0x0011203D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
309  {"NANO120SD3BN", 0x0011203C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
310  {"NANO120SE3BN", 0x00112034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
311  {"NANO130KC2BN", 0x00113040, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
312  {"NANO130KD2BN", 0x00113039, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
313  {"NANO130KD3BN", 0x00113038, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
314  {"NANO130KE3BN", 0x00113030, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
315  {"NANO130SC2BN", 0x00113042, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
316  {"NANO130SD2BN", 0x0011303D, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
317  {"NANO130SD3BN", 0x0011303C, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
318  {"NANO130SE3BN", 0x00113034, NUMICRO_BANKS_GENERAL(123 * 1024, 0 * 1024, 4 * 1024, 8)},
319 
320  /* NANO103 */
321  {"NANO103SD3AE", 0x00110301, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
322  {"NANO103LD3AE", 0x00110304, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
323  {"NANO103ZD3AE", 0x00110307, NUMICRO_BANKS_GENERAL(64 * 1024, 0 * 1024, 4 * 1024, 8)},
324 
325  /* NANO112AN */
326  {"NANO102LB1AN", 0x00110206, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
327  {"NANO102LC2AN", 0x00110208, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
328  {"NANO102SC2AN", 0x00110212, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
329  {"NANO102ZB1AN", 0x00110202, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
330  {"NANO102ZC2AN", 0x00110204, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
331  {"NANO112LB1AN", 0x00111202, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
332  {"NANO112LC2AN", 0x00111204, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
333  {"NANO112RB1AN", 0x00111210, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
334  {"NANO112RC2AN", 0x00111212, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
335  {"NANO112SB1AN", 0x00111206, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 4 * 1024, 8)},
336  {"NANO112SC2AN", 0x00111208, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
337  {"NANO112VC2AN", 0x00111216, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 4 * 1024, 8)},
338 
339  /* NUC029AN */
340  {"NUC029LAN", 0x00295A00, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 4)},
341  {"NUC029TAN", 0x00295804, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 4)},
342 
343  /* NUC029AE */
344  {"NUC029FAE", 0x00295415, NUMICRO_BANKS_GENERAL(16 * 1024, 0 * 1024, 2 * 1024, 8)},
345 
346  /* NUC100AN */
347  {"NUC100LD3AN", 0x00010003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
348  {"NUC100LE3AN", 0x00010000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
349  {"NUC100RD3AN", 0x00010012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
350  {"NUC100RE3AN", 0x00010009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
351  {"NUC100VD2AN", 0x00010022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
352  {"NUC100VD3AN", 0x00010021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
353  {"NUC100VE3AN", 0x00100018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
354  {"NUC120LD3AN", 0x00012003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
355  {"NUC120LE3AN", 0x00120000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
356  {"NUC120RD3AN", 0x00012012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
357  {"NUC120RE3AN", 0x00012009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
358  {"NUC120VD2AN", 0x00012022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
359  {"NUC120VD3AN", 0x00012021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
360  {"NUC120VE3AN", 0x00012018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
361 
362  /* NUC100BN */
363  {"NUC100LC1BN", 0x10010008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
364  {"NUC100LD1BN", 0x10010005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
365  {"NUC100LD2BN", 0x10010004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
366  {"NUC100RC1BN", 0x10010017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
367  {"NUC100RD1BN", 0x10010014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
368  {"NUC100RD2BN", 0x10010013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
369  {"NUC120LC1BN", 0x10012008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
370  {"NUC120LD1BN", 0x10012005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
371  {"NUC120LD2BN", 0x10012004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
372  {"NUC120RC1BN", 0x10012017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
373  {"NUC120RD1BN", 0x10012014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
374  {"NUC120RD2BN", 0x10012013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
375 
376  /* NUC100CN */
377  {"NUC130LC1CN", 0x20013008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
378  {"NUC130LD2CN", 0x20013004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
379  {"NUC130LE3CN", 0x20013000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
380  {"NUC130RC1CN", 0x20013017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
381  {"NUC130RD2CN", 0x20013013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
382  {"NUC130RE3CN", 0x20013009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
383  {"NUC130VE3CN", 0x20013018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
384  {"NUC140LC1CN", 0x20014008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
385  {"NUC140LD2CN", 0x20014004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
386  {"NUC140LE3CN", 0x20014000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
387  {"NUC140RC1CN", 0x20014017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
388  {"NUC140RD2CN", 0x20014013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
389  {"NUC140RE3CN", 0x20014009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
390  {"NUC140VE3CN", 0x20014018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
391 
392  /* NUC100DN */
393  {"NUC100LC1DN", 0x30010008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
394  {"NUC100LD1DN", 0x30010005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
395  {"NUC100LD2DN", 0x30010004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
396  {"NUC100LD3DN", 0x30010003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
397  {"NUC100LE3DN", 0x30010000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
398  {"NUC100RC1DN", 0x30010017, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
399  {"NUC100RD1DN", 0x30010014, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
400  {"NUC100RD2DN", 0x30010013, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
401  {"NUC100RD3DN", 0x30010012, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
402  {"NUC100RE3DN", 0x30010009, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
403  {"NUC100VD2DN", 0x30010022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
404  {"NUC100VD3DN", 0x30010021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
405  {"NUC100VE3DN", 0x30010018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
406  {"NUC120LC1DN", 0x30012008, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
407  {"NUC120LD1DN", 0x30012005, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
408  {"NUC120LD2DN", 0x30012004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
409  {"NUC120LD3DN", 0x30012003, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
410  {"NUC120LE3DN", 0x30012000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
411  {"NUC120RC1DN", 0x30012035, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
412  {"NUC120RD1DN", 0x30012032, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
413  {"NUC120RD2DN", 0x30012031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
414  {"NUC120RD3DN", 0x30012030, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
415  {"NUC120RE3DN", 0x30012027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
416  {"NUC120VD2DN", 0x30012022, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
417  {"NUC120VD3DN", 0x30012021, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
418  {"NUC120VE3DN", 0x30012018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
419 
420  /* NUC121 */
421  {"NUC121SC2AE", 0x00012105, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
422  {"NUC121LC2AE", 0x00012125, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
423  {"NUC121ZC2AE", 0x00012145, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
424  {"NUC125SC2AE", 0x00012505, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
425  {"NUC125LC2AE", 0x00012525, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
426  {"NUC125ZC2AE", 0x00012545, NUMICRO_BANKS_GENERAL(32 * 1024, 0 * 1024, 9 * 512, 8)},
427 
428  /* NUC122 */
429  {"NUC122LC1AN", 0x00012208, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
430  {"NUC122LD2AN", 0x00012204, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
431  {"NUC122SC1AN", 0x00012226, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
432  {"NUC122SD2AN", 0x00012222, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
433  {"NUC122ZC1AN", 0x00012235, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
434  {"NUC122ZD2AN", 0x00012231, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
435 
436  /* NUC123AN */
437  {"NUC123LC2AN1", 0x00012325, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
438  {"NUC123LD4AN0", 0x00012335, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
439  {"NUC123SC2AN1", 0x00012305, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
440  {"NUC123SD4AN0", 0x00012315, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
441  {"NUC123ZC2AN1", 0x00012345, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
442  {"NUC123ZD4AN0", 0x00012355, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
443 
444  /* NUC123AE */
445  {"NUC123LC2AE1", 0x10012325, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
446  {"NUC123LD4AE0", 0x10012335, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
447  {"NUC123SC2AE1", 0x10012305, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
448  {"NUC123SD4AE0", 0x10012315, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
449  {"NUC123ZC2AE1", 0x10012345, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
450  {"NUC123ZD4AE0", 0x10012355, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
451 
452  /* NUC131AE */
453  {"NUC131LC2AE", 0x10013103, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
454  {"NUC131LD2AE", 0x10013100, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
455  {"NUC131SC2AE", 0x10013113, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
456  {"NUC131SD2AE", 0x10013110, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
457 
458  /* NUC200/220AN */
459  {"NUC200LC2AN", 0x00020007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
460  {"NUC200LD2AN", 0x00020004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
461  {"NUC200LE3AN", 0x00020000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
462  {"NUC200SC2AN", 0x00020034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
463  {"NUC200SD2AN", 0x00020031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
464  {"NUC200SE3AN", 0x00020027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
465  {"NUC200VE3AN", 0x00020018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
466  {"NUC220LC2AN", 0x00022007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
467  {"NUC220LD2AN", 0x00022004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
468  {"NUC220LE3AN", 0x00022000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
469  {"NUC220SC2AN", 0x00022034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 4 * 1024, 8)},
470  {"NUC220SD2AN", 0x00022031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 4 * 1024, 8)},
471  {"NUC220SE3AN", 0x00022027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
472  {"NUC220VE3AN", 0x00022018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
473 
474  /* NUC230/240AE */
475  {"NUC230LC2AE", 0x10023007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
476  {"NUC230LD2AE", 0x10023004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
477  {"NUC230LE3AE", 0x10023000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
478  {"NUC230SC2AE", 0x10023034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
479  {"NUC230SD2AE", 0x10023031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
480  {"NUC230SE3AE", 0x10023027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
481  {"NUC230VE3AE", 0x10023018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
482  {"NUC240LC2AE", 0x10024007, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
483  {"NUC240LD2AE", 0x10024004, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
484  {"NUC240LE3AE", 0x10024000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
485  {"NUC240SC2AE", 0x10024034, NUMICRO_BANKS_GENERAL(32 * 1024, 4 * 1024, 8 * 1024, 8)},
486  {"NUC240SD2AE", 0x10024031, NUMICRO_BANKS_GENERAL(64 * 1024, 4 * 1024, 8 * 1024, 8)},
487  {"NUC240SE3AE", 0x10024027, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
488  {"NUC240VE3AE", 0x10024018, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 8 * 1024, 8)},
489 
490  /* M451 */
491  {"M451LC3AE", 0x00945101, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
492  {"M451LD3AE", 0x00945100, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
493  {"M451LE6AE", 0x00845101, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
494  {"M451LG6AE", 0x00845100, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
495  {"M451MLC3AE", 0x00945001, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
496  {"M451MLD3AE", 0x00945000, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
497  {"M451MLE6AE", 0x00845001, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
498  {"M451MLG6AE", 0x00845000, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
499  {"M451MSC3AE", 0x00945011, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
500  {"M451MSD3AE", 0x00945010, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
501  {"M451RC3AE", 0x00945121, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
502  {"M451RD3AE", 0x00945120, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
503  {"M451RE6AE", 0x00845121, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
504  {"M451RG6AE", 0x00845120, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
505  {"M451VE6AE", 0x00845131, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
506  {"M451VG6AE", 0x00845130, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
507  {"M452LC3AE", 0x00945201, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
508  {"M452LD3AE", 0x00945200, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
509  {"M452LE6AE", 0x00845201, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
510  {"M452LG6AE", 0x00845200, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
511  {"M452RD3AE", 0x00945220, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
512  {"M452RE6AE", 0x00845221, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
513  {"M452RG6AE", 0x00845220, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
514  {"M453LC3AE", 0x00945301, NUMICRO_BANKS_GENERAL(40 * 1024, 0 * 1024, 4 * 1024, 8)},
515  {"M453LD3AE", 0x00945300, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
516  {"M453LE6AE", 0x00845301, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
517  {"M453LG6AE", 0x00845300, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
518  {"M453RD3AE", 0x00945320, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
519  {"M453RE6AE", 0x00845321, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
520  {"M453RG6AE", 0x00845320, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
521  {"M453VD3AE", 0x00945330, NUMICRO_BANKS_GENERAL(72 * 1024, 0 * 1024, 4 * 1024, 8)},
522  {"M453VE6AE", 0x00845331, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
523  {"M453VG6AE", 0x00845330, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
524  {"M4TKVG6AE", 0x00845430, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
525  {"M4TKVE6AE", 0x00845431, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
526  {"M4TKRG6AE", 0x00845420, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
527  {"M4TKRE6AE", 0x00845421, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
528  {"M4TKLG6AE", 0x00845400, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 4 * 1024, 8)},
529  {"M4TKLE6AE", 0x00845401, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 4 * 1024, 8)},
530 
531  /* NUC442_472 */
532  {"NUC442JG8AE", 0x00044203, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
533  {"NUC442JI8AE", 0x00044201, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
534  {"NUC442KG8AE", 0x00044206, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
535  {"NUC442KI8AE", 0x00044204, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
536  {"NUC442RG8AE", 0x00044212, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
537  {"NUC442RI8AE", 0x00044210, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
538  {"NUC442VG8AE", 0x00044209, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
539  {"NUC442VI8AE", 0x00044207, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
540  {"NUC472HG8AE", 0x00047203, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
541  {"NUC472HI8AE", 0x00047201, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
542  {"NUC472JG8AE", 0x00047206, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
543  {"NUC472JI8AE", 0x00047204, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
544  {"NUC472KG8AE", 0x00047209, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
545  {"NUC472KI8AE", 0x00047207, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
546  {"NUC472VG8AE", 0x00047212, NUMICRO_BANKS_GENERAL(256 * 1024, 0 * 1024, 16 * 1024, 16)},
547  {"NUC472VI8AE", 0x00047210, NUMICRO_BANKS_GENERAL(512 * 1024, 0 * 1024, 16 * 1024, 16)},
548 
549  {"UNKNOWN", 0x00000000, NUMICRO_BANKS_GENERAL(128 * 1024, 0 * 1024, 16 * 1024, 8)},
550 };
551 
552 /* Private bank information for NuMicro. */
555  bool probed;
556  const struct numicro_cpu_type *cpu;
557 };
558 
559 /* Private variables */
560 static uint32_t m_page_size = NUMICRO_PAGESIZE;
561 static uint32_t m_address_bias_offset;
562 
563 /* Private methods */
564 static bool numicro_is_m0_fmc2017(struct target *target)
565 {
566  uint32_t fmc_version;
567  int retval = ERROR_OK;
568 
569  retval = target_read_u32(target, NUMICRO_M0_FLASH_VERSION, &fmc_version);
570  if (retval != ERROR_OK) {
571  LOG_WARNING("Could not read the value of NUMICRO_M0_FLASH_VERSION");
572  return false;
573  }
574 
575  uint32_t offset = 0x0;
576  bool is_m0_fmc2017 = false;
577 
578  if (fmc_version == NUMICRO_M0_FLASH_FMC2017) {
579  offset = 0x10000000;
580  is_m0_fmc2017 = true;
581  }
582 
583  LOG_DEBUG("This NuMicro M0 chip's FMC_BA is %0x08x (NUMICRO_M0_FLASH_VERSION: 0x%" PRIx32 ").",
585  fmc_version);
586 
587  return is_m0_fmc2017;
588 }
589 
590 static int numicro_get_arm_arch(struct target *target)
591 {
592  struct armv7m_common *armv7m = target_to_armv7m(target);
593 
594  if (armv7m->arm.arch != ARM_ARCH_V6M) {
595  LOG_DEBUG("NuMicro arm architecture: armv7m\n");
597  m_address_bias_offset = 0x10000000;
598  } else {
599  LOG_DEBUG("NuMicro arm architecture: armv6m\n");
602  m_address_bias_offset = 0x10000000;
603  else
604  m_address_bias_offset = 0x0;
605  }
606 
607  return ERROR_OK;
608 }
609 
610 static int numicro_reg_unlock(struct target *target)
611 {
612  uint32_t is_protected;
613  int retval = ERROR_OK;
614 
615  /* Check to see if NUC is register unlocked or not */
617  if (retval != ERROR_OK)
618  return retval;
619 
620  LOG_DEBUG("protected = 0x%08" PRIx32, is_protected);
621  if (is_protected == 0) { /* means protected - so unlock it */
622  /* unlock flash registers */
624  if (retval != ERROR_OK)
625  return retval;
627  if (retval != ERROR_OK)
628  return retval;
630  if (retval != ERROR_OK)
631  return retval;
632  }
633  /* Check that unlock worked */
635  if (retval != ERROR_OK)
636  return retval;
637 
638  if (is_protected == 1) { /* means unprotected */
639  LOG_DEBUG("protection removed");
640  } else {
641  LOG_DEBUG("still protected!!");
642  }
643 
644  return ERROR_OK;
645 }
646 
647 static int numicro_init_isp(struct target *target)
648 {
649  uint32_t reg_stat;
650  int retval = ERROR_OK;
651 
652  if (target->state != TARGET_HALTED) {
653  LOG_ERROR("Target not halted");
655  }
656 
657  retval = numicro_reg_unlock(target);
658  if (retval != ERROR_OK)
659  return retval;
660 
661  /* Enable ISP/SRAM/TICK Clock */
663  if (retval != ERROR_OK)
664  return retval;
665 
668  if (retval != ERROR_OK)
669  return retval;
670 
671  /* Enable ISP */
673  if (retval != ERROR_OK)
674  return retval;
675 
678  if (retval != ERROR_OK)
679  return retval;
680 
681  /* Write one to undocumented flash control register */
683  if (retval != ERROR_OK)
684  return retval;
685 
686  return ERROR_OK;
687 }
688 
689 static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t *rdata)
690 {
691  uint32_t timeout, status;
692  int retval = ERROR_OK;
693 
695  if (retval != ERROR_OK)
696  return retval;
697 
699  if (retval != ERROR_OK)
700  return retval;
701 
703  if (retval != ERROR_OK)
704  return retval;
705 
707  if (retval != ERROR_OK)
708  return retval;
709 
710  /* Wait for busy to clear - check the GO flag */
711  timeout = 100;
712  for (;;) {
714  if (retval != ERROR_OK)
715  return retval;
716  if ((status & (ISPTRG_ISPGO)) == 0)
717  break;
718  if (timeout-- <= 0) {
719  LOG_DEBUG("timed out waiting for flash");
720  return ERROR_FAIL;
721  }
722  busy_sleep(1); /* can use busy sleep for short times. */
723  }
724 
726  if (retval != ERROR_OK)
727  return retval;
728 
729  return ERROR_OK;
730 }
731 
732 /* NuMicro Program-LongWord Microcodes */
733 static const uint8_t numicro_flash_write_code[] = {
734 #include "../../../contrib/loaders/flash/numicro/numicro_m0.inc"
735 };
736 
737 /* Program LongWord Block Write */
738 static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer,
739  uint32_t offset, uint32_t count)
740 {
741  struct target *target = bank->target;
742  uint32_t buffer_size = 1024; /* Default minimum value */
743  struct working_area *write_algorithm;
744  struct working_area *source;
745  uint32_t address = bank->base + offset;
746  struct reg_param reg_params[4];
747  struct armv7m_algorithm armv7m_info;
748  int retval = ERROR_OK;
749 
750  /* Params:
751  * r0 - workarea buffer / result
752  * r1 - target address
753  * r2 - wordcount
754  * r3 - FMC/ISP base address
755  * Clobbered:
756  * r4 - tmp
757  * r5 - tmp
758  */
759 
760  /* Increase buffer_size if needed */
763 
764  /* check code alignment */
765  if (offset & 0x1) {
766  LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
768  }
769 
770  /* allocate working area with flash programming code */
772  &write_algorithm) != ERROR_OK) {
773  LOG_WARNING("no working area available, can't do block memory writes");
775  }
776 
777  retval = target_write_buffer(target, write_algorithm->address,
779  if (retval != ERROR_OK)
780  return retval;
781 
782  /* memory buffer */
784  buffer_size /= 4;
785  if (buffer_size <= 256) {
786  /* free working area, write algorithm already allocated */
787  target_free_working_area(target, write_algorithm);
788 
789  LOG_WARNING("No large enough working area available, can't do block memory writes");
791  }
792  }
793 
794  armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
795  armv7m_info.core_mode = ARM_MODE_THREAD;
796 
797  init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* *pLW (*buffer) */
798  init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* faddr */
799  init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of words to program */
800  init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* FMC/ISP base address */
801 
802  /* write code buffer and use Flash programming code within NuMicro */
803  /* Set breakpoint to 0 with time-out of 1000 ms */
804  while (count > 0) {
805  uint32_t thisrun_count = (count > (buffer_size / 4)) ? (buffer_size / 4) : count;
806 
807  retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer);
808  if (retval != ERROR_OK)
809  break;
810 
811  buf_set_u32(reg_params[0].value, 0, 32, source->address);
812  buf_set_u32(reg_params[1].value, 0, 32, address);
813  buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
814  buf_set_u32(reg_params[3].value, 0, 32, NUMICRO_FLASH_ISPCON - m_address_bias_offset);
815 
816  retval = target_run_algorithm(target, 0, NULL, 4, reg_params,
817  write_algorithm->address, 0, 100000, &armv7m_info);
818  if (retval != ERROR_OK) {
819  LOG_ERROR("Error executing NuMicro Flash programming algorithm");
821  break;
822  }
823 
824  if (buf_get_u32(reg_params[0].value, 0, 32) != ERROR_OK) {
825  LOG_ERROR("NuMicro Flash programming algorithm returned error");
827  break;
828  }
829 
830  buffer += thisrun_count * 4;
831  address += thisrun_count * 4;
832  count -= thisrun_count;
833  }
834 
836  target_free_working_area(target, write_algorithm);
837 
838  destroy_reg_param(&reg_params[0]);
839  destroy_reg_param(&reg_params[1]);
840  destroy_reg_param(&reg_params[2]);
841  destroy_reg_param(&reg_params[3]);
842 
843  return retval;
844 }
845 
846 /* Flash Lock checking - examines the lock bit. */
848 {
849  struct target *target = bank->target;
850  uint32_t set, config[2];
851  int retval = ERROR_OK;
852 
853  if (target->state != TARGET_HALTED) {
854  LOG_ERROR("Target not halted");
856  }
857 
858  LOG_INFO("Nuvoton NuMicro: Flash Lock Check...");
859 
861  retval = numicro_init_isp(target);
862  if (retval != ERROR_OK)
863  return retval;
864 
865  /* Read CONFIG0,CONFIG1 */
868 
869  LOG_DEBUG("CONFIG0: 0x%" PRIx32 ",CONFIG1: 0x%" PRIx32, config[0], config[1]);
870 
871  if ((config[0] & (1<<7)) == 0)
872  LOG_INFO("CBS=0: Boot From LPROM");
873  else
874  LOG_INFO("CBS=1: Boot From APROM");
875 
876  if ((config[0] & CONFIG0_LOCK_MASK) == 0) {
877 
878  LOG_INFO("Flash is secure locked!");
879  LOG_INFO("TO UNLOCK FLASH,EXECUTE chip_erase COMMAND!!");
880  set = 1;
881  } else {
882  LOG_INFO("Flash is not locked!");
883  set = 0;
884  }
885 
886  for (unsigned int i = 0; i < bank->num_sectors; i++)
887  bank->sectors[i].is_protected = set;
888 
889  return ERROR_OK;
890 }
891 
892 
893 static int numicro_erase(struct flash_bank *bank, unsigned int first,
894  unsigned int last)
895 {
896  struct target *target = bank->target;
897  uint32_t timeout, status;
898  int retval = ERROR_OK;
899 
900  if (target->state != TARGET_HALTED) {
901  LOG_ERROR("Target not halted");
903  }
904 
905  LOG_INFO("Nuvoton NuMicro: Sector Erase ... (%u to %u)", first, last);
906 
908  retval = numicro_init_isp(target);
909  if (retval != ERROR_OK)
910  return retval;
911 
913  if (retval != ERROR_OK)
914  return retval;
915 
916  for (unsigned int i = first; i <= last; i++) {
917  LOG_DEBUG("erasing sector %u at address " TARGET_ADDR_FMT, i, bank->base + bank->sectors[i].offset);
918  retval = target_write_u32(target,
920  bank->base + bank->sectors[i].offset);
921  if (retval != ERROR_OK)
922  return retval;
923  retval = target_write_u32(target,
925  ISPTRG_ISPGO); /* This is the only bit available */
926  if (retval != ERROR_OK)
927  return retval;
928 
929  /* wait for busy to clear - check the GO flag */
930  timeout = 100;
931  for (;;) {
933  if (retval != ERROR_OK)
934  return retval;
935  if (status == 0)
936  break;
937  if (timeout-- <= 0) {
938  LOG_DEBUG("timed out waiting for flash");
939  return ERROR_FAIL;
940  }
941  busy_sleep(1); /* can use busy sleep for short times. */
942  }
943 
944  /* check for failure */
946  if (retval != ERROR_OK)
947  return retval;
948  if ((status & ISPCON_ISPFF) != 0) {
949  LOG_DEBUG("failure: 0x%" PRIx32, status);
950  /* if bit is set, then must write to it to clear it. */
952  if (retval != ERROR_OK)
953  return retval;
954  }
955  }
956 
957  /* done, */
958  LOG_DEBUG("Erase done.");
959 
960  return ERROR_OK;
961 }
962 
963 /* The write routine stub. */
964 static int numicro_write(struct flash_bank *bank, const uint8_t *buffer,
965  uint32_t offset, uint32_t count)
966 {
967  struct target *target = bank->target;
968  uint32_t timeout, status;
969  int retval = ERROR_OK;
970 
971  if (target->state != TARGET_HALTED) {
972  LOG_ERROR("Target not halted");
974  }
975 
976  LOG_INFO("Nuvoton NuMicro: Flash Write ...");
977 
979  retval = numicro_init_isp(target);
980  if (retval != ERROR_OK)
981  return retval;
982 
984  if (retval != ERROR_OK)
985  return retval;
986 
987  assert(offset % 4 == 0);
988  assert(count % 4 == 0);
989 
990  uint32_t words_remaining = count / 4;
991 
992  /* try using a block write */
993  retval = numicro_writeblock(bank, buffer, offset, words_remaining);
994 
995  if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
996  /* if block write failed (no sufficient working area),
997  * we use normal (slow) single word accesses */
998  LOG_WARNING("couldn't use block writes, falling back to single "
999  "memory accesses");
1000 
1001  /* program command */
1002  for (uint32_t i = 0; i < count; i += 4) {
1003  /* write 4 bytes each time with 0xff padding to avoid unaligned case */
1004  uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff};
1005  memcpy(padding, buffer + i, MIN(4, count - i));
1006 
1007  retval = target_write_u32(target,
1009  bank->base + offset + i);
1010  if (retval != ERROR_OK)
1011  return retval;
1012  retval = target_write_memory(target,
1014  4, 1, padding);
1015  if (retval != ERROR_OK)
1016  return retval;
1017  retval = target_write_u32(target,
1019  ISPTRG_ISPGO);
1020  if (retval != ERROR_OK)
1021  return retval;
1022 
1023  /* wait for busy to clear - check the GO flag */
1024  timeout = 100;
1025  for (;;) {
1026  retval = target_read_u32(target,
1028  &status);
1029  if (retval != ERROR_OK)
1030  return retval;
1031  if (status == 0)
1032  break;
1033  if (timeout-- <= 0) {
1034  LOG_DEBUG("timed out waiting for flash");
1035  return ERROR_FAIL;
1036  }
1037  busy_sleep(1); /* can use busy sleep for short times. */
1038  }
1039 
1040  }
1041  }
1042 
1043  /* check for failure */
1045  if (retval != ERROR_OK)
1046  return retval;
1047  if ((status & ISPCON_ISPFF) != 0) {
1048  LOG_DEBUG("failure: 0x%" PRIx32, status);
1049  /* if bit is set, then must write to it to clear it. */
1050  retval = target_write_u32(target,
1052  (status | ISPCON_ISPFF));
1053  if (retval != ERROR_OK)
1054  return retval;
1055  } else {
1056  LOG_DEBUG("Write OK");
1057  }
1058 
1059  /* done. */
1060  LOG_DEBUG("Write done.");
1061 
1062  return ERROR_OK;
1063 }
1064 
1065 static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type **cpu)
1066 {
1067  uint32_t part_id;
1068  int retval = ERROR_OK;
1069 
1071  /* Read NuMicro PartID */
1073  if (retval != ERROR_OK) {
1074  LOG_WARNING("NuMicro flash driver: Failed to Get PartID\n");
1076  }
1077 
1078  LOG_INFO("Device ID: 0x%08" PRIx32, part_id);
1079  /* search part numbers */
1080  for (size_t i = 0; i < ARRAY_SIZE(numicro_parts); i++) {
1081  if (part_id == numicro_parts[i].partid) {
1082  *cpu = &numicro_parts[i];
1083  LOG_INFO("Device Name: %s", (*cpu)->partname);
1084  return ERROR_OK;
1085  }
1086  }
1087 
1088  return ERROR_FAIL;
1089 }
1090 
1091 static int numicro_get_flash_size(struct flash_bank *bank, const struct numicro_cpu_type *cpu, uint32_t *flash_size)
1092 {
1093  for (size_t i = 0; i < cpu->n_banks; i++) {
1094  if (bank->base == cpu->bank[i].base) {
1095  *flash_size = cpu->bank[i].size;
1096  LOG_INFO("bank base = " TARGET_ADDR_FMT ", size = 0x%08"
1097  PRIx32, bank->base, *flash_size);
1098  return ERROR_OK;
1099  }
1100  }
1102 }
1103 
1104 static int numicro_probe(struct flash_bank *bank)
1105 {
1106  uint32_t flash_size, offset = 0;
1107  int num_pages;
1108  const struct numicro_cpu_type *cpu;
1109  struct target *target = bank->target;
1110  int retval = ERROR_OK;
1111 
1112  retval = numicro_get_cpu_type(target, &cpu);
1113  if (retval != ERROR_OK) {
1114  LOG_WARNING("NuMicro flash driver: Failed to detect a known part\n");
1116  }
1117 
1118  retval = numicro_get_flash_size(bank, cpu, &flash_size);
1119  if (retval != ERROR_OK) {
1120  LOG_WARNING("NuMicro flash driver: Failed to detect flash size\n");
1122  }
1123 
1124  num_pages = flash_size / m_page_size;
1125 
1126  bank->num_sectors = num_pages;
1127  bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
1128  bank->size = flash_size;
1129 
1130  for (int i = 0; i < num_pages; i++) {
1131  bank->sectors[i].offset = offset;
1132  bank->sectors[i].size = m_page_size;
1133  bank->sectors[i].is_erased = -1;
1134  bank->sectors[i].is_protected = 0;
1135  offset += m_page_size;
1136  }
1137 
1138  struct numicro_flash_bank *numicro_info = bank->driver_priv;
1139  numicro_info->probed = true;
1140  numicro_info->cpu = cpu;
1141  LOG_DEBUG("Nuvoton NuMicro: Probed ...");
1142 
1143  return ERROR_OK;
1144 }
1145 
1146 /* Standard approach to autoprobing. */
1148 {
1149  struct numicro_flash_bank *numicro_info = bank->driver_priv;
1150  if (numicro_info->probed)
1151  return ERROR_OK;
1152  return numicro_probe(bank);
1153 }
1154 
1155 
1156 /* This is the function called in the config file. */
1157 FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
1158 {
1159  struct numicro_flash_bank *bank_info;
1160 
1161  if (CMD_ARGC < 6)
1163 
1164  LOG_DEBUG("add flash_bank numicro %s", bank->name);
1165 
1166  bank_info = malloc(sizeof(struct numicro_flash_bank));
1167 
1168  memset(bank_info, 0, sizeof(struct numicro_flash_bank));
1169 
1170  bank->driver_priv = bank_info;
1171  bank->write_start_alignment = bank->write_end_alignment = 4;
1172 
1173  return ERROR_OK;
1174 }
1175 
1176 COMMAND_HANDLER(numicro_handle_read_isp_command)
1177 {
1178  uint32_t address;
1179  uint32_t ispdat;
1180  int retval = ERROR_OK;
1181 
1182  if (CMD_ARGC != 1)
1184 
1186 
1188 
1190  retval = numicro_init_isp(target);
1191  if (retval != ERROR_OK)
1192  return retval;
1193 
1194  retval = numicro_fmc_cmd(target, ISPCMD_READ, address, 0, &ispdat);
1195  if (retval != ERROR_OK)
1196  return retval;
1197 
1198  LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1199 
1200  return ERROR_OK;
1201 }
1202 
1203 COMMAND_HANDLER(numicro_handle_write_isp_command)
1204 {
1205  uint32_t address;
1206  uint32_t ispdat, rdat;
1207  int retval = ERROR_OK;
1208 
1209  if (CMD_ARGC != 2)
1211 
1213  COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat);
1214 
1216 
1218  retval = numicro_init_isp(target);
1219  if (retval != ERROR_OK)
1220  return retval;
1221 
1222  retval = numicro_fmc_cmd(target, ISPCMD_WRITE, address, ispdat, &rdat);
1223  if (retval != ERROR_OK)
1224  return retval;
1225 
1226  LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
1227  return ERROR_OK;
1228 }
1229 
1230 COMMAND_HANDLER(numicro_handle_chip_erase_command)
1231 {
1232  int retval = ERROR_OK;
1233  uint32_t rdat;
1234 
1235  if (CMD_ARGC != 0)
1237 
1239 
1241  retval = numicro_init_isp(target);
1242  if (retval != ERROR_OK)
1243  return retval;
1244 
1245  retval = numicro_fmc_cmd(target, ISPCMD_CHIPERASE, 0, 0, &rdat);
1246  if (retval != ERROR_OK) {
1247  command_print(CMD, "numicro chip_erase failed");
1248  return retval;
1249  }
1250 
1251  command_print(CMD, "numicro chip_erase complete");
1252 
1253  return ERROR_OK;
1254 }
1255 
1256 static const struct command_registration numicro_exec_command_handlers[] = {
1257  {
1258  .name = "read_isp",
1259  .handler = numicro_handle_read_isp_command,
1260  .usage = "address",
1261  .mode = COMMAND_EXEC,
1262  .help = "read flash through ISP.",
1263  },
1264  {
1265  .name = "write_isp",
1266  .handler = numicro_handle_write_isp_command,
1267  .usage = "address value",
1268  .mode = COMMAND_EXEC,
1269  .help = "write flash through ISP.",
1270  },
1271  {
1272  .name = "chip_erase",
1273  .handler = numicro_handle_chip_erase_command,
1274  .mode = COMMAND_EXEC,
1275  .help = "chip erase through ISP.",
1276  .usage = "",
1277  },
1279 };
1280 
1281 static const struct command_registration numicro_command_handlers[] = {
1282  {
1283  .name = "numicro",
1284  .mode = COMMAND_ANY,
1285  .help = "numicro flash command group",
1286  .usage = "",
1288  },
1290 };
1291 
1292 const struct flash_driver numicro_flash = {
1293  .name = "numicro",
1294  .commands = numicro_command_handlers,
1295  .flash_bank_command = numicro_flash_bank_command,
1296  .erase = numicro_erase,
1297  .write = numicro_write,
1298  .read = default_flash_read,
1299  .probe = numicro_probe,
1300  .auto_probe = numicro_auto_probe,
1301  .erase_check = default_flash_blank_check,
1302  .protect_check = numicro_protect_check,
1303  .free_driver_priv = default_flash_free_driver_priv,
1304 };
void init_reg_param(struct reg_param *param, const char *reg_name, uint32_t size, enum param_direction direction)
Definition: algorithm.c:29
void destroy_reg_param(struct reg_param *param)
Definition: algorithm.c:38
@ PARAM_OUT
Definition: algorithm.h:16
@ PARAM_IN_OUT
Definition: algorithm.h:17
@ ARM_ARCH_V6M
Definition: arm.h:56
@ ARM_MODE_THREAD
Definition: arm.h:94
static struct armv7m_common * target_to_armv7m(struct target *target)
Definition: armv7m.h:273
#define ARMV7M_COMMON_MAGIC
Definition: armv7m.h:229
Support functions to access arbitrary bits in a byte array.
static uint32_t buf_get_u32(const uint8_t *_buffer, unsigned int first, unsigned int num)
Retrieves num bits from _buffer, starting at the first bit, returning the bits in a 32-bit word.
Definition: binarybuffer.h:104
static void buf_set_u32(uint8_t *_buffer, unsigned int first, unsigned int num, uint32_t value)
Sets num bits in _buffer, starting at the first bit, using the bits in value.
Definition: binarybuffer.h:34
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:389
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:146
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:161
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:405
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:156
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:445
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:151
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:256
@ COMMAND_ANY
Definition: command.h:42
@ COMMAND_EXEC
Definition: command.h:40
uint64_t buffer
Pointer to data buffer to send over SPI.
Definition: dw-spi-helper.h:0
uint32_t buffer_size
Size of dw_spi_program::buffer.
Definition: dw-spi-helper.h:5
uint32_t address
Starting address. Sector aligned.
Definition: dw-spi-helper.h:0
uint8_t bank
Definition: esirisc.c:135
#define ERROR_FLASH_OPERATION_FAILED
Definition: flash/common.h:30
#define ERROR_FLASH_DST_BREAKS_ALIGNMENT
Definition: flash/common.h:32
int default_flash_blank_check(struct flash_bank *bank)
Provides default erased-bank check handling.
int default_flash_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
Provides default read implementation for flash memory.
void default_flash_free_driver_priv(struct flash_bank *bank)
Deallocates bank->driver_priv.
void busy_sleep(uint64_t ms)
Definition: log.c:491
#define LOG_WARNING(expr ...)
Definition: log.h:144
#define ERROR_FAIL
Definition: log.h:188
#define LOG_ERROR(expr ...)
Definition: log.h:147
#define LOG_INFO(expr ...)
Definition: log.h:141
#define LOG_DEBUG(expr ...)
Definition: log.h:124
#define ERROR_OK
Definition: log.h:182
#define ISPCON_ISPFF
Definition: numicro.c:87
#define NUMICRO_FLASH_ISPCON
Definition: numicro.c:49
#define NUMICRO_M0_FLASH_VERSION
Definition: numicro.c:34
FLASH_BANK_COMMAND_HANDLER(numicro_flash_bank_command)
Definition: numicro.c:1157
static int numicro_init_isp(struct target *target)
Definition: numicro.c:647
#define AHBCLK_SRAM_EN
Definition: numicro.c:77
static int numicro_probe(struct flash_bank *bank)
Definition: numicro.c:1104
static uint32_t m_address_bias_offset
Definition: numicro.c:561
static uint32_t m_page_size
Definition: numicro.c:560
#define NUMICRO_CONFIG0
Definition: numicro.c:66
static int numicro_protect_check(struct flash_bank *bank)
Definition: numicro.c:847
#define AHBCLK_ISP_EN
Definition: numicro.c:76
#define REG_KEY1
Definition: numicro.c:103
#define REG_KEY3
Definition: numicro.c:105
#define NUMICRO_PAGESIZE
Definition: numicro.c:109
#define NUMICRO_M0_FLASH_FMC2017
Definition: numicro.c:35
static bool numicro_is_m0_fmc2017(struct target *target)
Definition: numicro.c:564
static int numicro_auto_probe(struct flash_bank *bank)
Definition: numicro.c:1147
#define ISPCMD_READ
Definition: numicro.c:92
static int numicro_get_arm_arch(struct target *target)
Definition: numicro.c:590
#define NUMICRO_FLASH_CHEAT
Definition: numicro.c:54
static int numicro_reg_unlock(struct target *target)
Definition: numicro.c:610
#define NUMICRO_FLASH_ISPCMD
Definition: numicro.c:52
static const uint8_t numicro_flash_write_code[]
Definition: numicro.c:733
#define NUMICRO_FLASH_ISPADR
Definition: numicro.c:50
#define NUMICRO_FLASH_BASE
Definition: numicro.c:48
static int numicro_writeblock(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: numicro.c:738
const struct flash_driver numicro_flash
Definition: numicro.c:1292
#define ISPCON_CFGUEN
Definition: numicro.c:85
#define NUMICRO_FLASH_ISPDAT
Definition: numicro.c:51
#define ISPTRG_ISPGO
Definition: numicro.c:100
#define NUMICRO_FLASH_ISPTRG
Definition: numicro.c:53
#define NUMICRO_SYS_WRPROT
Definition: numicro.c:39
#define REG_KEY2
Definition: numicro.c:104
static uint32_t numicro_fmc_cmd(struct target *target, uint32_t cmd, uint32_t addr, uint32_t wdata, uint32_t *rdata)
Definition: numicro.c:689
COMMAND_HANDLER(numicro_handle_read_isp_command)
Definition: numicro.c:1176
#define ISPCON_ISPEN
Definition: numicro.c:80
static const struct numicro_cpu_type numicro_parts[]
Definition: numicro.c:135
#define NUMICRO_SYS_BASE
Definition: numicro.c:38
#define ISPCON_LDUEN
Definition: numicro.c:86
static int numicro_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
Definition: numicro.c:964
#define AHBCLK_TICK_EN
Definition: numicro.c:78
#define ISPCMD_ERASE
Definition: numicro.c:94
static int numicro_get_flash_size(struct flash_bank *bank, const struct numicro_cpu_type *cpu, uint32_t *flash_size)
Definition: numicro.c:1091
static int numicro_erase(struct flash_bank *bank, unsigned int first, unsigned int last)
Definition: numicro.c:893
#define CONFIG0_LOCK_MASK
Definition: numicro.c:89
#define ISPCON_APUEN
Definition: numicro.c:84
#define NUMICRO_SYSCLK_AHBCLK
Definition: numicro.c:46
#define NUMICRO_CONFIG1
Definition: numicro.c:67
static int numicro_get_cpu_type(struct target *target, const struct numicro_cpu_type **cpu)
Definition: numicro.c:1065
#define NUMICRO_MAX_FLASH_BANKS
Definition: numicro.c:111
#define NUMICRO_BANKS_GENERAL(aprom_size, data_size, ldrom_size, config_size)
Definition: numicro.c:128
static const struct command_registration numicro_exec_command_handlers[]
Definition: numicro.c:1256
#define ISPCMD_CHIPERASE
Definition: numicro.c:95
#define ISPCMD_WRITE
Definition: numicro.c:93
static const struct command_registration numicro_command_handlers[]
Definition: numicro.c:1281
#define MIN(a, b)
Definition: replacements.h:22
target_addr_t addr
Start address to search for the control block.
Definition: rtt/rtt.c:28
struct rtt_source source
Definition: rtt/rtt.c:23
enum arm_arch arch
ARM architecture version.
Definition: arm.h:203
unsigned int common_magic
Definition: armv7m.h:306
enum arm_mode core_mode
Definition: armv7m.h:308
struct arm arm
Definition: armv7m.h:234
const char * name
Definition: command.h:239
Provides details of a flash bank, available either on-chip or through a major interface.
Definition: nor/core.h:75
Provides the implementation-independent structure that defines all of the callbacks required by OpenO...
Definition: nor/driver.h:39
const char * name
Gives a human-readable name of this flash driver, This field is used to select and initialize the dri...
Definition: nor/driver.h:44
Describes the geometry and status of a single flash sector within a flash bank.
Definition: nor/core.h:28
unsigned int n_banks
Definition: numicro.c:123
struct numicro_flash_bank_type bank[NUMICRO_MAX_FLASH_BANKS]
Definition: numicro.c:124
uint32_t partid
Definition: numicro.c:122
char * partname
Definition: numicro.c:121
struct working_area * write_algorithm
Definition: numicro.c:554
const struct numicro_cpu_type * cpu
Definition: numicro.c:556
Definition: target.h:119
uint32_t working_area_size
Definition: target.h:161
enum target_state state
Definition: target.h:167
Definition: psoc6.c:83
target_addr_t address
Definition: target.h:89
int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer)
Definition: target.c:2410
int target_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_param, target_addr_t entry_point, target_addr_t exit_point, unsigned int timeout_ms, void *arch_info)
Downloads a target-specific native code algorithm to the target, and executes it.
Definition: target.c:787
int target_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer)
Write count items of size bytes to the memory of target at the address given.
Definition: target.c:1289
int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area)
Definition: target.c:2118
int target_write_u32(struct target *target, target_addr_t address, uint32_t value)
Definition: target.c:2676
int target_free_working_area(struct target *target, struct working_area *area)
Free a working area.
Definition: target.c:2174
int target_read_u32(struct target *target, target_addr_t address, uint32_t *value)
Definition: target.c:2602
struct target * get_current_target(struct command_context *cmd_ctx)
Definition: target.c:469
#define ERROR_TARGET_NOT_HALTED
Definition: target.h:818
@ TARGET_HALTED
Definition: target.h:58
#define ERROR_TARGET_RESOURCE_NOT_AVAILABLE
Definition: target.h:822
#define TARGET_ADDR_FMT
Definition: types.h:286
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
#define NULL
Definition: usb.h:16
uint8_t status[4]
Definition: vdebug.c:17
uint8_t cmd
Definition: vdebug.c:1
uint8_t offset[4]
Definition: vdebug.c:9
uint8_t count[4]
Definition: vdebug.c:22