niietcm4: support for NIIET's Cortex-M4 microcontrollers
[openocd.git] / src / flash / nor / niietcm4.c
1 /***************************************************************************
2 * Copyright (C) 2015 by Bogdan Kolbov *
3 * kolbov@niiet.ru *
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 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "imp.h"
25 #include <helper/binarybuffer.h>
26 #include <target/algorithm.h>
27 #include <target/armv7m.h>
28
29 #define FLASH_DRIVER_VER 0x00010000
30 #define CHIPID_ADDR 0xF0000000
31 #define K1921VK01T_ID 0x00000000
32
33 /*==============================================================================
34 * FLASH CONTROL REGS
35 *==============================================================================
36 */
37
38 #define MAIN_MEM_TYPE 0
39 #define INFO_MEM_TYPE 1
40 #define SERVICE_MODE_ERASE_ADDR 0x80030164
41 #define MAGIC_KEY 0xA442
42
43 /*-- BOOTFLASH ---------------------------------------------------------------*/
44 #define BOOTFLASH_BASE 0xA001C000
45 #define FMA (BOOTFLASH_BASE + 0x00)
46 #define FMD1 (BOOTFLASH_BASE + 0x04)
47 #define FMC (BOOTFLASH_BASE + 0x08)
48 #define FCIS (BOOTFLASH_BASE + 0x0C)
49 #define FCIM (BOOTFLASH_BASE + 0x10)
50 #define FCIC (BOOTFLASH_BASE + 0x14)
51 #define FMD2 (BOOTFLASH_BASE + 0x50)
52 #define FMD3 (BOOTFLASH_BASE + 0x54)
53 #define FMD4 (BOOTFLASH_BASE + 0x58)
54
55
56 /*---- FMC: Command register */
57 #define FMC_WRITE (1<<0) /* Writing in main region */
58 #define FMC_PAGE_ERASE (1<<1) /* Page erase the main region */
59 #define FMC_FULL_ERASE (1<<2) /* Erase full flash */
60 #define FMC_WRITE_IFB (1<<4) /* Writing in info region */
61 #define FMC_PAGEERASE_IFB (1<<5) /* Erase page of info region */
62 #define FMC_MAGIC_KEY (MAGIC_KEY<<16) /* Operation run command */
63
64 /*---- FCIS: Status register */
65 #define FCIS_OP_CMLT (1<<0) /* Completion flag operation */
66 #define FCIS_OP_ERROR (1<<1) /* Flag operation error */
67
68 /*---- FCIC: CLear status register */
69 #define FCIC_CLR_OPCMLT (1<<0) /* Cleare completion flag in register FCIS */
70 #define FCIC_CLR_OPERROR (1<<1) /* Cleare error flag in register FCIS */
71
72 /*-- USERFLASH ---------------------------------------------------------------*/
73 #define USERFLASH_PAGE_SIZE 256
74 #define USERFLASH_PAGE_TOTALNUM 256
75
76 #define USERFLASH_BASE 0xA0022000
77 #define UFMA (USERFLASH_BASE + 0x00)
78 #define UFMD (USERFLASH_BASE + 0x04)
79 #define UFMC (USERFLASH_BASE + 0x08)
80 #define UFCIS (USERFLASH_BASE + 0x0C)
81 #define UFCIM (USERFLASH_BASE + 0x10)
82 #define UFCIC (USERFLASH_BASE + 0x14)
83
84 /*---- UFMC: Command register */
85 #define UFMC_WRITE (1<<0) /* Writing in main region */
86 #define UFMC_PAGE_ERASE (1<<1) /* Paged erase the main region */
87 #define UFMC_FULL_ERASE (1<<2) /* Erase full flash */
88 #define UFMC_READ (1<<3) /* Reading from main region */
89 #define UFMC_WRITE_IFB (1<<4) /* Writing in info region */
90 #define UFMC_PAGEERASE_IFB (1<<5) /* Erase page of info region */
91 #define UFMC_READ_IFB (1<<6) /* Reading from info region */
92 #define UFMC_MAGIC_KEY (MAGIC_KEY<<16) /* Operation run command */
93
94 /*---- UFCIS: Status register */
95 #define UFCIS_OP_CMLT (1<<0) /* Completion flag operation */
96 #define UFCIS_OP_ERROR (1<<1) /* Flag operation error */
97
98 /*---- UFCIC: CLear status register */
99 #define UFCIC_CLR_OPCMLT (1<<0) /* Cleared completion flag in register FCIS */
100 #define UFCIC_CLR_OPERROR (1<<1) /* Cleared error flag in register FCIS */
101
102 /*---- In info userflash address space */
103 #define INFOWORD0_ADDR 0x00
104 #define INFOWORD0_BOOTFROM_IFB (1<<0) /* Boot from bootflash or bootflash_ifb */
105 #define INFOWORD0_EN_GPIO (1<<1) /* Remap to 0x00000000 extmem or bootflash */
106 #define INFOWORD0_BOOTFROM_IFB_POS 0
107 #define INFOWORD0_EN_GPIO_POS 1
108 #define INFOWORD0_EXTMEM_SEL_POS 3 /* Choose altfunc of gpio to work with extmem */
109
110 #define INFOWORD1_ADDR 0x01
111 #define INFOWORD1_PINNUM_POS 0 /* Choose gpio pin number to control extmem boot */
112 #define INFOWORD1_PORTNUM_POS 4 /* Choose gpio port to control extmem boot */
113
114 #define INFOWORD2_ADDR 0x02
115 #define INFOWORD2_LOCK_IFB_BF (1<<0) /* Protect info part of bootflash */
116
117 #define INFOWORD3_ADDR 0x03
118 #define INFOWORD3_LOCK_IFB_UF (1<<0) /* Protect info part of userflash */
119
120 #define BF_LOCK_ADDR 0x40
121 #define UF_LOCK_ADDR 0x80
122
123 /**
124 * Private data for flash driver.
125 */
126 struct niietcm4_flash_bank {
127 /* target params */
128 bool probed;
129 uint32_t chipid;
130 char *chip_name;
131 char chip_brief[4096];
132 /* not mapped userflash params */
133 uint32_t uflash_width;
134 uint32_t uflash_size;
135 uint32_t uflash_pagetotal;
136 uint32_t uflash_info_size;
137 uint32_t uflash_info_pagetotal;
138 /* boot params */
139 bool bflash_info_remap;
140 char *extmem_boot_port;
141 uint32_t extmem_boot_pin;
142 uint32_t extmem_boot_altfunc;
143 bool extmem_boot;
144 };
145
146 /*==============================================================================
147 * HELPER FUNCTIONS
148 *==============================================================================
149 */
150
151 /**
152 * Wait while operation with bootflash being performed and check result status
153 */
154 static int niietcm4_opstatus_check(struct flash_bank *bank)
155 {
156 struct target *target = bank->target;
157 int retval;
158 int timeout = 100;
159
160 uint32_t flash_status;
161 retval = target_read_u32(target, FCIS, &flash_status);
162 if (retval != ERROR_OK)
163 return retval;
164
165 while (flash_status == 0x00) {
166 retval = target_read_u32(target, FCIS, &flash_status);
167 if (retval != ERROR_OK)
168 return retval;
169 if (timeout-- <= 0) {
170 LOG_ERROR("Bootflash operation timeout");
171 return ERROR_FLASH_OPERATION_FAILED;
172 }
173 busy_sleep(1); /* can use busy sleep for short times. */
174 }
175 if (flash_status == FCIS_OP_ERROR) {
176 LOG_ERROR("Bootflash operation error");
177 return ERROR_FLASH_OPERATION_FAILED;
178 }
179 /* clear status */
180 uint32_t flash_cmd = FCIC_CLR_OPCMLT | FCIC_CLR_OPERROR;
181 retval = target_write_u32(target, FCIC, flash_cmd);
182 if (retval != ERROR_OK)
183 return retval;
184
185 return retval;
186 }
187
188 /**
189 * Wait while operation with userflash being performed and check result status
190 */
191 static int niietcm4_uopstatus_check(struct flash_bank *bank)
192 {
193 struct target *target = bank->target;
194 int retval;
195 int timeout = 100;
196
197 uint32_t uflash_status;
198 retval = target_read_u32(target, UFCIS, &uflash_status);
199 if (retval != ERROR_OK)
200 return retval;
201
202 while (uflash_status == 0x00) {
203 retval = target_read_u32(target, UFCIS, &uflash_status);
204 if (retval != ERROR_OK)
205 return retval;
206 if (timeout-- <= 0) {
207 LOG_ERROR("Userflash operation timeout");
208 return ERROR_FLASH_OPERATION_FAILED;
209 }
210 busy_sleep(1); /* can use busy sleep for short times. */
211 }
212 if (uflash_status == UFCIS_OP_ERROR) {
213 LOG_ERROR("Userflash operation error");
214 return ERROR_FLASH_OPERATION_FAILED;
215 }
216 /* clear status */
217 uint32_t uflash_cmd = UFCIC_CLR_OPCMLT | UFCIC_CLR_OPERROR;
218 retval = target_write_u32(target, UFCIC, uflash_cmd);
219 if (retval != ERROR_OK)
220 return retval;
221
222 return retval;
223 }
224
225 /**
226 * Dump page of userflash region.
227 * If we want to change some settings, we have to dump it full, because userflash is flash(not EEPROM).
228 * And correct write to flash can be performed only after erase.
229 * So without dump, changing one registers will clear others.
230 */
231 static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
232 {
233 struct target *target = bank->target;
234 int i, retval;
235
236 uint32_t uflash_cmd;
237 if (mem_type == INFO_MEM_TYPE)
238 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
239 else
240 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ;
241
242 int first = page_num*USERFLASH_PAGE_SIZE;
243 int last = first + USERFLASH_PAGE_SIZE;
244
245 for (i = first; i < last; i++) {
246 retval = target_write_u32(target, UFMA, i);
247 if (retval != ERROR_OK)
248 return retval;
249 retval = target_write_u32(target, UFMC, uflash_cmd);
250 if (retval != ERROR_OK)
251 return retval;
252 retval = niietcm4_uopstatus_check(bank);
253 if (retval != ERROR_OK)
254 return retval;
255 retval = target_read_u32(target, UFMD, &dump[i]);
256 if (retval != ERROR_OK)
257 return retval;
258 }
259
260 return retval;
261 }
262
263 /**
264 * Load modified page dump to userflash region page.
265 */
266 static int niietcm4_load_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type)
267 {
268 struct target *target = bank->target;
269 int i, retval;
270
271 uint32_t uflash_cmd;
272 if (mem_type == INFO_MEM_TYPE)
273 uflash_cmd = UFMC_MAGIC_KEY | UFMC_WRITE_IFB;
274 else
275 uflash_cmd = UFMC_MAGIC_KEY | UFMC_WRITE;
276
277 int first = page_num*USERFLASH_PAGE_SIZE;
278 int last = first + USERFLASH_PAGE_SIZE;
279
280 for (i = first; i < last; i++) {
281 retval = target_write_u32(target, UFMA, i);
282 if (retval != ERROR_OK)
283 return retval;
284 retval = target_write_u32(target, UFMD, dump[i]);
285 if (retval != ERROR_OK)
286 return retval;
287 retval = target_write_u32(target, UFMC, uflash_cmd);
288 if (retval != ERROR_OK)
289 return retval;
290 retval = niietcm4_uopstatus_check(bank);
291 if (retval != ERROR_OK)
292 return retval;
293 }
294
295 return retval;
296 }
297
298 /**
299 * Erase one page of userflash info or main region
300 */
301 static int niietcm4_uflash_page_erase(struct flash_bank *bank, int page_num, int mem_type)
302 {
303 struct target *target = bank->target;
304 int retval;
305
306 uint32_t uflash_cmd;
307 if (mem_type == INFO_MEM_TYPE)
308 uflash_cmd = UFMC_MAGIC_KEY | UFMC_PAGEERASE_IFB;
309 else
310 uflash_cmd = UFMC_MAGIC_KEY | UFMC_PAGE_ERASE;
311
312 retval = target_write_u32(target, UFMA, page_num*USERFLASH_PAGE_SIZE);
313 if (retval != ERROR_OK)
314 return retval;
315 retval = target_write_u32(target, UFMD, 0xFF);
316 if (retval != ERROR_OK)
317 return retval;
318 retval = target_write_u32(target, UFMC, uflash_cmd);
319 if (retval != ERROR_OK)
320 return retval;
321 /* status check */
322 retval = niietcm4_uopstatus_check(bank);
323 if (retval != ERROR_OK)
324 return retval;
325
326 return retval;
327 }
328
329 /**
330 * Enable or disable protection of userflash pages
331 */
332 static int niietcm4_uflash_protect(struct flash_bank *bank, int mem_type, int set, int first, int last)
333 {
334 int retval;
335 if (mem_type == INFO_MEM_TYPE) {
336 /* read dump */
337 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
338 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
339 if (retval != ERROR_OK)
340 return retval;
341 /* modify dump */
342 if (set)
343 uflash_dump[INFOWORD2_ADDR] &= ~INFOWORD3_LOCK_IFB_UF;
344 else
345 uflash_dump[INFOWORD2_ADDR] |= INFOWORD3_LOCK_IFB_UF;
346 /* erase page 0 userflash */
347 retval = niietcm4_uflash_page_erase(bank, 0, 1);
348 if (retval != ERROR_OK)
349 return retval;
350 /* write dump to userflash */
351 retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
352 if (retval != ERROR_OK)
353 return retval;
354 } else {
355 /* read dump */
356 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
357 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
358 if (retval != ERROR_OK)
359 return retval;
360 /* modify dump */
361 for (int i = first; i <= last; i++) {
362 uint32_t reg_num = i/8;
363 uint32_t bit_num = i%8;
364 if (set)
365 uflash_dump[UF_LOCK_ADDR+reg_num] &= ~(1<<bit_num);
366 else
367 uflash_dump[UF_LOCK_ADDR+reg_num] |= (1<<bit_num);
368 }
369 /* erase page 0 info userflash */
370 retval = niietcm4_uflash_page_erase(bank, 0, 1);
371 if (retval != ERROR_OK)
372 return retval;
373 /* write dump to userflash */
374 retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
375 if (retval != ERROR_OK)
376 return retval;
377 }
378
379 return retval;
380 }
381
382 /*==============================================================================
383 * FLASH COMMANDS
384 *==============================================================================
385 */
386 COMMAND_HANDLER(niietcm4_handle_uflash_read_byte_command)
387 {
388 if (CMD_ARGC < 3)
389 return ERROR_COMMAND_SYNTAX_ERROR;
390
391 struct flash_bank *bank;
392 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
393 if (retval != ERROR_OK)
394 return retval;
395 struct target *target = bank->target;
396
397 /* skip over flash bank */
398 CMD_ARGC--;
399 CMD_ARGV++;
400
401 uint32_t uflash_addr;
402 uint32_t uflash_cmd;
403 uint32_t uflash_data;
404
405 if (strcmp("info", CMD_ARGV[0]) == 0)
406 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
407 else if (strcmp("main", CMD_ARGV[0]) == 0)
408 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ;
409 else
410 return ERROR_COMMAND_SYNTAX_ERROR;
411
412 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], uflash_addr);
413
414 retval = target_write_u32(target, UFMA, uflash_addr);
415 if (retval != ERROR_OK)
416 return retval;
417 retval = target_write_u32(target, UFMC, uflash_cmd);
418 if (retval != ERROR_OK)
419 return retval;
420 /* status check */
421 retval = niietcm4_uopstatus_check(bank);
422 if (retval != ERROR_OK)
423 return retval;
424 retval = target_read_u32(target, UFMD, &uflash_data);
425 if (retval != ERROR_OK)
426 return retval;
427 command_print(CMD_CTX, "Read userflash %s region:\n"
428 "address = 0x%04x,\n"
429 "value = 0x%02x.", CMD_ARGV[0], uflash_addr, uflash_data);
430 return retval;
431 }
432
433 COMMAND_HANDLER(niietcm4_handle_uflash_write_byte_command)
434 {
435 if (CMD_ARGC < 4)
436 return ERROR_COMMAND_SYNTAX_ERROR;
437
438 struct flash_bank *bank;
439 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
440 if (retval != ERROR_OK)
441 return retval;
442 struct target *target = bank->target;
443
444 if (target->state != TARGET_HALTED) {
445 LOG_ERROR("Target not halted");
446 return ERROR_TARGET_NOT_HALTED;
447 }
448
449 /* skip over flash bank */
450 CMD_ARGC--;
451 CMD_ARGV++;
452
453 uint32_t uflash_addr;
454 uint32_t uflash_data;
455 int mem_type;
456
457 if (strcmp("info", CMD_ARGV[0]) == 0)
458 mem_type = 1;
459 else if (strcmp("main", CMD_ARGV[0]) == 0)
460 mem_type = 0;
461 else
462 return ERROR_COMMAND_SYNTAX_ERROR;
463
464 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], uflash_addr);
465 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], uflash_data);
466
467 int page_num = uflash_addr/USERFLASH_PAGE_SIZE;
468
469 command_print(CMD_CTX, "Write userflash %s region:\n"
470 "address = 0x%04x,\n"
471 "value = 0x%02x.\n"
472 "Please wait ... ", CMD_ARGV[0], uflash_addr, uflash_data);
473 /* dump */
474 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
475 niietcm4_dump_uflash_page(bank, uflash_dump, page_num, mem_type);
476
477 /* modify dump */
478 uflash_dump[uflash_addr%USERFLASH_PAGE_SIZE] = uflash_data;
479
480 /* erase page userflash */
481 niietcm4_uflash_page_erase(bank, page_num, mem_type);
482
483 /* write dump to userflash */
484 niietcm4_load_uflash_page(bank, uflash_dump, page_num, mem_type);
485 command_print(CMD_CTX, "done!");
486 return retval;
487 }
488
489 COMMAND_HANDLER(niietcm4_handle_uflash_full_erase_command)
490 {
491 if (CMD_ARGC < 1)
492 return ERROR_COMMAND_SYNTAX_ERROR;
493
494 struct flash_bank *bank;
495 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
496 if (retval != ERROR_OK)
497 return retval;
498 struct target *target = bank->target;
499
500 if (target->state != TARGET_HALTED) {
501 LOG_ERROR("Target not halted");
502 return ERROR_TARGET_NOT_HALTED;
503 }
504
505 uint32_t uflash_addr = 0;
506 uint32_t uflash_data = 0xFF;
507 uint32_t uflash_cmd = UFMC_MAGIC_KEY | UFMC_FULL_ERASE;
508
509 retval = target_write_u32(target, UFMA, uflash_addr);
510 if (retval != ERROR_OK)
511 return retval;
512 retval = target_write_u32(target, UFMD, uflash_data);
513 if (retval != ERROR_OK)
514 return retval;
515 retval = target_write_u32(target, UFMC, uflash_cmd);
516 if (retval != ERROR_OK)
517 return retval;
518 /* status check */
519 retval = niietcm4_uopstatus_check(bank);
520 if (retval != ERROR_OK)
521 return retval;
522 command_print(CMD_CTX, "Userflash full erase done!");
523
524 return retval;
525 }
526
527 COMMAND_HANDLER(niietcm4_handle_uflash_erase_command)
528 {
529 if (CMD_ARGC < 4)
530 return ERROR_COMMAND_SYNTAX_ERROR;
531
532 struct flash_bank *bank;
533 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
534 if (retval != ERROR_OK)
535 return retval;
536 struct target *target = bank->target;
537
538 if (target->state != TARGET_HALTED) {
539 LOG_ERROR("Target not halted");
540 return ERROR_TARGET_NOT_HALTED;
541 }
542
543 /* skip over flash bank */
544 CMD_ARGC--;
545 CMD_ARGV++;
546
547 unsigned int first, last;
548 int mem_type;
549
550 if (strcmp("info", CMD_ARGV[0]) == 0)
551 mem_type = 1;
552 else if (strcmp("main", CMD_ARGV[0]) == 0)
553 mem_type = 0;
554 else
555 return ERROR_COMMAND_SYNTAX_ERROR;
556
557 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], first);
558 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], last);
559 for (unsigned int i = first; i <= last; i++) {
560 retval = niietcm4_uflash_page_erase(bank, i, mem_type);
561 if (retval != ERROR_OK)
562 return retval;
563 }
564
565 command_print(CMD_CTX, "Erase %s userflash pages %d through %d done!", CMD_ARGV[0], first, last);
566
567 return retval;
568 }
569
570 COMMAND_HANDLER(niietcm4_handle_uflash_protect_check_command)
571 {
572 if (CMD_ARGC < 2)
573 return ERROR_COMMAND_SYNTAX_ERROR;
574
575 struct flash_bank *bank;
576 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
577 if (retval != ERROR_OK)
578 return retval;
579
580 struct target *target = bank->target;
581 if (target->state != TARGET_HALTED) {
582 LOG_ERROR("Target not halted");
583 return ERROR_TARGET_NOT_HALTED;
584 }
585
586 /* skip over flash bank */
587 CMD_ARGC--;
588 CMD_ARGV++;
589
590 int mem_type;
591 if (strcmp("info", CMD_ARGV[0]) == 0)
592 mem_type = 1;
593 else if (strcmp("main", CMD_ARGV[0]) == 0)
594 mem_type = 0;
595 else
596 return ERROR_COMMAND_SYNTAX_ERROR;
597
598 int i, j;
599 uint32_t uflash_addr;
600 uint32_t uflash_cmd;
601 uint32_t uflash_data;
602
603 /* chose between main userflash and info userflash */
604 if (mem_type == INFO_MEM_TYPE) {
605 uflash_addr = INFOWORD3_ADDR;
606 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
607 retval = target_write_u32(target, UFMA, uflash_addr);
608 if (retval != ERROR_OK)
609 return retval;
610 retval = target_write_u32(target, UFMC, uflash_cmd);
611 if (retval != ERROR_OK)
612 return retval;
613
614 /* status check */
615 retval = niietcm4_uopstatus_check(bank);
616 if (retval != ERROR_OK)
617 return retval;
618 retval = target_read_u32(target, UFMD, &uflash_data);
619 if (retval != ERROR_OK)
620 return retval;
621
622 if (uflash_data & INFOWORD3_LOCK_IFB_UF)
623 command_print(CMD_CTX, "All sectors of info userflash are not protected!");
624 else
625 command_print(CMD_CTX, "All sectors of info userflash are protected!");
626 } else {
627 uflash_addr = UF_LOCK_ADDR;
628 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
629 for (i = 0; i < USERFLASH_PAGE_TOTALNUM/8; i++) {
630 retval = target_write_u32(target, UFMA, uflash_addr);
631 if (retval != ERROR_OK)
632 return retval;
633 retval = target_write_u32(target, UFMC, uflash_cmd);
634 if (retval != ERROR_OK)
635 return retval;
636
637 /* status check */
638 retval = niietcm4_uopstatus_check(bank);
639 if (retval != ERROR_OK)
640 return retval;
641 retval = target_read_u32(target, UFMD, &uflash_data);
642 if (retval != ERROR_OK)
643 return retval;
644
645 for (j = 0; j < 8; j++) {
646 if (uflash_data & 0x1)
647 command_print(CMD_CTX, "Userflash sector #%03d: 0x%04x (0x100) is not protected!",
648 i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
649 else
650 command_print(CMD_CTX, "Userflash sector #%03d: 0x%04x (0x100) is protected!",
651 i*8+j, (i*8+j)*USERFLASH_PAGE_SIZE);
652 uflash_data = uflash_data >> 1;
653 }
654 uflash_addr++;
655 }
656 }
657
658 return retval;
659 }
660
661 COMMAND_HANDLER(niietcm4_handle_uflash_protect_command)
662 {
663 if (CMD_ARGC < 5)
664 return ERROR_COMMAND_SYNTAX_ERROR;
665
666 struct flash_bank *bank;
667 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
668 if (retval != ERROR_OK)
669 return retval;
670 struct target *target = bank->target;
671
672 if (target->state != TARGET_HALTED) {
673 LOG_ERROR("Target not halted");
674 return ERROR_TARGET_NOT_HALTED;
675 }
676
677 /* skip over flash bank */
678 CMD_ARGC--;
679 CMD_ARGV++;
680
681 int mem_type;
682 if (strcmp("info", CMD_ARGV[0]) == 0)
683 mem_type = 1;
684 else if (strcmp("main", CMD_ARGV[0]) == 0)
685 mem_type = 0;
686 else
687 return ERROR_COMMAND_SYNTAX_ERROR;
688
689 unsigned int first, last;
690 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], first);
691 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], last);
692
693 int set;
694 if (strcmp("on", CMD_ARGV[3]) == 0) {
695 command_print(CMD_CTX, "Try to enable %s userflash sectors %d through %d protection. Please wait ... ",
696 CMD_ARGV[0], first, last);
697 set = 1;
698 } else if (strcmp("off", CMD_ARGV[3]) == 0) {
699 command_print(CMD_CTX, "Try to disable %s userflash sectors %d through %d protection. Please wait ... ",
700 CMD_ARGV[0], first, last);
701 set = 0;
702 } else
703 return ERROR_COMMAND_SYNTAX_ERROR;
704
705 retval = niietcm4_uflash_protect(bank, mem_type, set, first, last);
706 if (retval != ERROR_OK)
707 return retval;
708
709 command_print(CMD_CTX, "done!");
710 return retval;
711 }
712
713 COMMAND_HANDLER(niietcm4_handle_bflash_info_remap_command)
714 {
715 if (CMD_ARGC < 2)
716 return ERROR_COMMAND_SYNTAX_ERROR;
717
718 struct flash_bank *bank;
719 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
720 if (retval != ERROR_OK)
721 return retval;
722 struct target *target = bank->target;
723
724 if (target->state != TARGET_HALTED) {
725 LOG_ERROR("Target not halted");
726 return ERROR_TARGET_NOT_HALTED;
727 }
728
729 /* skip over flash bank */
730 CMD_ARGC--;
731 CMD_ARGV++;
732
733 int set;
734 if (strcmp("on", CMD_ARGV[0]) == 0) {
735 command_print(CMD_CTX, "Try to enable bootflash info region remap. Please wait ...");
736 set = 1;
737 } else if (strcmp("off", CMD_ARGV[0]) == 0) {
738 command_print(CMD_CTX, "Try to disable bootflash info region remap. Please wait ...");
739 set = 0;
740 } else
741 return ERROR_COMMAND_SYNTAX_ERROR;
742
743 /* dump */
744 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
745 niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
746
747 /* modify dump */
748 if (set)
749 uflash_dump[INFOWORD0_ADDR] &= ~INFOWORD0_BOOTFROM_IFB;
750 else
751 uflash_dump[INFOWORD0_ADDR] |= INFOWORD0_BOOTFROM_IFB;
752
753 /* erase page userflash */
754 niietcm4_uflash_page_erase(bank, 0, 1);
755
756 /* write dump to userflash */
757 niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
758 command_print(CMD_CTX, "done!");
759
760 return retval;
761 }
762
763 COMMAND_HANDLER(niietcm4_handle_extmem_cfg_command)
764 {
765 if (CMD_ARGC < 4)
766 return ERROR_COMMAND_SYNTAX_ERROR;
767
768 struct flash_bank *bank;
769 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
770 if (retval != ERROR_OK)
771 return retval;
772 struct target *target = bank->target;
773
774 if (target->state != TARGET_HALTED) {
775 LOG_ERROR("Target not halted");
776 return ERROR_TARGET_NOT_HALTED;
777 }
778
779 /* skip over flash bank */
780 CMD_ARGC--;
781 CMD_ARGV++;
782
783 uint32_t port;
784 if (strcmp("gpioa", CMD_ARGV[0]) == 0)
785 port = 8;
786 else if (strcmp("gpiob", CMD_ARGV[0]) == 0)
787 port = 9;
788 else if (strcmp("gpioc", CMD_ARGV[0]) == 0)
789 port = 10;
790 else if (strcmp("gpiod", CMD_ARGV[0]) == 0)
791 port = 11;
792 else if (strcmp("gpioe", CMD_ARGV[0]) == 0)
793 port = 12;
794 else if (strcmp("gpiof", CMD_ARGV[0]) == 0)
795 port = 13;
796 else if (strcmp("gpiog", CMD_ARGV[0]) == 0)
797 port = 14;
798 else if (strcmp("gpioh", CMD_ARGV[0]) == 0)
799 port = 15;
800 else
801 return ERROR_COMMAND_SYNTAX_ERROR;
802
803 uint32_t pin;
804 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], pin);
805 if (pin > 15)
806 return ERROR_COMMAND_SYNTAX_ERROR;
807
808 uint32_t func;
809 if (strcmp("func1", CMD_ARGV[2]) == 0)
810 func = 0;
811 else if (strcmp("func3", CMD_ARGV[2]) == 0)
812 func = 3;
813 else
814 return ERROR_COMMAND_SYNTAX_ERROR;
815
816 command_print(CMD_CTX, "Try to configure external memory boot interface:\n"
817 "port = %s\n"
818 "pin = %s\n"
819 "func = %s\n"
820 "Please wait ...", CMD_ARGV[0], CMD_ARGV[1], CMD_ARGV[2]);
821 /* dump */
822 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
823 niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
824
825 /* modify dump */
826 uflash_dump[INFOWORD0_ADDR] &= ~(3<<INFOWORD0_EXTMEM_SEL_POS);
827 uflash_dump[INFOWORD0_ADDR] |= func<<INFOWORD0_EXTMEM_SEL_POS;
828 uflash_dump[INFOWORD1_ADDR] = (port<<INFOWORD1_PORTNUM_POS) | (pin<<INFOWORD1_PINNUM_POS);
829
830 /* erase page userflash */
831 niietcm4_uflash_page_erase(bank, 0, 1);
832
833 /* write dump to userflash */
834 niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
835 command_print(CMD_CTX, "done!");
836
837 return retval;
838 }
839
840 COMMAND_HANDLER(niietcm4_handle_extmem_boot_command)
841 {
842 if (CMD_ARGC < 2)
843 return ERROR_COMMAND_SYNTAX_ERROR;
844
845 struct flash_bank *bank;
846 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
847 if (retval != ERROR_OK)
848 return retval;
849 struct target *target = bank->target;
850
851 if (target->state != TARGET_HALTED) {
852 LOG_ERROR("Target not halted");
853 return ERROR_TARGET_NOT_HALTED;
854 }
855
856 /* skip over flash bank */
857 CMD_ARGC--;
858 CMD_ARGV++;
859
860 int set;
861
862 if (strcmp("on", CMD_ARGV[0]) == 0) {
863 command_print(CMD_CTX, "Try to enable boot from external memory. Please wait ...");
864 set = 1;
865 } else if (strcmp("off", CMD_ARGV[0]) == 0) {
866 command_print(CMD_CTX, "Try to disable boot from external memory. Please wait ...");
867 set = 0;
868 } else
869 return ERROR_COMMAND_SYNTAX_ERROR;
870
871 /* dump */
872 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
873 niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
874
875 /* modify dump */
876 if (set)
877 uflash_dump[INFOWORD0_ADDR] &= ~INFOWORD0_EN_GPIO;
878 else
879 uflash_dump[INFOWORD0_ADDR] |= INFOWORD0_EN_GPIO;
880
881 /* erase page userflash */
882 niietcm4_uflash_page_erase(bank, 0, 1);
883
884 /* write dump to userflash */
885 niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
886 command_print(CMD_CTX, "done!");
887
888 return retval;
889 }
890
891 COMMAND_HANDLER(niietcm4_handle_service_mode_erase_command)
892 {
893 if (CMD_ARGC < 1)
894 return ERROR_COMMAND_SYNTAX_ERROR;
895
896 struct flash_bank *bank;
897 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
898 if (retval != ERROR_OK)
899 return retval;
900 struct target *target = bank->target;
901
902 command_print(CMD_CTX, "Try to perform service mode erase. Please wait ...");
903
904 retval = target_write_u32(target, SERVICE_MODE_ERASE_ADDR, 1);
905 if (retval != ERROR_OK)
906 return retval;
907
908 int timeout = 500;
909 uint32_t status;
910
911 retval = target_read_u32(target, SERVICE_MODE_ERASE_ADDR, &status);
912 if (retval != ERROR_OK)
913 return retval;
914
915 while (status != 0x03) {
916 retval = target_read_u32(target, SERVICE_MODE_ERASE_ADDR, &status);
917 if (retval != ERROR_OK)
918 return retval;
919 if (timeout-- <= 0) {
920 LOG_ERROR("Service mode erase timeout");
921 return ERROR_FLASH_OPERATION_FAILED;
922 }
923 busy_sleep(1); /* can use busy sleep for short times. */
924 }
925 command_print(CMD_CTX, "done! All data erased.");
926
927 return retval;
928 }
929
930 COMMAND_HANDLER(niietcm4_handle_driver_info_command)
931 {
932 if (CMD_ARGC < 1)
933 return ERROR_COMMAND_SYNTAX_ERROR;
934
935 struct flash_bank *bank;
936 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
937 if (retval != ERROR_OK)
938 return retval;
939
940 command_print(CMD_CTX, "niietcm4 flash driver\n"
941 "version: %d.%d\n"
942 "author: Bogdan Kolbov\n"
943 "mail: kolbov@niiet.ru",
944 FLASH_DRIVER_VER>>16,
945 FLASH_DRIVER_VER&0xFFFF);
946
947 return retval;
948 }
949
950 static const struct command_registration niietcm4_exec_command_handlers[] = {
951 {
952 .name = "uflash_read_byte",
953 .handler = niietcm4_handle_uflash_read_byte_command,
954 .mode = COMMAND_EXEC,
955 .usage = "bank_id ('main'|'info') address",
956 .help = "Read byte from main or info userflash region",
957 },
958 {
959 .name = "uflash_write_byte",
960 .handler = niietcm4_handle_uflash_write_byte_command,
961 .mode = COMMAND_EXEC,
962 .usage = "bank_id ('main'|'info') address value",
963 .help = "Write byte to main or info userflash region",
964 },
965 {
966 .name = "uflash_full_erase",
967 .handler = niietcm4_handle_uflash_full_erase_command,
968 .mode = COMMAND_EXEC,
969 .usage = "bank_id",
970 .help = "Erase all userflash including info region",
971 },
972 {
973 .name = "uflash_erase",
974 .handler = niietcm4_handle_uflash_erase_command,
975 .mode = COMMAND_EXEC,
976 .usage = "bank_id ('main'|'info') first_sector_num last_sector_num",
977 .help = "Erase sectors of main or info userflash region, starting at sector first up to and including last.",
978 },
979 {
980 .name = "uflash_protect_check",
981 .handler = niietcm4_handle_uflash_protect_check_command,
982 .mode = COMMAND_EXEC,
983 .usage = "bank_id ('main'|'info')",
984 .help = "Check sectors protect.",
985 },
986 {
987 .name = "uflash_protect",
988 .handler = niietcm4_handle_uflash_protect_command,
989 .mode = COMMAND_EXEC,
990 .usage = "bank_id ('main'|'info') first_sector_num last_sector_num ('on'|'off')",
991 .help = "Protect sectors of main or info userflash region, starting at sector first up to and including last.",
992 },
993 {
994 .name = "bflash_info_remap",
995 .handler = niietcm4_handle_bflash_info_remap_command,
996 .mode = COMMAND_EXEC,
997 .usage = "bank_id ('on'|'off')",
998 .help = "Enable remapping bootflash info region to 0x00000000 (or 0x40000000 if external memory boot used).",
999 },
1000 {
1001 .name = "extmem_cfg",
1002 .handler = niietcm4_handle_extmem_cfg_command,
1003 .mode = COMMAND_EXEC,
1004 .usage = "bank_id ('gpioa'|'gpiob'|'gpioc'|'gpiod'|'gpioe'|'gpiof'|'gpiog'|'gpioh') pin_num ('func1'|'func3')",
1005 .help = "Configure external memory interface for boot.",
1006 },
1007 {
1008 .name = "extmem_boot",
1009 .handler = niietcm4_handle_extmem_boot_command,
1010 .mode = COMMAND_EXEC,
1011 .usage = "bank_id ('on'|'off')",
1012 .help = "Enable boot from external memory.",
1013 },
1014 {
1015 .name = "service_mode_erase",
1016 .handler = niietcm4_handle_service_mode_erase_command,
1017 .mode = COMMAND_EXEC,
1018 .usage = "bank_id",
1019 .help = "Perform emergency erase of all flash (bootflash and userflash).",
1020 },
1021 {
1022 .name = "driver_info",
1023 .handler = niietcm4_handle_driver_info_command,
1024 .mode = COMMAND_EXEC,
1025 .usage = "bank_id",
1026 .help = "Show information about flash driver.",
1027 },
1028 COMMAND_REGISTRATION_DONE
1029 };
1030
1031 static const struct command_registration niietcm4_command_handlers[] = {
1032 {
1033 .name = "niietcm4",
1034 .mode = COMMAND_ANY,
1035 .help = "niietcm4 flash command group",
1036 .usage = "",
1037 .chain = niietcm4_exec_command_handlers,
1038 },
1039 COMMAND_REGISTRATION_DONE
1040 };
1041
1042 /*==============================================================================
1043 * FLASH INTERFACE
1044 *==============================================================================
1045 */
1046
1047 FLASH_BANK_COMMAND_HANDLER(niietcm4_flash_bank_command)
1048 {
1049 struct niietcm4_flash_bank *niietcm4_info;
1050
1051 if (CMD_ARGC < 7)
1052 return ERROR_COMMAND_SYNTAX_ERROR;
1053
1054 niietcm4_info = malloc(sizeof(struct niietcm4_flash_bank));
1055
1056 bank->driver_priv = niietcm4_info;
1057
1058 /* information will be updated by probing */
1059 niietcm4_info->probed = false;
1060 niietcm4_info->chipid = 0;
1061 niietcm4_info->chip_name = NULL;
1062 niietcm4_info->uflash_width = 0;
1063 niietcm4_info->uflash_size = 0;
1064 niietcm4_info->uflash_pagetotal = 0;
1065 niietcm4_info->uflash_info_size = 0;
1066 niietcm4_info->uflash_info_pagetotal = 0;
1067 niietcm4_info->bflash_info_remap = false;
1068 niietcm4_info->extmem_boot_port = NULL;
1069 niietcm4_info->extmem_boot_pin = 0;
1070 niietcm4_info->extmem_boot_altfunc = 0;
1071 niietcm4_info->extmem_boot = false;
1072
1073 return ERROR_OK;
1074 }
1075
1076 static int niietcm4_protect_check(struct flash_bank *bank)
1077 {
1078 struct target *target = bank->target;
1079 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1080
1081 int retval = ERROR_FLASH_OPERATION_FAILED;
1082 int set;
1083 uint32_t uflash_addr;
1084 uint32_t uflash_cmd;
1085 uint32_t uflash_data;
1086 /* chose between main bootflash and info bootflash */
1087 if (niietcm4_info->bflash_info_remap) {
1088 uflash_addr = INFOWORD2_ADDR;
1089 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
1090 retval = target_write_u32(target, UFMA, uflash_addr);
1091 if (retval != ERROR_OK)
1092 return retval;
1093 retval = target_write_u32(target, UFMC, uflash_cmd);
1094 if (retval != ERROR_OK)
1095 return retval;
1096
1097 /* status check */
1098 retval = niietcm4_uopstatus_check(bank);
1099 if (retval != ERROR_OK)
1100 return retval;
1101 retval = target_read_u32(target, UFMD, &uflash_data);
1102 if (retval != ERROR_OK)
1103 return retval;
1104
1105 if (uflash_data & INFOWORD2_LOCK_IFB_BF)
1106 set = 0;
1107 else
1108 set = 1;
1109 bank->sectors[0].is_protected = set;
1110 } else {
1111 uflash_addr = BF_LOCK_ADDR;
1112 uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
1113 for (int i = 0; i < bank->num_sectors/8; i++) {
1114 retval = target_write_u32(target, UFMA, uflash_addr);
1115 if (retval != ERROR_OK)
1116 return retval;
1117 retval = target_write_u32(target, UFMC, uflash_cmd);
1118 if (retval != ERROR_OK)
1119 return retval;
1120
1121 /* status check */
1122 retval = niietcm4_uopstatus_check(bank);
1123 if (retval != ERROR_OK)
1124 return retval;
1125 retval = target_read_u32(target, UFMD, &uflash_data);
1126 if (retval != ERROR_OK)
1127 return retval;
1128
1129 for (int j = 0; j < 8; j++) {
1130 if (uflash_data & 0x1)
1131 set = 0;
1132 else
1133 set = 1;
1134 bank->sectors[i*8+j].is_protected = set;
1135 uflash_data = uflash_data >> 1;
1136 }
1137 uflash_addr++;
1138 }
1139 }
1140
1141 return retval;
1142 }
1143
1144 static int niietcm4_mass_erase(struct flash_bank *bank)
1145 {
1146 struct target *target = bank->target;
1147
1148 int retval;
1149 uint32_t flash_cmd;
1150
1151 /* start mass erase */
1152 flash_cmd = FMC_MAGIC_KEY | FMC_FULL_ERASE;
1153 retval = target_write_u32(target, FMC, flash_cmd);
1154 if (retval != ERROR_OK)
1155 return retval;
1156
1157 /* status check */
1158 retval = niietcm4_opstatus_check(bank);
1159 if (retval != ERROR_OK)
1160 return retval;
1161
1162 return retval;
1163 }
1164
1165 static int niietcm4_erase(struct flash_bank *bank, int first, int last)
1166 {
1167 struct target *target = bank->target;
1168 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1169 int retval = ERROR_FLASH_OPERATION_FAILED;
1170
1171 if (bank->target->state != TARGET_HALTED) {
1172 LOG_ERROR("Target not halted");
1173 return ERROR_TARGET_NOT_HALTED;
1174 }
1175
1176 if ((first == 0) && (last == (bank->num_sectors - 1))) {
1177 retval = niietcm4_mass_erase(bank);
1178 return retval;
1179 }
1180
1181 /* chose between main bootflash and info bootflash */
1182 uint32_t flash_cmd, flash_addr;
1183 if (niietcm4_info->bflash_info_remap)
1184 flash_cmd = FMC_MAGIC_KEY | FMC_PAGEERASE_IFB;
1185 else
1186 flash_cmd = FMC_MAGIC_KEY | FMC_PAGE_ERASE;
1187
1188 /* erasing pages */
1189 unsigned int page_size = bank->size / bank->num_sectors;
1190 for (int i = first; i <= last; i++) {
1191 /* current page addr */
1192 flash_addr = i*page_size;
1193 retval = target_write_u32(target, FMA, flash_addr);
1194 if (retval != ERROR_OK)
1195 return retval;
1196
1197 /* start erase */
1198 retval = target_write_u32(target, FMC, flash_cmd);
1199 if (retval != ERROR_OK)
1200 return retval;
1201
1202 /* status check */
1203 retval = niietcm4_opstatus_check(bank);
1204 if (retval != ERROR_OK)
1205 return retval;
1206
1207 bank->sectors[i].is_erased = 1;
1208 }
1209
1210 return retval;
1211 }
1212
1213 static int niietcm4_protect(struct flash_bank *bank, int set, int first, int last)
1214 {
1215 struct target *target = bank->target;
1216 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1217
1218 int retval;
1219
1220 if (target->state != TARGET_HALTED) {
1221 LOG_ERROR("Target not halted");
1222 return ERROR_TARGET_NOT_HALTED;
1223 }
1224
1225 LOG_INFO("Plese wait ..."); /* it`s quite a long process */
1226 /* chose between main bootflash and info bootflash */
1227 if (niietcm4_info->bflash_info_remap) {
1228 /* dump */
1229 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
1230 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
1231 if (retval != ERROR_OK)
1232 return retval;
1233 /* modify dump */
1234 if (set)
1235 uflash_dump[INFOWORD2_ADDR] &= ~INFOWORD2_LOCK_IFB_BF;
1236 else
1237 uflash_dump[INFOWORD2_ADDR] |= INFOWORD2_LOCK_IFB_BF;
1238 /* erase page 0 userflash */
1239 retval = niietcm4_uflash_page_erase(bank, 0, 1);
1240 if (retval != ERROR_OK)
1241 return retval;
1242 /* write dump to userflash */
1243 retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
1244 if (retval != ERROR_OK)
1245 return retval;
1246 } else {
1247 /* read dump*/
1248 uint32_t uflash_dump[USERFLASH_PAGE_SIZE];
1249 retval = niietcm4_dump_uflash_page(bank, uflash_dump, 0, 1);
1250 if (retval != ERROR_OK)
1251 return retval;
1252 /* modify dump */
1253 for (int i = first; i <= last; i++) {
1254 uint32_t reg_num = i/8;
1255 uint32_t bit_num = i%8;
1256 if (set)
1257 uflash_dump[BF_LOCK_ADDR+reg_num] &= ~(1<<bit_num);
1258 else
1259 uflash_dump[BF_LOCK_ADDR+reg_num] |= (1<<bit_num);
1260 }
1261 /* erase page 0 info userflash */
1262 retval = niietcm4_uflash_page_erase(bank, 0, 1);
1263 if (retval != ERROR_OK)
1264 return retval;
1265 /* write dump to userflash */
1266 retval = niietcm4_load_uflash_page(bank, uflash_dump, 0, 1);
1267 if (retval != ERROR_OK)
1268 return retval;
1269 }
1270
1271 return retval;
1272 }
1273
1274 static int niietcm4_write_block(struct flash_bank *bank, const uint8_t *buffer,
1275 uint32_t offset, uint32_t count)
1276 {
1277 struct target *target = bank->target;
1278 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1279 uint32_t buffer_size = 32768 + 8; /* 8 bytes for rp and wp */
1280 struct working_area *write_algorithm;
1281 struct working_area *source;
1282 uint32_t address = bank->base + offset;
1283 struct reg_param reg_params[5];
1284 struct armv7m_algorithm armv7m_info;
1285 int retval = ERROR_OK;
1286
1287 /* see contrib/loaders/flash/k1921vk01t.S for src */
1288 static const uint8_t niietcm4_flash_write_code[] = {
1289 0x14, 0x4f, 0x16, 0x68, 0x00, 0x2e, 0x23, 0xd0, 0x55, 0x68, 0xb5, 0x42, 0xf9, 0xd0, 0x2e, 0x68,
1290 0x7e, 0x60, 0x04, 0x35, 0x2e, 0x68, 0x3e, 0x65, 0x04, 0x35, 0x2e, 0x68, 0x7e, 0x65, 0x04, 0x35,
1291 0x2e, 0x68, 0xbe, 0x65, 0x04, 0x35, 0x3c, 0x60, 0x10, 0x34, 0xb8, 0x60, 0xfe, 0x68, 0x00, 0x2e,
1292 0xfc, 0xd0, 0x02, 0x2e, 0x0a, 0xd0, 0x01, 0x26, 0x7e, 0x61, 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46,
1293 0x08, 0x35, 0x55, 0x60, 0x01, 0x39, 0x00, 0x29, 0x02, 0xd0, 0xda, 0xe7, 0x00, 0x20, 0x50, 0x60,
1294 0x30, 0x46, 0x00, 0xbe, 0x00, 0xc0, 0x01, 0xa0
1295 };
1296
1297 /* flash write code */
1298 if (target_alloc_working_area(target, sizeof(niietcm4_flash_write_code),
1299 &write_algorithm) != ERROR_OK) {
1300 LOG_WARNING("no working area available, can't do block memory writes");
1301 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1302 };
1303
1304 retval = target_write_buffer(target, write_algorithm->address,
1305 sizeof(niietcm4_flash_write_code), niietcm4_flash_write_code);
1306 if (retval != ERROR_OK)
1307 return retval;
1308
1309 /* memory buffer */
1310 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
1311 buffer_size /= 2;
1312 buffer_size &= ~15UL; /* Make sure it's 16 byte aligned */
1313 buffer_size += 8; /* And 8 bytes for WP and RP */
1314 if (buffer_size <= 256) {
1315 /* we already allocated the writing code, but failed to get a
1316 * buffer, free the algorithm */
1317 target_free_working_area(target, write_algorithm);
1318
1319 LOG_WARNING("no large enough working area available, can't do block memory writes");
1320 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
1321 }
1322 };
1323
1324 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* write_cmd base (in), status (out) */
1325 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (128bit) */
1326 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
1327 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
1328 init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
1329
1330 uint32_t flash_cmd;
1331 if (niietcm4_info->bflash_info_remap)
1332 flash_cmd = FMC_MAGIC_KEY | FMC_WRITE_IFB;
1333 else
1334 flash_cmd = FMC_MAGIC_KEY | FMC_WRITE;
1335
1336 buf_set_u32(reg_params[0].value, 0, 32, flash_cmd);
1337 buf_set_u32(reg_params[1].value, 0, 32, count);
1338 buf_set_u32(reg_params[2].value, 0, 32, source->address);
1339 buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
1340 buf_set_u32(reg_params[4].value, 0, 32, address);
1341
1342 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
1343 armv7m_info.core_mode = ARM_MODE_THREAD;
1344
1345 retval = target_run_flash_async_algorithm(target, buffer, count, 16,
1346 0, NULL,
1347 5, reg_params,
1348 source->address, source->size,
1349 write_algorithm->address, 0,
1350 &armv7m_info);
1351
1352 if (retval == ERROR_FLASH_OPERATION_FAILED)
1353 LOG_ERROR("flash write failed at address 0x%"PRIx32,
1354 buf_get_u32(reg_params[4].value, 0, 32));
1355
1356 target_free_working_area(target, source);
1357 target_free_working_area(target, write_algorithm);
1358
1359 destroy_reg_param(&reg_params[0]);
1360 destroy_reg_param(&reg_params[1]);
1361 destroy_reg_param(&reg_params[2]);
1362 destroy_reg_param(&reg_params[3]);
1363 destroy_reg_param(&reg_params[4]);
1364
1365 return retval;
1366 }
1367
1368 static int niietcm4_write(struct flash_bank *bank, const uint8_t *buffer,
1369 uint32_t offset, uint32_t count)
1370 {
1371 struct target *target = bank->target;
1372 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1373
1374 if (bank->target->state != TARGET_HALTED) {
1375 LOG_ERROR("Target not halted");
1376 return ERROR_TARGET_NOT_HALTED;
1377 }
1378
1379 if (offset & 0x3) {
1380 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
1381 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
1382 }
1383
1384 int retval;
1385
1386 /* try using block write */
1387 retval = niietcm4_write_block(bank, buffer, offset, count/16);
1388 uint32_t flash_addr, flash_cmd, flash_data;
1389
1390 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
1391 /* if block write failed (no sufficient working area),
1392 * we use normal (slow) single halfword accesses */
1393 LOG_WARNING("Can't use block writes, falling back to single memory accesses");
1394 LOG_INFO("Plese wait ..."); /* it`s quite a long process */
1395
1396 /* chose between main bootflash and info bootflash */
1397 if (niietcm4_info->bflash_info_remap)
1398 flash_cmd = FMC_MAGIC_KEY | FMC_WRITE_IFB;
1399 else
1400 flash_cmd = FMC_MAGIC_KEY | FMC_WRITE;
1401
1402 /* write 16 bytes per try */
1403 for (unsigned int i = 0; i < count; i += 16) {
1404 /* current addr */
1405 LOG_INFO("%d byte of %d", i, count);
1406 flash_addr = offset + i;
1407 retval = target_write_u32(target, FMA, flash_addr);
1408 if (retval != ERROR_OK)
1409 return retval;
1410
1411 /* if there's an odd number of bytes, the data has to be padded */
1412 uint8_t padding[16] = { 0xff, 0xff, 0xff, 0xff,
1413 0xff, 0xff, 0xff, 0xff,
1414 0xff, 0xff, 0xff, 0xff,
1415 0xff, 0xff, 0xff, 0xff};
1416 memcpy(padding, buffer + i, MIN(16, count-i));
1417
1418 /* place in reg 16 bytes of data */
1419 flash_data = (padding[3]<<24) | (padding[2]<<16) | (padding[1]<<8) | padding[0];
1420 retval = target_write_u32(target, FMD1, flash_data);
1421 if (retval != ERROR_OK)
1422 return retval;
1423 flash_data = (padding[7]<<24) | (padding[6]<<16) | (padding[5]<<8) | padding[4];
1424 retval = target_write_u32(target, FMD2, flash_data);
1425 if (retval != ERROR_OK)
1426 return retval;
1427 flash_data = (padding[11]<<24) | (padding[10]<<16) | (padding[9]<<8) | padding[8];
1428 retval = target_write_u32(target, FMD3, flash_data);
1429 if (retval != ERROR_OK)
1430 return retval;
1431 flash_data = (padding[15]<<24) | (padding[14]<<16) | (padding[13]<<8) | padding[12];
1432 retval = target_write_u32(target, FMD4, flash_data);
1433 if (retval != ERROR_OK)
1434 return retval;
1435
1436 /* write start */
1437 retval = target_write_u32(target, FMC, flash_cmd);
1438 if (retval != ERROR_OK)
1439 return retval;
1440
1441 /* status check */
1442 retval = niietcm4_opstatus_check(bank);
1443 if (retval != ERROR_OK)
1444 return retval;
1445 }
1446
1447 }
1448
1449 return retval;
1450 }
1451
1452 static int niietcm4_probe_k1921vk01t(struct flash_bank *bank)
1453 {
1454 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1455 struct target *target = bank->target;
1456 int retval;
1457
1458 niietcm4_info->chip_name = "K1921VK01T";
1459
1460 /* check if we in service mode */
1461 uint32_t service_mode;
1462 retval = target_read_u32(target, 0x80017000, &service_mode);
1463 if (retval != ERROR_OK)
1464 return retval;
1465 service_mode = (service_mode>>2) & 0x1;
1466
1467 if (!service_mode) {
1468 niietcm4_info->uflash_width = 8;
1469 niietcm4_info->uflash_size = 0x10000;
1470 niietcm4_info->uflash_pagetotal = 256;
1471 niietcm4_info->uflash_info_size = 0x200;
1472 niietcm4_info->uflash_info_pagetotal = 2;
1473
1474 uint32_t uflash_data[2];
1475 uint32_t uflash_cmd = UFMC_MAGIC_KEY | UFMC_READ_IFB;
1476 for (int i = 0; i < 2; i++) {
1477 retval = target_write_u32(target, UFMA, i);
1478 if (retval != ERROR_OK)
1479 return retval;
1480 retval = target_write_u32(target, UFMC, uflash_cmd);
1481 if (retval != ERROR_OK)
1482 return retval;
1483 /* status check */
1484 retval = niietcm4_uopstatus_check(bank);
1485 if (retval != ERROR_OK)
1486 return retval;
1487 retval = target_read_u32(target, UFMD, &uflash_data[i]);
1488 if (retval != ERROR_OK)
1489 return retval;
1490 }
1491
1492 int boot_from_ifb = (uflash_data[0]>>INFOWORD0_BOOTFROM_IFB_POS) & 0x1;
1493 int en_gpio = (uflash_data[0]>>INFOWORD0_EN_GPIO_POS) & 0x1;
1494 int extmem_sel = (uflash_data[0]>>INFOWORD0_EXTMEM_SEL_POS) & 0x3;
1495 int pinnum = (uflash_data[1]>>INFOWORD1_PINNUM_POS) & 0xF;
1496 int portnum = (uflash_data[1]>>INFOWORD1_PORTNUM_POS) & 0x7;
1497
1498 if (boot_from_ifb)
1499 niietcm4_info->bflash_info_remap = false;
1500 else
1501 niietcm4_info->bflash_info_remap = true;
1502 if (extmem_sel == 0x2)
1503 niietcm4_info->extmem_boot_altfunc = 3;
1504 else
1505 niietcm4_info->extmem_boot_altfunc = 1;
1506 if (portnum == 0x0)
1507 niietcm4_info->extmem_boot_port = "GPIOA";
1508 else if (portnum == 0x1)
1509 niietcm4_info->extmem_boot_port = "GPIOB";
1510 else if (portnum == 0x2)
1511 niietcm4_info->extmem_boot_port = "GPIOC";
1512 else if (portnum == 0x3)
1513 niietcm4_info->extmem_boot_port = "GPIOD";
1514 else if (portnum == 0x4)
1515 niietcm4_info->extmem_boot_port = "GPIOE";
1516 else if (portnum == 0x5)
1517 niietcm4_info->extmem_boot_port = "GPIOF";
1518 else if (portnum == 0x6)
1519 niietcm4_info->extmem_boot_port = "GPIOG";
1520 else if (portnum == 0x7)
1521 niietcm4_info->extmem_boot_port = "GPIOH";
1522 else
1523 niietcm4_info->extmem_boot_port = "not defined";
1524 if (en_gpio)
1525 niietcm4_info->extmem_boot = false;
1526 else
1527 niietcm4_info->extmem_boot = true;
1528 niietcm4_info->extmem_boot_pin = pinnum;
1529
1530 /* check state of extmem boot en pin, if "high", extmem remapped to 0x00000000 */
1531 uint32_t extmem_boot_port_data;
1532 retval = target_read_u32(target, 0x80010000 + 0x1000*portnum, &extmem_boot_port_data);
1533 if (retval != ERROR_OK)
1534 return retval;
1535 int extmem_boot_pin_data = (extmem_boot_port_data>>pinnum) & 0x1;
1536
1537 uint32_t extmem_base;
1538 uint32_t bflash_base;
1539 if (extmem_boot_pin_data && niietcm4_info->extmem_boot) {
1540 extmem_base = 0x00000000;
1541 bflash_base = 0x40000000;
1542 } else {
1543 extmem_base = 0x40000000;
1544 bflash_base = 0x00000000;
1545 }
1546
1547 uint32_t bflash_size = 0x100000;
1548 uint32_t bflash_pages = 128;
1549 uint32_t bflash_info_size = 0x2000;
1550 uint32_t bflash_info_pages = 1;
1551 if (niietcm4_info->bflash_info_remap) {
1552 bflash_base += 0x2000;
1553 bflash_size -= 0x2000;
1554 bflash_pages--;
1555 bank->size = bflash_info_size;
1556 bank->num_sectors = bflash_info_pages;
1557 } else {
1558 bank->size = bflash_size;
1559 bank->num_sectors = bflash_pages;
1560 }
1561
1562 char info_bootflash_addr_str[64];
1563 if (niietcm4_info->bflash_info_remap)
1564 snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "0x%08x base adress", bank->base);
1565 else
1566 snprintf(info_bootflash_addr_str, sizeof(info_bootflash_addr_str), "not maped to global adress space");
1567
1568 snprintf(niietcm4_info->chip_brief,
1569 sizeof(niietcm4_info->chip_brief),
1570 "\n"
1571 "MEMORY CONFIGURATION\n"
1572 "Bootflash :\n"
1573 " %d kB total\n"
1574 " %d pages %d kB each\n"
1575 " 0x%08x base adress\n"
1576 "%s"
1577 "Info bootflash :\n"
1578 " %d kB total\n"
1579 " %d pages %d kB each\n"
1580 " %s\n"
1581 "%s"
1582 "Userflash :\n"
1583 " %d kB total\n"
1584 " %d pages %d B each\n"
1585 " %d bit cells\n"
1586 " not maped to global adress space\n"
1587 "Info userflash :\n"
1588 " %d B total\n"
1589 " %d pages of %d B each\n"
1590 " %d bit cells\n"
1591 " not maped to global adress space\n"
1592 "RAM :\n"
1593 " 192 kB total\n"
1594 " 0x20000000 base adress\n"
1595 "External memory :\n"
1596 " 8/16 bit address space\n"
1597 " 0x%08x base adress\n"
1598 "\n"
1599 "INFOWORD STATUS\n"
1600 "Bootflash info region remap :\n"
1601 " %s\n"
1602 "External memory boot port :\n"
1603 " %s\n"
1604 "External memory boot pin :\n"
1605 " %d\n"
1606 "External memory interface alternative function :\n"
1607 " %d\n"
1608 "Option boot from external memory :\n"
1609 " %s\n",
1610 bflash_size/1024,
1611 bflash_pages,
1612 (bflash_size/bflash_pages)/1024,
1613 bflash_base,
1614 niietcm4_info->bflash_info_remap ? "" : " this flash will be used for debugging, writing and etc\n",
1615 bflash_info_size/1024,
1616 bflash_info_pages,
1617 (bflash_info_size/bflash_info_pages)/1024,
1618 info_bootflash_addr_str,
1619 niietcm4_info->bflash_info_remap ? " this flash will be used for debugging, writing and etc\n" : "",
1620 niietcm4_info->uflash_size/1024,
1621 niietcm4_info->uflash_pagetotal,
1622 niietcm4_info->uflash_size/niietcm4_info->uflash_pagetotal,
1623 niietcm4_info->uflash_width,
1624 niietcm4_info->uflash_info_size,
1625 niietcm4_info->uflash_info_pagetotal,
1626 niietcm4_info->uflash_info_size/niietcm4_info->uflash_info_pagetotal,
1627 niietcm4_info->uflash_width,
1628 extmem_base,
1629 niietcm4_info->bflash_info_remap ? "enable" : "disable",
1630 niietcm4_info->extmem_boot_port,
1631 niietcm4_info->extmem_boot_pin,
1632 niietcm4_info->extmem_boot_altfunc,
1633 niietcm4_info->extmem_boot ? "enable" : "disable");
1634 } else{
1635 bank->size = 0x100000;
1636 bank->num_sectors = 128;
1637
1638 sprintf(niietcm4_info->chip_brief,
1639 "\n"
1640 "H[2] was HIGH while startup. Device entered service mode.\n"
1641 "All flashes were locked.\n"
1642 "If you want to perform emergency erase (erase all flashes),\n"
1643 "please use \"service_mode_erase\" command and reset device.\n"
1644 "Do not forget to pull H[2] down while reset for returning to normal operation mode.\n"
1645 );
1646 }
1647
1648 return retval;
1649 }
1650
1651 static int niietcm4_probe(struct flash_bank *bank)
1652 {
1653 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1654 struct target *target = bank->target;
1655
1656 if (bank->sectors) {
1657 free(bank->sectors);
1658 bank->sectors = NULL;
1659 }
1660 uint32_t retval;
1661 uint32_t chipid;
1662
1663 retval = target_read_u32(target, CHIPID_ADDR, &chipid);
1664 if (retval != ERROR_OK) {
1665 chipid = K1921VK01T_ID;
1666 LOG_INFO("unknown chipid, assuming K1921VK01T");
1667 }
1668
1669 if (chipid == K1921VK01T_ID)
1670 niietcm4_probe_k1921vk01t(bank);
1671
1672 int page_total = bank->num_sectors;
1673 int page_size = bank->size / page_total;
1674
1675 bank->sectors = malloc(sizeof(struct flash_sector) * page_total);
1676
1677 for (int i = 0; i < page_total; i++) {
1678 bank->sectors[i].offset = i * page_size;
1679 bank->sectors[i].size = page_size;
1680 bank->sectors[i].is_erased = -1;
1681 bank->sectors[i].is_protected = -1;
1682 }
1683
1684 niietcm4_info->probed = true;
1685
1686 return ERROR_OK;
1687 }
1688
1689 static int niietcm4_auto_probe(struct flash_bank *bank)
1690 {
1691 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1692 if (niietcm4_info->probed)
1693 return ERROR_OK;
1694 return niietcm4_probe(bank);
1695 }
1696
1697 static int get_niietcm4_info(struct flash_bank *bank, char *buf, int buf_size)
1698 {
1699 struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv;
1700 LOG_INFO("\nNIIET Cortex M4F %s\n%s", niietcm4_info->chip_name, niietcm4_info->chip_brief);
1701 snprintf(buf, buf_size, " ");
1702
1703 return ERROR_OK;
1704 }
1705
1706
1707 struct flash_driver niietcm4_flash = {
1708 .name = "niietcm4",
1709 .usage = "flash bank <name> niietcm4 <base> <size> 0 0 <target#>",
1710 .commands = niietcm4_command_handlers,
1711 .flash_bank_command = niietcm4_flash_bank_command,
1712 .erase = niietcm4_erase,
1713 .protect = niietcm4_protect,
1714 .write = niietcm4_write,
1715 .read = default_flash_read,
1716 .probe = niietcm4_probe,
1717 .auto_probe = niietcm4_auto_probe,
1718 .erase_check = default_flash_blank_check,
1719 .protect_check = niietcm4_protect_check,
1720 .info = get_niietcm4_info,
1721 };

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)