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