Fredrik Hederstierna: fix leak + clean up return codes
[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 static u32 bank1start = 0x00080000;
40
41 int str9x_register_commands(struct command_context_s *cmd_ctx);
42 int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
43 int str9x_erase(struct flash_bank_s *bank, int first, int last);
44 int str9x_protect(struct flash_bank_s *bank, int set, int first, int last);
45 int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
46 int str9x_probe(struct flash_bank_s *bank);
47 int str9x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
48 int str9x_protect_check(struct flash_bank_s *bank);
49 int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size);
50
51 int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
52
53 flash_driver_t str9x_flash =
54 {
55 .name = "str9x",
56 .register_commands = str9x_register_commands,
57 .flash_bank_command = str9x_flash_bank_command,
58 .erase = str9x_erase,
59 .protect = str9x_protect,
60 .write = str9x_write,
61 .probe = str9x_probe,
62 .auto_probe = str9x_probe,
63 .erase_check = default_flash_blank_check,
64 .protect_check = str9x_protect_check,
65 .info = str9x_info
66 };
67
68 int str9x_register_commands(struct command_context_s *cmd_ctx)
69 {
70 command_t *str9x_cmd = register_command(cmd_ctx, NULL, "str9x", NULL, COMMAND_ANY, NULL);
71
72 register_command(cmd_ctx, str9x_cmd, "flash_config", str9x_handle_flash_config_command, COMMAND_EXEC,
73 "configure str9 flash controller");
74
75 return ERROR_OK;
76 }
77
78 int str9x_build_block_list(struct flash_bank_s *bank)
79 {
80 str9x_flash_bank_t *str9x_info = bank->driver_priv;
81
82 int i;
83 int num_sectors;
84 int b0_sectors = 0, b1_sectors = 0;
85 u32 offset = 0;
86
87 /* set if we have large flash str9 */
88 str9x_info->variant = 0;
89 str9x_info->bank1 = 0;
90
91 switch (bank->size)
92 {
93 case (256 * 1024):
94 b0_sectors = 4;
95 break;
96 case (512 * 1024):
97 b0_sectors = 8;
98 break;
99 case (1024 * 1024):
100 bank1start = 0x00100000;
101 str9x_info->variant = 1;
102 b0_sectors = 16;
103 break;
104 case (2048 * 1024):
105 bank1start = 0x00200000;
106 str9x_info->variant = 1;
107 b0_sectors = 32;
108 break;
109 case (128 * 1024):
110 str9x_info->variant = 1;
111 str9x_info->bank1 = 1;
112 b1_sectors = 8;
113 bank1start = bank->base;
114 break;
115 case (32 * 1024):
116 str9x_info->bank1 = 1;
117 b1_sectors = 4;
118 bank1start = bank->base;
119 break;
120 default:
121 LOG_ERROR("BUG: unknown bank->size encountered");
122 exit(-1);
123 }
124
125 num_sectors = b0_sectors + b1_sectors;
126
127 bank->num_sectors = num_sectors;
128 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
129 str9x_info->sector_bits = malloc(sizeof(u32) * num_sectors);
130
131 num_sectors = 0;
132
133 for (i = 0; i < b0_sectors; i++)
134 {
135 bank->sectors[num_sectors].offset = offset;
136 bank->sectors[num_sectors].size = 0x10000;
137 offset += bank->sectors[i].size;
138 bank->sectors[num_sectors].is_erased = -1;
139 bank->sectors[num_sectors].is_protected = 1;
140 str9x_info->sector_bits[num_sectors++] = (1<<i);
141 }
142
143 for (i = 0; i < b1_sectors; i++)
144 {
145 bank->sectors[num_sectors].offset = offset;
146 bank->sectors[num_sectors].size = str9x_info->variant == 0 ? 0x2000 : 0x4000;
147 offset += bank->sectors[i].size;
148 bank->sectors[num_sectors].is_erased = -1;
149 bank->sectors[num_sectors].is_protected = 1;
150 if (str9x_info->variant)
151 str9x_info->sector_bits[num_sectors++] = (1<<i);
152 else
153 str9x_info->sector_bits[num_sectors++] = (1<<(i+8));
154 }
155
156 return ERROR_OK;
157 }
158
159 /* flash bank str9x <base> <size> 0 0 <target#>
160 */
161 int str9x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
162 {
163 str9x_flash_bank_t *str9x_info;
164
165 if (argc < 6)
166 {
167 LOG_WARNING("incomplete flash_bank str9x configuration");
168 return ERROR_FLASH_BANK_INVALID;
169 }
170
171 str9x_info = malloc(sizeof(str9x_flash_bank_t));
172 bank->driver_priv = str9x_info;
173
174 str9x_build_block_list(bank);
175
176 str9x_info->write_algorithm = NULL;
177
178 return ERROR_OK;
179 }
180
181 int str9x_protect_check(struct flash_bank_s *bank)
182 {
183 str9x_flash_bank_t *str9x_info = bank->driver_priv;
184 target_t *target = bank->target;
185
186 int i;
187 u32 adr;
188 u32 status = 0;
189
190 if (bank->target->state != TARGET_HALTED)
191 {
192 return ERROR_TARGET_NOT_HALTED;
193 }
194
195 /* read level one protection */
196
197 if (str9x_info->variant)
198 {
199 if (str9x_info->bank1)
200 {
201 adr = bank1start + 0x18;
202 target_write_u16(target, adr, 0x90);
203 target_read_u16(target, adr, (u16*)&status);
204 }
205 else
206 {
207 adr = bank1start + 0x14;
208 target_write_u16(target, adr, 0x90);
209 target_read_u32(target, adr, &status);
210 }
211 }
212 else
213 {
214 adr = bank1start + 0x10;
215 target_write_u16(target, adr, 0x90);
216 target_read_u16(target, adr, (u16*)&status);
217 }
218
219 /* read array command */
220 target_write_u16(target, adr, 0xFF);
221
222 for (i = 0; i < bank->num_sectors; i++)
223 {
224 if (status & str9x_info->sector_bits[i])
225 bank->sectors[i].is_protected = 1;
226 else
227 bank->sectors[i].is_protected = 0;
228 }
229
230 return ERROR_OK;
231 }
232
233 int str9x_erase(struct flash_bank_s *bank, int first, int last)
234 {
235 target_t *target = bank->target;
236 int i;
237 u32 adr;
238 u8 status;
239
240 if (bank->target->state != TARGET_HALTED)
241 {
242 return ERROR_TARGET_NOT_HALTED;
243 }
244
245 for (i = first; i <= last; i++)
246 {
247 adr = bank->base + bank->sectors[i].offset;
248
249 /* erase sectors */
250 target_write_u16(target, adr, 0x20);
251 target_write_u16(target, adr, 0xD0);
252
253 /* get status */
254 target_write_u16(target, adr, 0x70);
255
256 while (1) {
257 target_read_u8(target, adr, &status);
258 if( status & 0x80 )
259 break;
260 usleep(1000);
261 }
262
263 /* clear status, also clear read array */
264 target_write_u16(target, adr, 0x50);
265
266 /* read array command */
267 target_write_u16(target, adr, 0xFF);
268
269 if( status & 0x22 )
270 {
271 LOG_ERROR("error erasing flash bank, status: 0x%x", status);
272 return ERROR_FLASH_OPERATION_FAILED;
273 }
274 }
275
276 for (i = first; i <= last; i++)
277 bank->sectors[i].is_erased = 1;
278
279 return ERROR_OK;
280 }
281
282 int str9x_protect(struct flash_bank_s *bank, int set, int first, int last)
283 {
284 target_t *target = bank->target;
285 int i;
286 u32 adr;
287 u8 status;
288
289 if (bank->target->state != TARGET_HALTED)
290 {
291 return ERROR_TARGET_NOT_HALTED;
292 }
293
294 for (i = first; i <= last; i++)
295 {
296 /* Level One Protection */
297
298 adr = bank->base + bank->sectors[i].offset;
299
300 target_write_u16(target, adr, 0x60);
301 if( set )
302 target_write_u16(target, adr, 0x01);
303 else
304 target_write_u16(target, adr, 0xD0);
305
306 /* query status */
307 target_read_u8(target, adr, &status);
308
309 /* clear status, also clear read array */
310 target_write_u16(target, adr, 0x50);
311
312 /* read array command */
313 target_write_u16(target, adr, 0xFF);
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 = ERROR_OK;
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 LOG_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 LOG_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 LOG_ERROR("error executing str9x flash write algorithm");
403 break;
404 }
405
406 if (buf_get_u32(reg_params[3].value, 0, 32) != 0x80)
407 {
408 retval = ERROR_FLASH_OPERATION_FAILED;
409 break;
410 }
411
412 buffer += thisrun_count * 2;
413 address += thisrun_count * 2;
414 count -= thisrun_count;
415 }
416
417 target_free_working_area(target, source);
418 target_free_working_area(target, str9x_info->write_algorithm);
419
420 destroy_reg_param(&reg_params[0]);
421 destroy_reg_param(&reg_params[1]);
422 destroy_reg_param(&reg_params[2]);
423 destroy_reg_param(&reg_params[3]);
424
425 return retval;
426 }
427
428 int str9x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
429 {
430 target_t *target = bank->target;
431 u32 words_remaining = (count / 2);
432 u32 bytes_remaining = (count & 0x00000001);
433 u32 address = bank->base + offset;
434 u32 bytes_written = 0;
435 u8 status;
436 u32 retval;
437 u32 check_address = offset;
438 u32 bank_adr;
439 int i;
440
441 if (bank->target->state != TARGET_HALTED)
442 {
443 return ERROR_TARGET_NOT_HALTED;
444 }
445
446 if (offset & 0x1)
447 {
448 LOG_WARNING("offset 0x%x breaks required 2-byte alignment", offset);
449 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
450 }
451
452 for (i = 0; i < bank->num_sectors; i++)
453 {
454 u32 sec_start = bank->sectors[i].offset;
455 u32 sec_end = sec_start + bank->sectors[i].size;
456
457 /* check if destination falls within the current sector */
458 if ((check_address >= sec_start) && (check_address < sec_end))
459 {
460 /* check if destination ends in the current sector */
461 if (offset + count < sec_end)
462 check_address = offset + count;
463 else
464 check_address = sec_end;
465 }
466 }
467
468 if (check_address != offset + count)
469 return ERROR_FLASH_DST_OUT_OF_BANK;
470
471 /* multiple half words (2-byte) to be programmed? */
472 if (words_remaining > 0)
473 {
474 /* try using a block write */
475 if ((retval = str9x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK)
476 {
477 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
478 {
479 /* if block write failed (no sufficient working area),
480 * we use normal (slow) single dword accesses */
481 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
482 }
483 else if (retval == ERROR_FLASH_OPERATION_FAILED)
484 {
485 LOG_ERROR("flash writing failed with error code: 0x%x", retval);
486 return ERROR_FLASH_OPERATION_FAILED;
487 }
488 }
489 else
490 {
491 buffer += words_remaining * 2;
492 address += words_remaining * 2;
493 words_remaining = 0;
494 }
495 }
496
497 while (words_remaining > 0)
498 {
499 bank_adr = address & ~0x03;
500
501 /* write data command */
502 target_write_u16(target, bank_adr, 0x40);
503 target->type->write_memory(target, address, 2, 1, buffer + bytes_written);
504
505 /* get status command */
506 target_write_u16(target, bank_adr, 0x70);
507
508 while (1) {
509 target_read_u8(target, bank_adr, &status);
510 if( status & 0x80 )
511 break;
512 usleep(1000);
513 }
514
515 /* clear status reg and read array */
516 target_write_u16(target, bank_adr, 0x50);
517 target_write_u16(target, bank_adr, 0xFF);
518
519 if (status & 0x10)
520 return ERROR_FLASH_OPERATION_FAILED;
521 else if (status & 0x02)
522 return ERROR_FLASH_OPERATION_FAILED;
523
524 bytes_written += 2;
525 words_remaining--;
526 address += 2;
527 }
528
529 if (bytes_remaining)
530 {
531 u8 last_halfword[2] = {0xff, 0xff};
532 int i = 0;
533
534 while(bytes_remaining > 0)
535 {
536 last_halfword[i++] = *(buffer + bytes_written);
537 bytes_remaining--;
538 bytes_written++;
539 }
540
541 bank_adr = address & ~0x03;
542
543 /* write data comamnd */
544 target_write_u16(target, bank_adr, 0x40);
545 target->type->write_memory(target, address, 2, 1, last_halfword);
546
547 /* query status command */
548 target_write_u16(target, bank_adr, 0x70);
549
550 while (1) {
551 target_read_u8(target, bank_adr, &status);
552 if( status & 0x80 )
553 break;
554 usleep(1000);
555 }
556
557 /* clear status reg and read array */
558 target_write_u16(target, bank_adr, 0x50);
559 target_write_u16(target, bank_adr, 0xFF);
560
561 if (status & 0x10)
562 return ERROR_FLASH_OPERATION_FAILED;
563 else if (status & 0x02)
564 return ERROR_FLASH_OPERATION_FAILED;
565 }
566
567 return ERROR_OK;
568 }
569
570 int str9x_probe(struct flash_bank_s *bank)
571 {
572 return ERROR_OK;
573 }
574
575 int str9x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
576 {
577 return ERROR_OK;
578 }
579
580 int str9x_info(struct flash_bank_s *bank, char *buf, int buf_size)
581 {
582 snprintf(buf, buf_size, "str9x flash driver info" );
583 return ERROR_OK;
584 }
585
586 int str9x_handle_flash_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
587 {
588 str9x_flash_bank_t *str9x_info;
589 flash_bank_t *bank;
590 target_t *target = NULL;
591
592 if (argc < 5)
593 {
594 return ERROR_COMMAND_SYNTAX_ERROR;
595 }
596
597 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
598 if (!bank)
599 {
600 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
601 return ERROR_OK;
602 }
603
604 str9x_info = bank->driver_priv;
605
606 target = bank->target;
607
608 if (bank->target->state != TARGET_HALTED)
609 {
610 return ERROR_TARGET_NOT_HALTED;
611 }
612
613 /* config flash controller */
614 target_write_u32(target, FLASH_BBSR, strtoul(args[1], NULL, 0));
615 target_write_u32(target, FLASH_NBBSR, strtoul(args[2], NULL, 0));
616 target_write_u32(target, FLASH_BBADR, (strtoul(args[3], NULL, 0) >> 2));
617 target_write_u32(target, FLASH_NBBADR, (strtoul(args[4], NULL, 0) >> 2));
618
619 /* set bit 18 instruction TCM order as per flash programming manual */
620 arm966e_write_cp15(target, 62, 0x40000);
621
622 /* enable flash bank 1 */
623 target_write_u32(target, FLASH_CR, 0x18);
624 return ERROR_OK;
625 }

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)