1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
32 #include <target/arm966e.h>
33 #include <target/algorithm.h>
36 static uint32_t bank1start
= 0x00080000;
38 static int str9x_build_block_list(struct flash_bank
*bank
)
40 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
44 int b0_sectors
= 0, b1_sectors
= 0;
47 /* set if we have large flash str9 */
48 str9x_info
->variant
= 0;
49 str9x_info
->bank1
= 0;
60 bank1start
= 0x00100000;
61 str9x_info
->variant
= 1;
65 bank1start
= 0x00200000;
66 str9x_info
->variant
= 1;
70 str9x_info
->variant
= 1;
71 str9x_info
->bank1
= 1;
73 bank1start
= bank
->base
;
76 str9x_info
->bank1
= 1;
78 bank1start
= bank
->base
;
81 LOG_ERROR("BUG: unknown bank->size encountered");
85 num_sectors
= b0_sectors
+ b1_sectors
;
87 bank
->num_sectors
= num_sectors
;
88 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
89 str9x_info
->sector_bits
= malloc(sizeof(uint32_t) * num_sectors
);
93 for (i
= 0; i
< b0_sectors
; i
++)
95 bank
->sectors
[num_sectors
].offset
= offset
;
96 bank
->sectors
[num_sectors
].size
= 0x10000;
97 offset
+= bank
->sectors
[i
].size
;
98 bank
->sectors
[num_sectors
].is_erased
= -1;
99 bank
->sectors
[num_sectors
].is_protected
= 1;
100 str9x_info
->sector_bits
[num_sectors
++] = (1 << i
);
103 for (i
= 0; i
< b1_sectors
; i
++)
105 bank
->sectors
[num_sectors
].offset
= offset
;
106 bank
->sectors
[num_sectors
].size
= str9x_info
->variant
== 0 ? 0x2000 : 0x4000;
107 offset
+= bank
->sectors
[i
].size
;
108 bank
->sectors
[num_sectors
].is_erased
= -1;
109 bank
->sectors
[num_sectors
].is_protected
= 1;
110 if (str9x_info
->variant
)
111 str9x_info
->sector_bits
[num_sectors
++] = (1 << i
);
113 str9x_info
->sector_bits
[num_sectors
++] = (1 << (i
+ 8));
119 /* flash bank str9x <base> <size> 0 0 <target#>
121 FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command
)
123 struct str9x_flash_bank
*str9x_info
;
127 LOG_WARNING("incomplete flash_bank str9x configuration");
128 return ERROR_FLASH_BANK_INVALID
;
131 str9x_info
= malloc(sizeof(struct str9x_flash_bank
));
132 bank
->driver_priv
= str9x_info
;
134 str9x_build_block_list(bank
);
136 str9x_info
->write_algorithm
= NULL
;
141 static int str9x_protect_check(struct flash_bank
*bank
)
144 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
145 struct target
*target
= bank
->target
;
150 uint16_t hstatus
= 0;
152 if (bank
->target
->state
!= TARGET_HALTED
)
154 LOG_ERROR("Target not halted");
155 return ERROR_TARGET_NOT_HALTED
;
158 /* read level one protection */
160 if (str9x_info
->variant
)
162 if (str9x_info
->bank1
)
164 adr
= bank1start
+ 0x18;
165 if ((retval
= target_write_u16(target
, adr
, 0x90)) != ERROR_OK
)
169 if ((retval
= target_read_u16(target
, adr
, &hstatus
)) != ERROR_OK
)
177 adr
= bank1start
+ 0x14;
178 if ((retval
= target_write_u16(target
, adr
, 0x90)) != ERROR_OK
)
182 if ((retval
= target_read_u32(target
, adr
, &status
)) != ERROR_OK
)
190 adr
= bank1start
+ 0x10;
191 if ((retval
= target_write_u16(target
, adr
, 0x90)) != ERROR_OK
)
195 if ((retval
= target_read_u16(target
, adr
, &hstatus
)) != ERROR_OK
)
202 /* read array command */
203 if ((retval
= target_write_u16(target
, adr
, 0xFF)) != ERROR_OK
)
208 for (i
= 0; i
< bank
->num_sectors
; i
++)
210 if (status
& str9x_info
->sector_bits
[i
])
211 bank
->sectors
[i
].is_protected
= 1;
213 bank
->sectors
[i
].is_protected
= 0;
219 static int str9x_erase(struct flash_bank
*bank
, int first
, int last
)
221 struct target
*target
= bank
->target
;
228 if (bank
->target
->state
!= TARGET_HALTED
)
230 LOG_ERROR("Target not halted");
231 return ERROR_TARGET_NOT_HALTED
;
234 /* Check if we can erase whole bank */
235 if ((first
== 0) && (last
== (bank
->num_sectors
- 1)))
237 /* Optimize to run erase bank command instead of sector */
239 /* Add timeout duration since erase bank takes more time */
240 total_timeout
= 1000 * bank
->num_sectors
;
244 /* Erase sector command */
246 total_timeout
= 1000;
249 for (i
= first
; i
<= last
; i
++)
252 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
254 /* erase sectors or block */
255 if ((retval
= target_write_u16(target
, adr
, erase_cmd
)) != ERROR_OK
)
259 if ((retval
= target_write_u16(target
, adr
, 0xD0)) != ERROR_OK
)
265 if ((retval
= target_write_u16(target
, adr
, 0x70)) != ERROR_OK
)
271 for (timeout
= 0; timeout
< total_timeout
; timeout
++)
273 if ((retval
= target_read_u8(target
, adr
, &status
)) != ERROR_OK
)
281 if (timeout
== total_timeout
)
283 LOG_ERROR("erase timed out");
287 /* clear status, also clear read array */
288 if ((retval
= target_write_u16(target
, adr
, 0x50)) != ERROR_OK
)
293 /* read array command */
294 if ((retval
= target_write_u16(target
, adr
, 0xFF)) != ERROR_OK
)
301 LOG_ERROR("error erasing flash bank, status: 0x%x", status
);
302 return ERROR_FLASH_OPERATION_FAILED
;
305 /* If we ran erase bank command, we are finished */
306 if (erase_cmd
== 0x80)
310 for (i
= first
; i
<= last
; i
++)
311 bank
->sectors
[i
].is_erased
= 1;
316 static int str9x_protect(struct flash_bank
*bank
,
317 int set
, int first
, int last
)
319 struct target
*target
= bank
->target
;
324 if (bank
->target
->state
!= TARGET_HALTED
)
326 LOG_ERROR("Target not halted");
327 return ERROR_TARGET_NOT_HALTED
;
330 for (i
= first
; i
<= last
; i
++)
332 /* Level One Protection */
334 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
336 target_write_u16(target
, adr
, 0x60);
338 target_write_u16(target
, adr
, 0x01);
340 target_write_u16(target
, adr
, 0xD0);
343 target_read_u8(target
, adr
, &status
);
345 /* clear status, also clear read array */
346 target_write_u16(target
, adr
, 0x50);
348 /* read array command */
349 target_write_u16(target
, adr
, 0xFF);
355 static int str9x_write_block(struct flash_bank
*bank
,
356 uint8_t *buffer
, uint32_t offset
, uint32_t count
)
358 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
359 struct target
*target
= bank
->target
;
360 uint32_t buffer_size
= 32768;
361 struct working_area
*source
;
362 uint32_t address
= bank
->base
+ offset
;
363 struct reg_param reg_params
[4];
364 struct arm_algorithm armv4_5_info
;
365 int retval
= ERROR_OK
;
367 /* see contib/loaders/flash/str9x.s for src */
369 static const uint32_t str9x_flash_write_code
[] = {
371 0xe3c14003, /* bic r4, r1, #3 */
372 0xe3a03040, /* mov r3, #0x40 */
373 0xe1c430b0, /* strh r3, [r4, #0] */
374 0xe0d030b2, /* ldrh r3, [r0], #2 */
375 0xe0c130b2, /* strh r3, [r1], #2 */
376 0xe3a03070, /* mov r3, #0x70 */
377 0xe1c430b0, /* strh r3, [r4, #0] */
379 0xe5d43000, /* ldrb r3, [r4, #0] */
380 0xe3130080, /* tst r3, #0x80 */
381 0x0afffffc, /* beq busy */
382 0xe3a05050, /* mov r5, #0x50 */
383 0xe1c450b0, /* strh r5, [r4, #0] */
384 0xe3a050ff, /* mov r5, #0xFF */
385 0xe1c450b0, /* strh r5, [r4, #0] */
386 0xe3130012, /* tst r3, #0x12 */
387 0x1a000001, /* bne exit */
388 0xe2522001, /* subs r2, r2, #1 */
389 0x1affffed, /* bne write */
391 0xe1200070, /* bkpt #0 */
394 /* flash write code */
395 if (target_alloc_working_area(target
, sizeof(str9x_flash_write_code
),
396 &str9x_info
->write_algorithm
) != ERROR_OK
)
398 LOG_WARNING("no working area available, can't do block memory writes");
399 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
402 target_write_buffer(target
, str9x_info
->write_algorithm
->address
,
403 sizeof(str9x_flash_write_code
),
404 (uint8_t*)str9x_flash_write_code
);
407 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
)
410 if (buffer_size
<= 256)
412 /* if we already allocated the writing code, but failed to get a
413 * buffer, free the algorithm */
414 if (str9x_info
->write_algorithm
)
415 target_free_working_area(target
, str9x_info
->write_algorithm
);
417 LOG_WARNING("no large enough working area available, can't do block memory writes");
418 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
422 armv4_5_info
.common_magic
= ARM_COMMON_MAGIC
;
423 armv4_5_info
.core_mode
= ARM_MODE_SVC
;
424 armv4_5_info
.core_state
= ARM_STATE_ARM
;
426 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
427 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
428 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
429 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
433 uint32_t thisrun_count
= (count
> (buffer_size
/ 2)) ? (buffer_size
/ 2) : count
;
435 target_write_buffer(target
, source
->address
, thisrun_count
* 2, buffer
);
437 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
438 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
439 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
441 if ((retval
= target_run_algorithm(target
, 0, NULL
, 4, reg_params
,
442 str9x_info
->write_algorithm
->address
,
443 0, 10000, &armv4_5_info
)) != ERROR_OK
)
445 LOG_ERROR("error executing str9x flash write algorithm");
446 retval
= ERROR_FLASH_OPERATION_FAILED
;
450 if (buf_get_u32(reg_params
[3].value
, 0, 32) != 0x80)
452 retval
= ERROR_FLASH_OPERATION_FAILED
;
456 buffer
+= thisrun_count
* 2;
457 address
+= thisrun_count
* 2;
458 count
-= thisrun_count
;
461 target_free_working_area(target
, source
);
462 target_free_working_area(target
, str9x_info
->write_algorithm
);
464 destroy_reg_param(®_params
[0]);
465 destroy_reg_param(®_params
[1]);
466 destroy_reg_param(®_params
[2]);
467 destroy_reg_param(®_params
[3]);
472 static int str9x_write(struct flash_bank
*bank
,
473 uint8_t *buffer
, uint32_t offset
, uint32_t count
)
475 struct target
*target
= bank
->target
;
476 uint32_t words_remaining
= (count
/ 2);
477 uint32_t bytes_remaining
= (count
& 0x00000001);
478 uint32_t address
= bank
->base
+ offset
;
479 uint32_t bytes_written
= 0;
482 uint32_t check_address
= offset
;
486 if (bank
->target
->state
!= TARGET_HALTED
)
488 LOG_ERROR("Target not halted");
489 return ERROR_TARGET_NOT_HALTED
;
494 LOG_WARNING("offset 0x%" PRIx32
" breaks required 2-byte alignment", offset
);
495 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
498 for (i
= 0; i
< bank
->num_sectors
; i
++)
500 uint32_t sec_start
= bank
->sectors
[i
].offset
;
501 uint32_t sec_end
= sec_start
+ bank
->sectors
[i
].size
;
503 /* check if destination falls within the current sector */
504 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
506 /* check if destination ends in the current sector */
507 if (offset
+ count
< sec_end
)
508 check_address
= offset
+ count
;
510 check_address
= sec_end
;
514 if (check_address
!= offset
+ count
)
515 return ERROR_FLASH_DST_OUT_OF_BANK
;
517 /* multiple half words (2-byte) to be programmed? */
518 if (words_remaining
> 0)
520 /* try using a block write */
521 if ((retval
= str9x_write_block(bank
, buffer
, offset
, words_remaining
)) != ERROR_OK
)
523 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
525 /* if block write failed (no sufficient working area),
526 * we use normal (slow) single dword accesses */
527 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
529 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
531 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
532 return ERROR_FLASH_OPERATION_FAILED
;
537 buffer
+= words_remaining
* 2;
538 address
+= words_remaining
* 2;
543 while (words_remaining
> 0)
545 bank_adr
= address
& ~0x03;
547 /* write data command */
548 target_write_u16(target
, bank_adr
, 0x40);
549 target_write_memory(target
, address
, 2, 1, buffer
+ bytes_written
);
551 /* get status command */
552 target_write_u16(target
, bank_adr
, 0x70);
555 for (timeout
= 0; timeout
< 1000; timeout
++)
557 target_read_u8(target
, bank_adr
, &status
);
564 LOG_ERROR("write timed out");
568 /* clear status reg and read array */
569 target_write_u16(target
, bank_adr
, 0x50);
570 target_write_u16(target
, bank_adr
, 0xFF);
573 return ERROR_FLASH_OPERATION_FAILED
;
574 else if (status
& 0x02)
575 return ERROR_FLASH_OPERATION_FAILED
;
584 uint8_t last_halfword
[2] = {0xff, 0xff};
587 while (bytes_remaining
> 0)
589 last_halfword
[i
++] = *(buffer
+ bytes_written
);
594 bank_adr
= address
& ~0x03;
596 /* write data command */
597 target_write_u16(target
, bank_adr
, 0x40);
598 target_write_memory(target
, address
, 2, 1, last_halfword
);
600 /* query status command */
601 target_write_u16(target
, bank_adr
, 0x70);
604 for (timeout
= 0; timeout
< 1000; timeout
++)
606 target_read_u8(target
, bank_adr
, &status
);
613 LOG_ERROR("write timed out");
617 /* clear status reg and read array */
618 target_write_u16(target
, bank_adr
, 0x50);
619 target_write_u16(target
, bank_adr
, 0xFF);
622 return ERROR_FLASH_OPERATION_FAILED
;
623 else if (status
& 0x02)
624 return ERROR_FLASH_OPERATION_FAILED
;
630 static int str9x_probe(struct flash_bank
*bank
)
636 COMMAND_HANDLER(str9x_handle_part_id_command
)
642 static int get_str9x_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
644 snprintf(buf
, buf_size
, "str9x flash driver info");
648 COMMAND_HANDLER(str9x_handle_flash_config_command
)
650 struct str9x_flash_bank
*str9x_info
;
651 struct target
*target
= NULL
;
655 return ERROR_COMMAND_SYNTAX_ERROR
;
658 struct flash_bank
*bank
;
659 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
660 if (ERROR_OK
!= retval
)
663 uint32_t bbsr
, nbbsr
, bbadr
, nbbadr
;
664 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], bbsr
);
665 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], nbbsr
);
666 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[3], bbadr
);
667 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[4], nbbadr
);
669 str9x_info
= bank
->driver_priv
;
671 target
= bank
->target
;
673 if (bank
->target
->state
!= TARGET_HALTED
)
675 LOG_ERROR("Target not halted");
676 return ERROR_TARGET_NOT_HALTED
;
679 /* config flash controller */
680 target_write_u32(target
, FLASH_BBSR
, bbsr
);
681 target_write_u32(target
, FLASH_NBBSR
, nbbsr
);
682 target_write_u32(target
, FLASH_BBADR
, bbadr
>> 2);
683 target_write_u32(target
, FLASH_NBBADR
, nbbadr
>> 2);
685 /* set bit 18 instruction TCM order as per flash programming manual */
686 arm966e_write_cp15(target
, 62, 0x40000);
688 /* enable flash bank 1 */
689 target_write_u32(target
, FLASH_CR
, 0x18);
693 static const struct command_registration str9x_config_command_handlers
[] = {
695 .name
= "flash_config",
696 .handler
= str9x_handle_flash_config_command
,
697 .mode
= COMMAND_EXEC
,
698 .help
= "Configure str9x flash controller, prior to "
699 "programming the flash.",
700 .usage
= "bank_id BBSR NBBSR BBADR NBBADR",
702 COMMAND_REGISTRATION_DONE
705 static const struct command_registration str9x_command_handlers
[] = {
709 .help
= "str9x flash command group",
710 .chain
= str9x_config_command_handlers
,
712 COMMAND_REGISTRATION_DONE
715 struct flash_driver str9x_flash
= {
717 .commands
= str9x_command_handlers
,
718 .flash_bank_command
= str9x_flash_bank_command
,
719 .erase
= str9x_erase
,
720 .protect
= str9x_protect
,
721 .write
= str9x_write
,
722 .read
= default_flash_read
,
723 .probe
= str9x_probe
,
724 .auto_probe
= str9x_probe
,
725 .erase_check
= default_flash_blank_check
,
726 .protect_check
= str9x_protect_check
,
727 .info
= get_str9x_info
,
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)