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

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)