command_handler: change to 'argc' to CMD_ARGC
[openocd.git] / src / flash / str9x.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include "str9x.h"
31 #include "arm966e.h"
32 #include "algorithm.h"
33
34
35 static uint32_t bank1start = 0x00080000;
36
37 static int str9x_build_block_list(struct flash_bank *bank)
38 {
39 struct str9x_flash_bank *str9x_info = bank->driver_priv;
40
41 int i;
42 int num_sectors;
43 int b0_sectors = 0, b1_sectors = 0;
44 uint32_t offset = 0;
45
46 /* set if we have large flash str9 */
47 str9x_info->variant = 0;
48 str9x_info->bank1 = 0;
49
50 switch (bank->size)
51 {
52 case (256 * 1024):
53 b0_sectors = 4;
54 break;
55 case (512 * 1024):
56 b0_sectors = 8;
57 break;
58 case (1024 * 1024):
59 bank1start = 0x00100000;
60 str9x_info->variant = 1;
61 b0_sectors = 16;
62 break;
63 case (2048 * 1024):
64 bank1start = 0x00200000;
65 str9x_info->variant = 1;
66 b0_sectors = 32;
67 break;
68 case (128 * 1024):
69 str9x_info->variant = 1;
70 str9x_info->bank1 = 1;
71 b1_sectors = 8;
72 bank1start = bank->base;
73 break;
74 case (32 * 1024):
75 str9x_info->bank1 = 1;
76 b1_sectors = 4;
77 bank1start = bank->base;
78 break;
79 default:
80 LOG_ERROR("BUG: unknown bank->size encountered");
81 exit(-1);
82 }
83
84 num_sectors = b0_sectors + b1_sectors;
85
86 bank->num_sectors = num_sectors;
87 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
88 str9x_info->sector_bits = malloc(sizeof(uint32_t) * num_sectors);
89
90 num_sectors = 0;
91
92 for (i = 0; i < b0_sectors; i++)
93 {
94 bank->sectors[num_sectors].offset = offset;
95 bank->sectors[num_sectors].size = 0x10000;
96 offset += bank->sectors[i].size;
97 bank->sectors[num_sectors].is_erased = -1;
98 bank->sectors[num_sectors].is_protected = 1;
99 str9x_info->sector_bits[num_sectors++] = (1 << i);
100 }
101
102 for (i = 0; i < b1_sectors; i++)
103 {
104 bank->sectors[num_sectors].offset = offset;
105 bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
106 offset += bank->sectors[i].size;
107 bank->sectors[num_sectors].is_erased = -1;
108 bank->sectors[num_sectors].is_protected = 1;
109 if (str9x_info->variant)
110 str9x_info->sector_bits[num_sectors++] = (1 << i);
111 else
112 str9x_info->sector_bits[num_sectors++] = (1 << (i + 8));
113 }
114
115 return ERROR_OK;
116 }
117
118 /* flash bank str9x <base> <size> 0 0 <target#>
119 */
120 FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command)
121 {
122 struct str9x_flash_bank *str9x_info;
123
124 if (CMD_ARGC < 6)
125 {
126 LOG_WARNING("incomplete flash_bank str9x configuration");
127 return ERROR_FLASH_BANK_INVALID;
128 }
129
130 str9x_info = malloc(sizeof(struct str9x_flash_bank));
131 bank->driver_priv = str9x_info;
132
133 str9x_build_block_list(bank);
134
135 str9x_info->write_algorithm = NULL;
136
137 return ERROR_OK;
138 }
139
140 static int str9x_protect_check(struct flash_bank *bank)
141 {
142 int retval;
143 struct str9x_flash_bank *str9x_info = bank->driver_priv;
144 struct target *target = bank->target;
145
146 int i;
147 uint32_t adr;
148 uint32_t status = 0;
149 uint16_t hstatus = 0;
150
151 if (bank->target->state != TARGET_HALTED)
152 {
153 LOG_ERROR("Target not halted");
154 return ERROR_TARGET_NOT_HALTED;
155 }
156
157 /* read level one protection */
158
159 if (str9x_info->variant)
160 {
161 if (str9x_info->bank1)
162 {
163 adr = bank1start + 0x18;
164 if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
165 {
166 return retval;
167 }
168 if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
169 {
170 return retval;
171 }
172 status = hstatus;
173 }
174 else
175 {
176 adr = bank1start + 0x14;
177 if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
178 {
179 return retval;
180 }
181 if ((retval = target_read_u32(target, adr, &status)) != ERROR_OK)
182 {
183 return retval;
184 }
185 }
186 }
187 else
188 {
189 adr = bank1start + 0x10;
190 if ((retval = target_write_u16(target, adr, 0x90)) != ERROR_OK)
191 {
192 return retval;
193 }
194 if ((retval = target_read_u16(target, adr, &hstatus)) != ERROR_OK)
195 {
196 return retval;
197 }
198 status = hstatus;
199 }
200
201 /* read array command */
202 if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
203 {
204 return retval;
205 }
206
207 for (i = 0; i < bank->num_sectors; i++)
208 {
209 if (status & str9x_info->sector_bits[i])
210 bank->sectors[i].is_protected = 1;
211 else
212 bank->sectors[i].is_protected = 0;
213 }
214
215 return ERROR_OK;
216 }
217
218 static int str9x_erase(struct flash_bank *bank, int first, int last)
219 {
220 struct target *target = bank->target;
221 int i;
222 uint32_t adr;
223 uint8_t status;
224 uint8_t erase_cmd;
225
226 if (bank->target->state != TARGET_HALTED)
227 {
228 LOG_ERROR("Target not halted");
229 return ERROR_TARGET_NOT_HALTED;
230 }
231
232 /* Check if we erase whole bank */
233 if ((first == 0) && (last == (bank->num_sectors - 1)))
234 {
235 /* Optimize to run erase bank command instead of sector */
236 erase_cmd = 0x80;
237 }
238 else
239 {
240 /* Erase sector command */
241 erase_cmd = 0x20;
242 }
243
244 for (i = first; i <= last; i++)
245 {
246 int retval;
247 adr = bank->base + bank->sectors[i].offset;
248
249 /* erase sectors */
250 if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK)
251 {
252 return retval;
253 }
254 if ((retval = target_write_u16(target, adr, 0xD0)) != ERROR_OK)
255 {
256 return retval;
257 }
258
259 /* get status */
260 if ((retval = target_write_u16(target, adr, 0x70)) != ERROR_OK)
261 {
262 return retval;
263 }
264
265 int timeout;
266 for (timeout = 0; timeout < 1000; timeout++) {
267 if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK)
268 {
269 return retval;
270 }
271 if (status & 0x80)
272 break;
273 alive_sleep(1);
274 }
275 if (timeout == 1000)
276 {
277 LOG_ERROR("erase timed out");
278 return ERROR_FAIL;
279 }
280
281 /* clear status, also clear read array */
282 if ((retval = target_write_u16(target, adr, 0x50)) != ERROR_OK)
283 {
284 return retval;
285 }
286
287 /* read array command */
288 if ((retval = target_write_u16(target, adr, 0xFF)) != ERROR_OK)
289 {
290 return retval;
291 }
292
293 if (status & 0x22)
294 {
295 LOG_ERROR("error erasing flash bank, status: 0x%x", status);
296 return ERROR_FLASH_OPERATION_FAILED;
297 }
298
299 /* If we ran erase bank command, we are finished */
300 if (erase_cmd == 0x80)
301 break;
302 }
303
304 for (i = first; i <= last; i++)
305 bank->sectors[i].is_erased = 1;
306
307 return ERROR_OK;
308 }
309
310 static int str9x_protect(struct flash_bank *bank,
311 int set, int first, int last)
312 {
313 struct target *target = bank->target;
314 int i;
315 uint32_t adr;
316 uint8_t status;
317
318 if (bank->target->state != TARGET_HALTED)
319 {
320 LOG_ERROR("Target not halted");
321 return ERROR_TARGET_NOT_HALTED;
322 }
323
324 for (i = first; i <= last; i++)
325 {
326 /* Level One Protection */
327
328 adr = bank->base + bank->sectors[i].offset;
329
330 target_write_u16(target, adr, 0x60);
331 if (set)
332 target_write_u16(target, adr, 0x01);
333 else
334 target_write_u16(target, adr, 0xD0);
335
336 /* query status */
337 target_read_u8(target, adr, &status);
338
339 /* clear status, also clear read array */
340 target_write_u16(target, adr, 0x50);
341
342 /* read array command */
343 target_write_u16(target, adr, 0xFF);
344 }
345
346 return ERROR_OK;
347 }
348
349 static int str9x_write_block(struct flash_bank *bank,
350 uint8_t *buffer, uint32_t offset, uint32_t count)
351 {
352 struct str9x_flash_bank *str9x_info = bank->driver_priv;
353 struct target *target = bank->target;
354 uint32_t buffer_size = 8192;
355 struct working_area *source;
356 uint32_t address = bank->base + offset;
357 struct reg_param reg_params[4];
358 struct armv4_5_algorithm armv4_5_info;
359 int retval = ERROR_OK;
360
361 uint32_t str9x_flash_write_code[] = {
362 /* write: */
363 0xe3c14003, /* bic r4, r1, #3 */
364 0xe3a03040, /* mov r3, #0x40 */
365 0xe1c430b0, /* strh r3, [r4, #0] */
366 0xe0d030b2, /* ldrh r3, [r0], #2 */
367 0xe0c130b2, /* strh r3, [r1], #2 */
368 0xe3a03070, /* mov r3, #0x70 */
369 0xe1c430b0, /* strh r3, [r4, #0] */
370 /* busy: */
371 0xe5d43000, /* ldrb r3, [r4, #0] */
372 0xe3130080, /* tst r3, #0x80 */
373 0x0afffffc, /* beq busy */
374 0xe3a05050, /* mov r5, #0x50 */
375 0xe1c450b0, /* strh r5, [r4, #0] */
376 0xe3a050ff, /* mov r5, #0xFF */
377 0xe1c450b0, /* strh r5, [r4, #0] */
378 0xe3130012, /* tst r3, #0x12 */
379 0x1a000001, /* bne exit */
380 0xe2522001, /* subs r2, r2, #1 */
381 0x1affffed, /* bne write */
382 /* exit: */
383 0xeafffffe, /* b exit */
384 };
385
386 /* flash write code */
387 if (target_alloc_working_area(target, 4 * 19, &str9x_info->write_algorithm) != ERROR_OK)
388 {
389 LOG_WARNING("no working area available, can't do block memory writes");
390 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
391 };
392
393 target_write_buffer(target, str9x_info->write_algorithm->address, 19 * 4, (uint8_t*)str9x_flash_write_code);
394
395 /* memory buffer */
396 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
397 {
398 buffer_size /= 2;
399 if (buffer_size <= 256)
400 {
401 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
402 if (str9x_info->write_algorithm)
403 target_free_working_area(target, str9x_info->write_algorithm);
404
405 LOG_WARNING("no large enough working area available, can't do block memory writes");
406 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
407 }
408 }
409
410 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
411 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
412 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
413
414 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
415 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
416 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
417 init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
418
419 while (count > 0)
420 {
421 uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
422
423 target_write_buffer(target, source->address, thisrun_count * 2, buffer);
424
425 buf_set_u32(reg_params[0].value, 0, 32, source->address);
426 buf_set_u32(reg_params[1].value, 0, 32, address);
427 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
428
429 if ((retval = target_run_algorithm(target, 0, NULL, 4, reg_params, str9x_info->write_algorithm->address, str9x_info->write_algorithm->address + (18 * 4), 10000, &armv4_5_info)) != ERROR_OK)
430 {
431 LOG_ERROR("error executing str9x flash write algorithm");
432 retval = ERROR_FLASH_OPERATION_FAILED;
433 break;
434 }
435
436 if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
437 {
438 retval = ERROR_FLASH_OPERATION_FAILED;
439 break;
440 }
441
442 buffer += thisrun_count * 2;
443 address += thisrun_count * 2;
444 count -= thisrun_count;
445 }
446
447 target_free_working_area(target, source);
448 target_free_working_area(target, str9x_info->write_algorithm);
449
450 destroy_reg_param(&reg_params[0]);
451 destroy_reg_param(&reg_params[1]);
452 destroy_reg_param(&reg_params[2]);
453 destroy_reg_param(&reg_params[3]);
454
455 return retval;
456 }
457
458 static int str9x_write(struct flash_bank *bank,
459 uint8_t *buffer, uint32_t offset, uint32_t count)
460 {
461 struct target *target = bank->target;
462 uint32_t words_remaining = (count / 2);
463 uint32_t bytes_remaining = (count & 0x00000001);
464 uint32_t address = bank->base + offset;
465 uint32_t bytes_written = 0;
466 uint8_t status;
467 int retval;
468 uint32_t check_address = offset;
469 uint32_t bank_adr;
470 int i;
471
472 if (bank->target->state != TARGET_HALTED)
473 {
474 LOG_ERROR("Target not halted");
475 return ERROR_TARGET_NOT_HALTED;
476 }
477
478 if (offset & 0x1)
479 {
480 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
481 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
482 }
483
484 for (i = 0; i < bank->num_sectors; i++)
485 {
486 uint32_t sec_start = bank->sectors[i].offset;
487 uint32_t sec_end = sec_start + bank->sectors[i].size;
488
489 /* check if destination falls within the current sector */
490 if ((check_address >= sec_start) && (check_address < sec_end))
491 {
492 /* check if destination ends in the current sector */
493 if (offset + count < sec_end)
494 check_address = offset + count;
495 else
496 check_address = sec_end;
497 }
498 }
499
500 if (check_address != offset + count)
501 return ERROR_FLASH_DST_OUT_OF_BANK;
502
503 /* multiple half words (2-byte) to be programmed? */
504 if (words_remaining > 0)
505 {
506 /* try using a block write */
507 if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
508 {
509 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
510 {
511 /* if block write failed (no sufficient working area),
512 * we use normal (slow) single dword accesses */
513 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
514 }
515 else if (retval == ERROR_FLASH_OPERATION_FAILED)
516 {
517 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
518 return ERROR_FLASH_OPERATION_FAILED;
519 }
520 }
521 else
522 {
523 buffer += words_remaining * 2;
524 address += words_remaining * 2;
525 words_remaining = 0;
526 }
527 }
528
529 while (words_remaining > 0)
530 {
531 bank_adr = address & ~0x03;
532
533 /* write data command */
534 target_write_u16(target, bank_adr, 0x40);
535 target_write_memory(target, address, 2, 1, buffer + bytes_written);
536
537 /* get status command */
538 target_write_u16(target, bank_adr, 0x70);
539
540 int timeout;
541 for (timeout = 0; timeout < 1000; timeout++)
542 {
543 target_read_u8(target, bank_adr, &status);
544 if (status & 0x80)
545 break;
546 alive_sleep(1);
547 }
548 if (timeout == 1000)
549 {
550 LOG_ERROR("write timed out");
551 return ERROR_FAIL;
552 }
553
554 /* clear status reg and read array */
555 target_write_u16(target, bank_adr, 0x50);
556 target_write_u16(target, bank_adr, 0xFF);
557
558 if (status & 0x10)
559 return ERROR_FLASH_OPERATION_FAILED;
560 else if (status & 0x02)
561 return ERROR_FLASH_OPERATION_FAILED;
562
563 bytes_written += 2;
564 words_remaining--;
565 address += 2;
566 }
567
568 if (bytes_remaining)
569 {
570 uint8_t last_halfword[2] = {0xff, 0xff};
571 int i = 0;
572
573 while (bytes_remaining > 0)
574 {
575 last_halfword[i++] = *(buffer + bytes_written);
576 bytes_remaining--;
577 bytes_written++;
578 }
579
580 bank_adr = address & ~0x03;
581
582 /* write data command */
583 target_write_u16(target, bank_adr, 0x40);
584 target_write_memory(target, address, 2, 1, last_halfword);
585
586 /* query status command */
587 target_write_u16(target, bank_adr, 0x70);
588
589 int timeout;
590 for (timeout = 0; timeout < 1000; timeout++)
591 {
592 target_read_u8(target, bank_adr, &status);
593 if (status & 0x80)
594 break;
595 alive_sleep(1);
596 }
597 if (timeout == 1000)
598 {
599 LOG_ERROR("write timed out");
600 return ERROR_FAIL;
601 }
602
603 /* clear status reg and read array */
604 target_write_u16(target, bank_adr, 0x50);
605 target_write_u16(target, bank_adr, 0xFF);
606
607 if (status & 0x10)
608 return ERROR_FLASH_OPERATION_FAILED;
609 else if (status & 0x02)
610 return ERROR_FLASH_OPERATION_FAILED;
611 }
612
613 return ERROR_OK;
614 }
615
616 static int str9x_probe(struct flash_bank *bank)
617 {
618 return ERROR_OK;
619 }
620
621 #if 0
622 COMMAND_HANDLER(str9x_handle_part_id_command)
623 {
624 return ERROR_OK;
625 }
626 #endif
627
628 static int str9x_info(struct flash_bank *bank, char *buf, int buf_size)
629 {
630 snprintf(buf, buf_size, "str9x flash driver info");
631 return ERROR_OK;
632 }
633
634 COMMAND_HANDLER(str9x_handle_flash_config_command)
635 {
636 struct str9x_flash_bank *str9x_info;
637 struct target *target = NULL;
638
639 if (CMD_ARGC < 5)
640 {
641 return ERROR_COMMAND_SYNTAX_ERROR;
642 }
643
644 struct flash_bank *bank;
645 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank_by_num, 0, &bank);
646 if (ERROR_OK != retval)
647 return retval;
648
649 uint32_t bbsr, nbbsr, bbadr, nbbadr;
650 COMMAND_PARSE_NUMBER(u32, args[1], bbsr);
651 COMMAND_PARSE_NUMBER(u32, args[2], nbbsr);
652 COMMAND_PARSE_NUMBER(u32, args[3], bbadr);
653 COMMAND_PARSE_NUMBER(u32, args[4], nbbadr);
654
655 str9x_info = bank->driver_priv;
656
657 target = bank->target;
658
659 if (bank->target->state != TARGET_HALTED)
660 {
661 LOG_ERROR("Target not halted");
662 return ERROR_TARGET_NOT_HALTED;
663 }
664
665 /* config flash controller */
666 target_write_u32(target, FLASH_BBSR, bbsr);
667 target_write_u32(target, FLASH_NBBSR, nbbsr);
668 target_write_u32(target, FLASH_BBADR, bbadr >> 2);
669 target_write_u32(target, FLASH_NBBADR, nbbadr >> 2);
670
671 /* set bit 18 instruction TCM order as per flash programming manual */
672 arm966e_write_cp15(target, 62, 0x40000);
673
674 /* enable flash bank 1 */
675 target_write_u32(target, FLASH_CR, 0x18);
676 return ERROR_OK;
677 }
678
679 static int str9x_register_commands(struct command_context *cmd_ctx)
680 {
681 struct command *str9x_cmd = register_command(cmd_ctx, NULL, "str9x",
682 NULL, COMMAND_ANY, "str9x flash commands");
683
684 register_command(cmd_ctx, str9x_cmd, "flash_config",
685 str9x_handle_flash_config_command, COMMAND_EXEC,
686 "configure str9 flash controller");
687
688 return ERROR_OK;
689 }
690
691 struct flash_driver str9x_flash = {
692 .name = "str9x",
693 .register_commands = &str9x_register_commands,
694 .flash_bank_command = &str9x_flash_bank_command,
695 .erase = &str9x_erase,
696 .protect = &str9x_protect,
697 .write = &str9x_write,
698 .probe = &str9x_probe,
699 .auto_probe = &str9x_probe,
700 .erase_check = &default_flash_blank_check,
701 .protect_check = &str9x_protect_check,
702 .info = &str9x_info,
703 };

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)