OpenOCD
mini51.c
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2013 Cosmin Gorgovan *
3  * cosmin [at] linux-geek [dot] org *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
19  ***************************************************************************/
20 
21 /*
22  Flash driver for the Nuvoton NuMicro Mini51 and M051 series microcontrollers
23 
24  Part |APROM Size |Part ID (at 0x5000_0000)
25  ----------------------------------------------
26  MINI51LAN 4 KB 0x00205100
27  MINI51ZAN 4 KB 0x00205103
28  MINI51TAN 4 KB 0x00205104
29  MINI52LAN 8 KB 0x00205200
30  MINI52ZAN 8 KB 0x00205203
31  MINI52TAN 8 KB 0x00205204
32  MINI54LAN 16 KB 0x00205400
33  MINI54ZAN 16 KB 0x00205403
34  MINI54TAN 16 KB 0x00205404
35  M052LBN 8 KB 0x10005200
36  M054LBN 16 KB 0x10005400
37  M058LBN 32 KB 0x10005800
38  M0516LBN 64 KB 0x10005A00
39  M052ZBN 8 KB 0x10005203
40  M054ZBN 16 KB 0x10005403
41  M058ZBN 32 KB 0x10005803
42  M0516ZBN 64 KB 0x10005A03
43  M052LDN 8 KB 0x20005200
44  M054LDN 16 KB 0x20005400
45  M058LDN 32 KB 0x20005800
46  M0516LDN 64 KB 0x20005A00
47  M052ZDN 8 KB 0x20005203
48  M054ZDN 16 KB 0x20005403
49  M058ZDN 32 KB 0x20005803
50  M0516ZDN 64 KB 0x20005A03
51  M052LDE 8 KB 0x30005200
52  M054LDE 16 KB 0x30005400
53  M058LDE 32 KB 0x30005800
54  M0516LDE 64 KB 0x30005A00
55  M052ZDE 8 KB 0x30005203
56  M054ZDE 16 KB 0x30005403
57  M058ZDE 32 KB 0x30005803
58  M0516ZDE 64 KB 0x30005A03
59 
60  Datasheet & TRM
61  ---------------
62 
63  The ISP flash programming procedure is described on pages 130 and 131 of the (not very verbose) TRM.
64 
65  http://www.keil.com/dd/docs/datashts/nuvoton/mini51/da00-mini51_52_54c1.pdf
66 
67  M051 ISP datasheet pages 190-206:
68  http://www.nuvoton.com/hq/resource-download.jsp?tp_GUID=DA05-M052-54-58-516
69 
70  This driver
71  -----------
72 
73  * chip_erase, erase, read and write operations have been implemented;
74  * All operations support APROM, LDROM, FLASH DATA and CONFIG;
75 
76  Flash access limitations
77  ------------------------
78 
79  For implementing the read operation, please note that the APROM isn't memory mapped when booted from LDROM.
80 */
81 
82 #ifdef HAVE_CONFIG_H
83 #include "config.h"
84 #endif
85 
86 #include "imp.h"
87 
88 #define PART_ID_REG 0x50000000
89 #define IPRSTC1 0x50000008
90 #define REGLOCKADDR 0x50000100
91 #define ISPCON 0x5000C000
92 #define ISPADR 0x5000C004
93 #define ISPDAT 0x5000C008
94 #define ISPCMD 0x5000C00C
95 #define ISPTRG 0x5000C010
96 /* Undocumented isp register */
97 #define ISPUNKNOWN 0x5000C01C
98 
99 #define IPRSTC_CPU_RST 0x02
100 
101 #define ISPCON_ISPFF 0x40
102 #define ISPCON_LDUEN 0x20
103 #define ISPCON_CFGUEN 0x10
104 #define ISPCON_APUEN 0x08
105 #define ISPCON_BS_LDROM 0x02
106 #define ISPCON_ISPEN 0x01
107 
108 #define ISPCMD_READ 0x00
109 #define ISPCMD_PROGRAM 0x21
110 #define ISPCMD_ERASE 0x22
111 #define ISPCMD_CHIP_ERASE 0x26
112 
113 #define ISPTRG_ISPGO 0x01
114 
115 #define MINI51_APROM_BASE 0x00000000
116 #define MINI51_DATA_BASE 0x0001F000
117 #define MINI51_LDROM_BASE 0x00100000
118 #define MINI51_CONFIG_BASE 0x00300000
119 
120 #define MINI51_KB 1024
121 #define MINI51_PAGE_SIZE 512
122 #define MINI51_TIMEOUT 1000
123 
124 
125 #define ENSURE_OK(status) if (status != ERROR_OK) return status
126 
127 #define MINI51_MAX_FLASH_BANKS 4
128 
130  uint32_t base;
131  uint32_t size;
132 };
133 
135  char *name;
136  uint32_t ppid;
137  unsigned n_banks;
139 };
140 
141 #define MINI51_BANKS_MINI51(aprom_size) \
142  .n_banks = 3, \
143  { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_LDROM_BASE, 2*1024}, {MINI51_CONFIG_BASE, 512} }
144 
145 #define MINI51_BANKS_M051(aprom_size) \
146  .n_banks = 4, \
147  { {MINI51_APROM_BASE, (aprom_size)}, {MINI51_DATA_BASE, 4*1024}, {MINI51_LDROM_BASE, 4*1024}, \
148  {MINI51_CONFIG_BASE, 1024} }
149 
150 static const struct mini51_cpu_type mini51_cpu[] = {
151  { "MINI51LAN", 0x00205100, MINI51_BANKS_MINI51(4*1024) },
152  { "MINI51ZAN", 0x00205103, MINI51_BANKS_MINI51(4*1024) },
153  { "MINI51TAN", 0x00205104, MINI51_BANKS_MINI51(4*1024) },
154  { "MINI52LAN", 0x00205200, MINI51_BANKS_MINI51(8*1024) },
155  { "MINI52ZAN", 0x00205203, MINI51_BANKS_MINI51(8*1024) },
156  { "MINI52TAN", 0x00205204, MINI51_BANKS_MINI51(8*1024) },
157  { "MINI54LAN", 0x00205400, MINI51_BANKS_MINI51(16*1024) },
158  { "MINI54ZAN", 0x00205403, MINI51_BANKS_MINI51(16*1024) },
159  { "MINI54TAN", 0x00205404, MINI51_BANKS_MINI51(16*1024) },
160 
161  { "M052LBN", 0x10005200, MINI51_BANKS_M051(8*1024) },
162  { "M054LBN", 0x10005400, MINI51_BANKS_M051(16*1024) },
163  { "M058LBN", 0x10005800, MINI51_BANKS_M051(32*1024) },
164  { "M0516LBN", 0x10005A00, MINI51_BANKS_M051(64*1024) },
165  { "M052ZBN", 0x10005203, MINI51_BANKS_M051(8*1024) },
166  { "M054ZBN", 0x10005403, MINI51_BANKS_M051(16*1024) },
167  { "M058ZBN", 0x10005803, MINI51_BANKS_M051(32*1024) },
168  { "M0516ZBN", 0x10005A03, MINI51_BANKS_M051(64*1024) },
169  { "M052LDN", 0x20005200, MINI51_BANKS_M051(8*1024) },
170  { "M054LDN", 0x20005400, MINI51_BANKS_M051(16*1024) },
171  { "M058LDN", 0x20005800, MINI51_BANKS_M051(32*1024) },
172  { "M0516LDN", 0x20005A00, MINI51_BANKS_M051(64*1024) },
173  { "M052ZDN", 0x20005203, MINI51_BANKS_M051(8*1024) },
174  { "M054ZDN", 0x20005403, MINI51_BANKS_M051(16*1024) },
175  { "M058ZDN", 0x20005803, MINI51_BANKS_M051(32*1024) },
176  { "M0516ZDN", 0x20005A03, MINI51_BANKS_M051(64*1024) },
177  { "M052LDE", 0x30005200, MINI51_BANKS_M051(8*1024) },
178  { "M054LDE", 0x30005400, MINI51_BANKS_M051(16*1024) },
179  { "M058LDE", 0x30005800, MINI51_BANKS_M051(32*1024) },
180  { "M0516LDE", 0x30005A00, MINI51_BANKS_M051(64*1024) },
181  { "M052ZDE", 0x30005203, MINI51_BANKS_M051(8*1024) },
182  { "M054ZDE", 0x30005403, MINI51_BANKS_M051(16*1024) },
183  { "M058ZDE", 0x30005803, MINI51_BANKS_M051(32*1024) },
184  { "M0516ZDE", 0x30005A03, MINI51_BANKS_M051(64*1024) },
185 };
186 
188  bool probed;
189  const struct mini51_cpu_type *cpu;
190 };
191 
192 /* Private methods */
193 
194 static int mini51_unlock_reg(struct target *target)
195 {
196  int status;
197  status = target_write_u32(target, REGLOCKADDR, 0x59);
198  if (status != ERROR_OK)
199  return status;
200  status = target_write_u32(target, REGLOCKADDR, 0x16);
201  if (status != ERROR_OK)
202  return status;
203  status = target_write_u32(target, REGLOCKADDR, 0x88);
204  if (status != ERROR_OK)
205  return status;
206 
207  return ERROR_OK;
208 }
209 
210 
211 static int mini51_get_part_id(struct target *target, uint32_t *part_id)
212 {
213  int retu = target_read_u32(target, PART_ID_REG, part_id);
214  LOG_INFO("device id = 0x%08" PRIx32 "", *part_id);
215  return retu;
216 }
217 
218 static int mini51_get_cpu_type(struct target *target, const struct mini51_cpu_type** cpu)
219 {
220  uint32_t part_id;
221  int status;
222 
223  status = mini51_get_part_id(target, &part_id);
224  ENSURE_OK(status);
225 
226  for (size_t i = 0; i < sizeof(mini51_cpu)/sizeof(mini51_cpu[0]); i++) {
227  if (part_id == mini51_cpu[i].ppid) {
228  *cpu = &mini51_cpu[i];
229  LOG_INFO("device name = %s", (*cpu)->name);
230  return ERROR_OK;
231  }
232  }
233 
235 }
236 
237 static int mini51_get_flash_size(struct flash_bank *bank, const struct mini51_cpu_type *cpu, uint32_t *flash_size)
238 {
239  for (size_t i = 0; i < cpu->n_banks; i++) {
240  if (bank->base == cpu->bank[i].base) {
241  *flash_size = cpu->bank[i].size;
242  LOG_INFO("bank base = 0x%08" PRIx32 ", size = 0x%08" PRIx32 "", bank->base, *flash_size);
243  return ERROR_OK;
244  }
245  }
247 }
248 
249 static int mini51_isp_execute(struct target *target)
250 {
251  int status;
252  uint32_t ispcon;
253  int timeout;
254  uint32_t isptrg;
255 
256  /* start ISP operation */
257  status = target_write_u32(target, ISPTRG, ISPTRG_ISPGO);
258  ENSURE_OK(status);
259 
260  /* Wait for for command to finish executing */
261  timeout = MINI51_TIMEOUT;
262  do {
263  target_read_u32(target, ISPTRG, &isptrg);
264  timeout--;
265  } while ((isptrg & ISPTRG_ISPGO) && (timeout > 0));
266  if (timeout == 0) {
267  LOG_WARNING("Mini51 flash driver: Timeout executing flash command\n");
269  }
270 
271  /* Check for errors */
272  status = target_read_u32(target, ISPCON, &ispcon);
273  ENSURE_OK(status);
274  if (ispcon & ISPCON_ISPFF) {
275  LOG_WARNING("Mini51 flash driver: operation failed\n");
277  }
278  return status;
279 }
280 
281 static int mini51_isp_execute_cmd(struct target *target, uint32_t cmd, uint32_t address, uint32_t data)
282 {
283  int status;
284  status = target_write_u32(target, ISPDAT, data);
285  ENSURE_OK(status);
286  status = target_write_u32(target, ISPADR, address);
287  ENSURE_OK(status);
288  status = target_write_u32(target, ISPCMD, cmd);
289  ENSURE_OK(status);
290 
291  status = mini51_isp_execute(target);
292  return status;
293 }
294 
295 static int mini51_isp_execute_cmd_read(struct target *target, uint32_t cmd, uint32_t address, uint32_t *data)
296 {
297  int status;
298  status = target_write_u32(target, ISPADR, address);
299  ENSURE_OK(status);
300  status = target_write_u32(target, ISPCMD, cmd);
301  ENSURE_OK(status);
302 
303  status = mini51_isp_execute(target);
304  ENSURE_OK(status);
305 
306  status = target_read_u32(target, ISPDAT, data);
307  ENSURE_OK(status);
308 
309  return status;
310 }
311 
312 static int mini51_isp_enable(struct target *target)
313 {
314  int status;
315  uint32_t ispcon;
316 
317  if (target->state != TARGET_HALTED) {
318  LOG_ERROR("Target not halted");
320  }
321 
322  status = mini51_unlock_reg(target);
323  ENSURE_OK(status);
324  status = target_read_u32(target, ISPCON, &ispcon);
325  ENSURE_OK(status);
327  status = target_write_u32(target, ISPCON, ispcon);
328  return status;
329 }
330 
331 /* Public (API) methods */
332 
333 FLASH_BANK_COMMAND_HANDLER(mini51_flash_bank_command)
334 {
335  struct mini51_flash_bank *mini51_info;
336  mini51_info = malloc(sizeof(struct mini51_flash_bank));
337  mini51_info->probed = false;
338  bank->driver_priv = mini51_info;
339 
340  return ERROR_OK;
341 }
342 
343 static int mini51_protect_check(struct flash_bank *bank)
344 {
345  LOG_WARNING("Mini51 flash driver: protect_check not implemented yet\n");
346 
348 }
349 
350 static int mini51_read(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
351 {
352  int status;
353  uint32_t ispdat;
354  struct target *target = bank->target;
355 
356  if ((offset & 0x3) || (count & 0x3)) {
357  LOG_WARNING("Mini51 flash driver: unaligned access not supported\n");
359  }
360 
361  status = mini51_isp_enable(target);
362  ENSURE_OK(status);
363 
364  for (uint32_t i = offset; i < offset + count; i += 4) {
365  status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, bank->base + i, &ispdat);
366  memcpy(buffer, &ispdat, sizeof(ispdat));
367  ENSURE_OK(status);
368  buffer += sizeof(ispdat);
369  }
370 
371  return ERROR_OK;
372 }
373 
374 
375 static int mini51_erase(struct flash_bank *bank, int first, int last)
376 {
377  int status;
378  struct target *target = bank->target;
379 
380  /* Enable ISP */
381  status = mini51_isp_enable(target);
382  ENSURE_OK(status);
383 
384  for (int page_start = first; page_start <= last; page_start++) {
385  /* Set up erase command */
386  uint32_t address = bank->base + page_start*MINI51_PAGE_SIZE;
387  status = mini51_isp_execute_cmd(target, ISPCMD_ERASE, address, 0);
388  ENSURE_OK(status);
389  }
390 
391  return ERROR_OK;
392 }
393 
394 static int mini51_protect(struct flash_bank *bank, int set, int first, int last)
395 {
396  LOG_WARNING("Mini51 flash driver: protect operation not implemented yet\n");
397 
399 }
400 
401 static int mini51_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count)
402 {
403  int status;
404  uint32_t ispdat;
405  struct target *target = bank->target;
406 
407  if ((offset & 0x3) || (count & 0x3)) {
408  LOG_WARNING("Mini51 flash driver: unaligned access not supported\n");
410  }
411 
412  status = mini51_isp_enable(target);
413  ENSURE_OK(status);
414 
415  for (uint32_t i = offset; i < offset + count; i += 4) {
416  memcpy(&ispdat, buffer, sizeof(ispdat));
417  status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, bank->base + i, ispdat);
418  ENSURE_OK(status);
419  buffer += sizeof(ispdat);
420  }
421 
422  return ERROR_OK;
423 }
424 
425 static int mini51_probe(struct flash_bank *bank)
426 {
427  uint32_t flash_size;
428  int status;
429  int num_pages;
430  uint32_t offset = 0;
431  const struct mini51_cpu_type *cpu;
432  struct target *target = bank->target;
433 
434  status = mini51_get_cpu_type(target, &cpu);
435  if (status != ERROR_OK) {
436  LOG_WARNING("Mini51 flash driver: Failed to detect a known part\n");
438  }
439 
440  status = mini51_get_flash_size(bank, cpu, &flash_size);
441  if (status != ERROR_OK) {
442  LOG_WARNING("Mini51 flash driver: Failed to detect flash size\n");
444  }
445 
446  num_pages = flash_size / MINI51_PAGE_SIZE;
447 
448  bank->num_sectors = num_pages;
449  bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
450  bank->size = flash_size;
451 
452  for (int i = 0; i < num_pages; i++) {
453  bank->sectors[i].offset = offset;
454  bank->sectors[i].size = MINI51_PAGE_SIZE;
455  bank->sectors[i].is_erased = -1;
456  bank->sectors[i].is_protected = 0;
457  offset += MINI51_PAGE_SIZE;
458  }
459 
460  struct mini51_flash_bank *mini51_info = bank->driver_priv;
461  mini51_info->probed = true;
462  mini51_info->cpu = cpu;
463 
464  return ERROR_OK;
465 }
466 
467 static int mini51_auto_probe(struct flash_bank *bank)
468 {
469  struct mini51_flash_bank *mini51_info = bank->driver_priv;
470  if (mini51_info->probed)
471  return ERROR_OK;
472  return mini51_probe(bank);
473 }
474 
475 COMMAND_HANDLER(mini51_handle_read_isp_command)
476 {
477  uint32_t address;
478  uint32_t ispdat;
479  int status;
480 
481  if (CMD_ARGC != 1)
483 
484  COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
485 
487 
488  status = mini51_isp_enable(target);
489  ENSURE_OK(status);
490  status = mini51_isp_execute_cmd_read(target, ISPCMD_READ, address, &ispdat);
491  ENSURE_OK(status);
492  LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
493  return ERROR_OK;
494 }
495 
496 COMMAND_HANDLER(mini51_handle_write_isp_command)
497 {
498  uint32_t address;
499  uint32_t ispdat;
500  int status;
501 
502  if (CMD_ARGC != 2)
504 
505  COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
506  COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], ispdat);
507 
509 
510  status = mini51_isp_enable(target);
511  ENSURE_OK(status);
512  status = mini51_isp_execute_cmd(target, ISPCMD_PROGRAM, address, ispdat);
513  ENSURE_OK(status);
514  LOG_INFO("0x%08" PRIx32 ": 0x%08" PRIx32, address, ispdat);
515  return ERROR_OK;
516 }
517 
518 COMMAND_HANDLER(mini51_handle_chip_erase_command)
519 {
520  int status;
521  if (CMD_ARGC != 0)
523 
525 
526  status = mini51_isp_enable(target);
527  ENSURE_OK(status);
528  /* Write one to undocumented flash control register */
529  status = target_write_u32(target, ISPUNKNOWN, 1);
530  ENSURE_OK(status);
531 
532  status = mini51_isp_execute_cmd(target, ISPCMD_CHIP_ERASE, 0, 0);
533  ENSURE_OK(status);
534  return ERROR_OK;
535 }
536 
538  {
539  .name = "read_isp",
540  .handler = mini51_handle_read_isp_command,
541  .usage = "address",
542  .mode = COMMAND_EXEC,
543  .help = "read flash through ISP.",
544  },
545  {
546  .name = "write_isp",
547  .handler = mini51_handle_write_isp_command,
548  .usage = "address value",
549  .mode = COMMAND_EXEC,
550  .help = "write flash through ISP.",
551  },
552  {
553  .name = "chip_erase",
554  .handler = mini51_handle_chip_erase_command,
555  .mode = COMMAND_EXEC,
556  .help = "chip erase.",
557  },
559 };
560 
562  {
563  .name = "mini51",
564  .mode = COMMAND_ANY,
565  .help = "mini51 flash command group",
566  .usage = "",
568  },
570 };
571 
573  .name = "mini51",
574  .commands = mini51_command_handlers,
575  .flash_bank_command = mini51_flash_bank_command,
576  .erase = mini51_erase,
577  .protect = mini51_protect,
578  .write = mini51_write,
579  .read = mini51_read,
580  .probe = mini51_probe,
581  .auto_probe = mini51_auto_probe,
582  .erase_check = default_flash_blank_check,
583  .protect_check = mini51_protect_check,
584 };