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

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)