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

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)