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

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)