fixed not halted 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 adr = bank->base + bank->sectors[i].offset;
266
267 /* erase sectors */
268 target_write_u16(target, adr, erase_cmd);
269 target_write_u16(target, adr, 0xD0);
270
271 /* get status */
272 target_write_u16(target, adr, 0x70);
273
274 while (1) {
275 target_read_u8(target, adr, &status);
276 if( status & 0x80 )
277 break;
278 usleep(1000);
279 }
280
281 /* clear status, also clear read array */
282 target_write_u16(target, adr, 0x50);
283
284 /* read array command */
285 target_write_u16(target, adr, 0xFF);
286
287 if( status & 0x22 )
288 {
289 LOG_ERROR("error erasing flash bank, status: 0x%x", status);
290 return ERROR_FLASH_OPERATION_FAILED;
291 }
292
293 /* If we ran erase bank command, we are finished */
294 if (erase_cmd == 0x80)
295 break;
296 }
297
298 for (i = first; i <= last; i++)
299 bank->sectors[i].is_erased = 1;
300
301 return ERROR_OK;
302 }
303
304 int str9x_protect(struct flash_bank_s *bank, int set, int first, int last)
305 {
306 target_t *target = bank->target;
307 int i;
308 u32 adr;
309 u8 status;
310
311 if (bank->target->state != TARGET_HALTED)
312 {
313 LOG_ERROR("Target not halted");
314 return ERROR_TARGET_NOT_HALTED;
315 }
316
317 for (i = first; i <= last; i++)
318 {
319 /* Level One Protection */
320
321 adr = bank->base + bank->sectors[i].offset;
322
323 target_write_u16(target, adr, 0x60);
324 if( set )
325 target_write_u16(target, adr, 0x01);
326 else
327 target_write_u16(target, adr, 0xD0);
328
329 /* query status */
330 target_read_u8(target, adr, &status);
331
332 /* clear status, also clear read array */
333 target_write_u16(target, adr, 0x50);
334
335 /* read array command */
336 target_write_u16(target, adr, 0xFF);
337 }
338
339 return ERROR_OK;
340 }
341
342 int str9x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
343 {
344 str9x_flash_bank_t *str9x_info = bank->driver_priv;
345 target_t *target = bank->target;
346 u32 buffer_size = 8192;
347 working_area_t *source;
348 u32 address = bank->base + offset;
349 reg_param_t reg_params[4];
350 armv4_5_algorithm_t armv4_5_info;
351 int retval = ERROR_OK;
352
353 u32 str9x_flash_write_code[] = {
354 /* write: */
355 0xe3c14003, /* bic r4, r1, #3 */
356 0xe3a03040, /* mov r3, #0x40 */
357 0xe1c430b0, /* strh r3, [r4, #0] */
358 0xe0d030b2, /* ldrh r3, [r0], #2 */
359 0xe0c130b2, /* strh r3, [r1], #2 */
360 0xe3a03070, /* mov r3, #0x70 */
361 0xe1c430b0, /* strh r3, [r4, #0] */
362 /* busy: */
363 0xe5d43000, /* ldrb r3, [r4, #0] */
364 0xe3130080, /* tst r3, #0x80 */
365 0x0afffffc, /* beq busy */
366 0xe3a05050, /* mov r5, #0x50 */
367 0xe1c450b0, /* strh r5, [r4, #0] */
368 0xe3a050ff, /* mov r5, #0xFF */
369 0xe1c450b0, /* strh r5, [r4, #0] */
370 0xe3130012, /* tst r3, #0x12 */
371 0x1a000001, /* bne exit */
372 0xe2522001, /* subs r2, r2, #1 */
373 0x1affffed, /* bne write */
374 /* exit: */
375 0xeafffffe, /* b exit */
376 };
377
378 /* flash write code */
379 if (target_alloc_working_area(target, 4 * 19, &str9x_info->write_algorithm) != ERROR_OK)
380 {
381 LOG_WARNING("no working area available, can't do block memory writes");
382 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
383 };
384
385 target_write_buffer(target, str9x_info->write_algorithm->address, 19 * 4, (u8*)str9x_flash_write_code);
386
387 /* memory buffer */
388 while (target_alloc_working_area(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 buffer, free the algorithm */
394 if (str9x_info->write_algorithm)
395 target_free_working_area(target, str9x_info->write_algorithm);
396
397 LOG_WARNING("no large enough working area available, can't do block memory writes");
398 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
399 }
400 }
401
402 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
403 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
404 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
405
406 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
407 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
408 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
409 init_reg_param(&reg_params[3], "r3", 32, PARAM_IN);
410
411 while (count > 0)
412 {
413 u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
414
415 target_write_buffer(target, source->address, thisrun_count * 2, buffer);
416
417 buf_set_u32(reg_params[0].value, 0, 32, source->address);
418 buf_set_u32(reg_params[1].value, 0, 32, address);
419 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
420
421 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)
422 {
423 LOG_ERROR("error executing str9x flash write algorithm");
424 retval = ERROR_FLASH_OPERATION_FAILED;
425 break;
426 }
427
428 if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
429 {
430 retval = ERROR_FLASH_OPERATION_FAILED;
431 break;
432 }
433
434 buffer += thisrun_count * 2;
435 address += thisrun_count * 2;
436 count -= thisrun_count;
437 }
438
439 target_free_working_area(target, source);
440 target_free_working_area(target, str9x_info->write_algorithm);
441
442 destroy_reg_param(&reg_params[0]);
443 destroy_reg_param(&reg_params[1]);
444 destroy_reg_param(&reg_params[2]);
445 destroy_reg_param(&reg_params[3]);
446
447 return retval;
448 }
449
450 int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
451 {
452 target_t *target = bank->target;
453 u32 words_remaining = (count / 2);
454 u32 bytes_remaining = (count & 0x00000001);
455 u32 address = bank->base + offset;
456 u32 bytes_written = 0;
457 u8 status;
458 u32 retval;
459 u32 check_address = offset;
460 u32 bank_adr;
461 int i;
462
463 if (bank->target->state != TARGET_HALTED)
464 {
465 LOG_ERROR("Target not halted");
466 return ERROR_TARGET_NOT_HALTED;
467 }
468
469 if (offset & 0x1)
470 {
471 LOG_WARNING("offset 0x%x breaks required 2-byte alignment", offset);
472 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
473 }
474
475 for (i = 0; i < bank->num_sectors; i++)
476 {
477 u32 sec_start = bank->sectors[i].offset;
478 u32 sec_end = sec_start + bank->sectors[i].size;
479
480 /* check if destination falls within the current sector */
481 if ((check_address >= sec_start) && (check_address < sec_end))
482 {
483 /* check if destination ends in the current sector */
484 if (offset + count < sec_end)
485 check_address = offset + count;
486 else
487 check_address = sec_end;
488 }
489 }
490
491 if (check_address != offset + count)
492 return ERROR_FLASH_DST_OUT_OF_BANK;
493
494 /* multiple half words (2-byte) to be programmed? */
495 if (words_remaining > 0)
496 {
497 /* try using a block write */
498 if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
499 {
500 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
501 {
502 /* if block write failed (no sufficient working area),
503 * we use normal (slow) single dword accesses */
504 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
505 }
506 else if (retval == ERROR_FLASH_OPERATION_FAILED)
507 {
508 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
509 return ERROR_FLASH_OPERATION_FAILED;
510 }
511 }
512 else
513 {
514 buffer += words_remaining * 2;
515 address += words_remaining * 2;
516 words_remaining = 0;
517 }
518 }
519
520 while (words_remaining > 0)
521 {
522 bank_adr = address & ~0x03;
523
524 /* write data command */
525 target_write_u16(target, bank_adr, 0x40);
526 target->type->write_memory(target, address, 2, 1, buffer + bytes_written);
527
528 /* get status command */
529 target_write_u16(target, bank_adr, 0x70);
530
531 while (1) {
532 target_read_u8(target, bank_adr, &status);
533 if( status & 0x80 )
534 break;
535 usleep(1000);
536 }
537
538 /* clear status reg and read array */
539 target_write_u16(target, bank_adr, 0x50);
540 target_write_u16(target, bank_adr, 0xFF);
541
542 if (status & 0x10)
543 return ERROR_FLASH_OPERATION_FAILED;
544 else if (status & 0x02)
545 return ERROR_FLASH_OPERATION_FAILED;
546
547 bytes_written += 2;
548 words_remaining--;
549 address += 2;
550 }
551
552 if (bytes_remaining)
553 {
554 u8 last_halfword[2] = {0xff, 0xff};
555 int i = 0;
556
557 while(bytes_remaining > 0)
558 {
559 last_halfword[i++] = *(buffer + bytes_written);
560 bytes_remaining--;
561 bytes_written++;
562 }
563
564 bank_adr = address & ~0x03;
565
566 /* write data comamnd */
567 target_write_u16(target, bank_adr, 0x40);
568 target->type->write_memory(target, address, 2, 1, last_halfword);
569
570 /* query status command */
571 target_write_u16(target, bank_adr, 0x70);
572
573 while (1) {
574 target_read_u8(target, bank_adr, &status);
575 if( status & 0x80 )
576 break;
577 usleep(1000);
578 }
579
580 /* clear status reg and read array */
581 target_write_u16(target, bank_adr, 0x50);
582 target_write_u16(target, bank_adr, 0xFF);
583
584 if (status & 0x10)
585 return ERROR_FLASH_OPERATION_FAILED;
586 else if (status & 0x02)
587 return ERROR_FLASH_OPERATION_FAILED;
588 }
589
590 return ERROR_OK;
591 }
592
593 int str9x_probe(struct flash_bank_s *bank)
594 {
595 return ERROR_OK;
596 }
597
598 int str9x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
599 {
600 return ERROR_OK;
601 }
602
603 int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size)
604 {
605 snprintf(buf, buf_size, "str9x flash driver info" );
606 return ERROR_OK;
607 }
608
609 int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
610 {
611 str9x_flash_bank_t *str9x_info;
612 flash_bank_t *bank;
613 target_t *target = NULL;
614
615 if (argc < 5)
616 {
617 return ERROR_COMMAND_SYNTAX_ERROR;
618 }
619
620 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
621 if (!bank)
622 {
623 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
624 return ERROR_OK;
625 }
626
627 str9x_info = bank->driver_priv;
628
629 target = bank->target;
630
631 if (bank->target->state != TARGET_HALTED)
632 {
633 LOG_ERROR("Target not halted");
634 return ERROR_TARGET_NOT_HALTED;
635 }
636
637 /* config flash controller */
638 target_write_u32(target, FLASH_BBSR, strtoul(args[1], NULL, 0));
639 target_write_u32(target, FLASH_NBBSR, strtoul(args[2], NULL, 0));
640 target_write_u32(target, FLASH_BBADR, (strtoul(args[3], NULL, 0) >> 2));
641 target_write_u32(target, FLASH_NBBADR, (strtoul(args[4], NULL, 0) >> 2));
642
643 /* set bit 18 instruction TCM order as per flash programming manual */
644 arm966e_write_cp15(target, 62, 0x40000);
645
646 /* enable flash bank 1 */
647 target_write_u32(target, FLASH_CR, 0x18);
648 return ERROR_OK;
649 }

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)