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

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)