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

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)