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

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)