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>
37 #define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */
38 #define FLASH_NBBSR 0x54000004 /* Non-Boot Bank Size Register */
39 #define FLASH_BBADR 0x5400000C /* Boot Bank Base Address Register */
40 #define FLASH_NBBADR 0x54000010 /* Non-Boot Bank Base Address Register */
41 #define FLASH_CR 0x54000018 /* Control Register */
42 #define FLASH_SR 0x5400001C /* Status Register */
43 #define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */
45 struct str9x_flash_bank
{
46 uint32_t *sector_bits
;
49 struct working_area
*write_algorithm
;
52 enum str9x_status_codes
{
53 STR9X_CMD_SUCCESS
= 0,
54 STR9X_INVALID_COMMAND
= 1,
55 STR9X_SRC_ADDR_ERROR
= 2,
56 STR9X_DST_ADDR_ERROR
= 3,
57 STR9X_SRC_ADDR_NOT_MAPPED
= 4,
58 STR9X_DST_ADDR_NOT_MAPPED
= 5,
59 STR9X_COUNT_ERROR
= 6,
60 STR9X_INVALID_SECTOR
= 7,
61 STR9X_SECTOR_NOT_BLANK
= 8,
62 STR9X_SECTOR_NOT_PREPARED
= 9,
63 STR9X_COMPARE_ERROR
= 10,
67 static uint32_t bank1start
= 0x00080000;
69 static int str9x_build_block_list(struct flash_bank
*bank
)
71 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
75 int b0_sectors
= 0, b1_sectors
= 0;
78 /* set if we have large flash str9 */
79 str9x_info
->variant
= 0;
80 str9x_info
->bank1
= 0;
90 bank1start
= 0x00100000;
91 str9x_info
->variant
= 1;
95 bank1start
= 0x00200000;
96 str9x_info
->variant
= 1;
100 str9x_info
->variant
= 1;
101 str9x_info
->bank1
= 1;
103 bank1start
= bank
->base
;
106 str9x_info
->bank1
= 1;
108 bank1start
= bank
->base
;
111 LOG_ERROR("BUG: unknown bank->size encountered");
115 num_sectors
= b0_sectors
+ b1_sectors
;
117 bank
->num_sectors
= num_sectors
;
118 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
119 str9x_info
->sector_bits
= malloc(sizeof(uint32_t) * num_sectors
);
123 for (i
= 0; i
< b0_sectors
; i
++) {
124 bank
->sectors
[num_sectors
].offset
= offset
;
125 bank
->sectors
[num_sectors
].size
= 0x10000;
126 offset
+= bank
->sectors
[i
].size
;
127 bank
->sectors
[num_sectors
].is_erased
= -1;
128 bank
->sectors
[num_sectors
].is_protected
= 1;
129 str9x_info
->sector_bits
[num_sectors
++] = (1 << i
);
132 for (i
= 0; i
< b1_sectors
; i
++) {
133 bank
->sectors
[num_sectors
].offset
= offset
;
134 bank
->sectors
[num_sectors
].size
= str9x_info
->variant
== 0 ? 0x2000 : 0x4000;
135 offset
+= bank
->sectors
[i
].size
;
136 bank
->sectors
[num_sectors
].is_erased
= -1;
137 bank
->sectors
[num_sectors
].is_protected
= 1;
138 if (str9x_info
->variant
)
139 str9x_info
->sector_bits
[num_sectors
++] = (1 << i
);
141 str9x_info
->sector_bits
[num_sectors
++] = (1 << (i
+ 8));
147 /* flash bank str9x <base> <size> 0 0 <target#>
149 FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command
)
151 struct str9x_flash_bank
*str9x_info
;
154 return ERROR_COMMAND_SYNTAX_ERROR
;
156 str9x_info
= malloc(sizeof(struct str9x_flash_bank
));
157 bank
->driver_priv
= str9x_info
;
159 str9x_build_block_list(bank
);
161 str9x_info
->write_algorithm
= NULL
;
166 static int str9x_protect_check(struct flash_bank
*bank
)
169 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
170 struct target
*target
= bank
->target
;
175 uint16_t hstatus
= 0;
177 if (bank
->target
->state
!= TARGET_HALTED
) {
178 LOG_ERROR("Target not halted");
179 return ERROR_TARGET_NOT_HALTED
;
182 /* read level one protection */
184 if (str9x_info
->variant
) {
185 if (str9x_info
->bank1
) {
186 adr
= bank1start
+ 0x18;
187 retval
= target_write_u16(target
, adr
, 0x90);
188 if (retval
!= ERROR_OK
)
190 retval
= target_read_u16(target
, adr
, &hstatus
);
191 if (retval
!= ERROR_OK
)
195 adr
= bank1start
+ 0x14;
196 retval
= target_write_u16(target
, adr
, 0x90);
197 if (retval
!= ERROR_OK
)
199 retval
= target_read_u32(target
, adr
, &status
);
200 if (retval
!= ERROR_OK
)
204 adr
= bank1start
+ 0x10;
205 retval
= target_write_u16(target
, adr
, 0x90);
206 if (retval
!= ERROR_OK
)
208 retval
= target_read_u16(target
, adr
, &hstatus
);
209 if (retval
!= ERROR_OK
)
214 /* read array command */
215 retval
= target_write_u16(target
, adr
, 0xFF);
216 if (retval
!= ERROR_OK
)
219 for (i
= 0; i
< bank
->num_sectors
; i
++) {
220 if (status
& str9x_info
->sector_bits
[i
])
221 bank
->sectors
[i
].is_protected
= 1;
223 bank
->sectors
[i
].is_protected
= 0;
229 static int str9x_erase(struct flash_bank
*bank
, int first
, int last
)
231 struct target
*target
= bank
->target
;
238 if (bank
->target
->state
!= TARGET_HALTED
) {
239 LOG_ERROR("Target not halted");
240 return ERROR_TARGET_NOT_HALTED
;
243 /* Check if we can erase whole bank */
244 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
245 /* Optimize to run erase bank command instead of sector */
247 /* Add timeout duration since erase bank takes more time */
248 total_timeout
= 1000 * bank
->num_sectors
;
250 /* Erase sector command */
252 total_timeout
= 1000;
255 /* this is so the compiler can *know* */
256 assert(total_timeout
> 0);
258 for (i
= first
; i
<= last
; i
++) {
260 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
262 /* erase sectors or block */
263 retval
= target_write_u16(target
, adr
, erase_cmd
);
264 if (retval
!= ERROR_OK
)
266 retval
= target_write_u16(target
, adr
, 0xD0);
267 if (retval
!= ERROR_OK
)
271 retval
= target_write_u16(target
, adr
, 0x70);
272 if (retval
!= ERROR_OK
)
276 for (timeout
= 0; timeout
< total_timeout
; timeout
++) {
277 retval
= target_read_u8(target
, adr
, &status
);
278 if (retval
!= ERROR_OK
)
284 if (timeout
== total_timeout
) {
285 LOG_ERROR("erase timed out");
289 /* clear status, also clear read array */
290 retval
= target_write_u16(target
, adr
, 0x50);
291 if (retval
!= ERROR_OK
)
294 /* read array command */
295 retval
= target_write_u16(target
, adr
, 0xFF);
296 if (retval
!= ERROR_OK
)
300 LOG_ERROR("error erasing flash bank, status: 0x%x", status
);
301 return ERROR_FLASH_OPERATION_FAILED
;
304 /* If we ran erase bank command, we are finished */
305 if (erase_cmd
== 0x80)
309 for (i
= first
; i
<= last
; i
++)
310 bank
->sectors
[i
].is_erased
= 1;
315 static int str9x_protect(struct flash_bank
*bank
,
316 int set
, int first
, int last
)
318 struct target
*target
= bank
->target
;
323 if (bank
->target
->state
!= TARGET_HALTED
) {
324 LOG_ERROR("Target not halted");
325 return ERROR_TARGET_NOT_HALTED
;
328 for (i
= first
; i
<= last
; i
++) {
329 /* Level One Protection */
331 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
333 target_write_u16(target
, adr
, 0x60);
335 target_write_u16(target
, adr
, 0x01);
337 target_write_u16(target
, adr
, 0xD0);
340 target_read_u8(target
, adr
, &status
);
342 /* clear status, also clear read array */
343 target_write_u16(target
, adr
, 0x50);
345 /* read array command */
346 target_write_u16(target
, adr
, 0xFF);
352 static int str9x_write_block(struct flash_bank
*bank
,
353 uint8_t *buffer
, uint32_t offset
, uint32_t count
)
355 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
356 struct target
*target
= bank
->target
;
357 uint32_t buffer_size
= 32768;
358 struct working_area
*source
;
359 uint32_t address
= bank
->base
+ offset
;
360 struct reg_param reg_params
[4];
361 struct arm_algorithm arm_algo
;
362 int retval
= ERROR_OK
;
364 /* see contib/loaders/flash/str9x.s for src */
366 static const uint32_t str9x_flash_write_code
[] = {
368 0xe3c14003, /* bic r4, r1, #3 */
369 0xe3a03040, /* mov r3, #0x40 */
370 0xe1c430b0, /* strh r3, [r4, #0] */
371 0xe0d030b2, /* ldrh r3, [r0], #2 */
372 0xe0c130b2, /* strh r3, [r1], #2 */
373 0xe3a03070, /* mov r3, #0x70 */
374 0xe1c430b0, /* strh r3, [r4, #0] */
376 0xe5d43000, /* ldrb r3, [r4, #0] */
377 0xe3130080, /* tst r3, #0x80 */
378 0x0afffffc, /* beq busy */
379 0xe3a05050, /* mov r5, #0x50 */
380 0xe1c450b0, /* strh r5, [r4, #0] */
381 0xe3a050ff, /* mov r5, #0xFF */
382 0xe1c450b0, /* strh r5, [r4, #0] */
383 0xe3130012, /* tst r3, #0x12 */
384 0x1a000001, /* bne exit */
385 0xe2522001, /* subs r2, r2, #1 */
386 0x1affffed, /* bne write */
388 0xe1200070, /* bkpt #0 */
391 /* flash write code */
392 if (target_alloc_working_area(target
, sizeof(str9x_flash_write_code
),
393 &str9x_info
->write_algorithm
) != ERROR_OK
) {
394 LOG_WARNING("no working area available, can't do block memory writes");
395 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
398 target_write_buffer(target
, str9x_info
->write_algorithm
->address
,
399 sizeof(str9x_flash_write_code
),
400 (uint8_t *)str9x_flash_write_code
);
403 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
405 if (buffer_size
<= 256) {
406 /* if we already allocated the writing code, but failed to get a
407 * buffer, free the algorithm */
408 if (str9x_info
->write_algorithm
)
409 target_free_working_area(target
, str9x_info
->write_algorithm
);
411 LOG_WARNING("no large enough working area available, can't do block memory writes");
412 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
416 arm_algo
.common_magic
= ARM_COMMON_MAGIC
;
417 arm_algo
.core_mode
= ARM_MODE_SVC
;
418 arm_algo
.core_state
= ARM_STATE_ARM
;
420 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
421 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
422 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
423 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
426 uint32_t thisrun_count
= (count
> (buffer_size
/ 2)) ? (buffer_size
/ 2) : count
;
428 target_write_buffer(target
, source
->address
, thisrun_count
* 2, buffer
);
430 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
431 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
432 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
434 retval
= target_run_algorithm(target
, 0, NULL
, 4, reg_params
,
435 str9x_info
->write_algorithm
->address
,
436 0, 10000, &arm_algo
);
437 if (retval
!= ERROR_OK
) {
438 LOG_ERROR("error executing str9x flash write algorithm");
439 retval
= ERROR_FLASH_OPERATION_FAILED
;
443 if (buf_get_u32(reg_params
[3].value
, 0, 32) != 0x80) {
444 retval
= ERROR_FLASH_OPERATION_FAILED
;
448 buffer
+= thisrun_count
* 2;
449 address
+= thisrun_count
* 2;
450 count
-= thisrun_count
;
453 target_free_working_area(target
, source
);
454 target_free_working_area(target
, str9x_info
->write_algorithm
);
456 destroy_reg_param(®_params
[0]);
457 destroy_reg_param(®_params
[1]);
458 destroy_reg_param(®_params
[2]);
459 destroy_reg_param(®_params
[3]);
464 static int str9x_write(struct flash_bank
*bank
,
465 uint8_t *buffer
, uint32_t offset
, uint32_t count
)
467 struct target
*target
= bank
->target
;
468 uint32_t words_remaining
= (count
/ 2);
469 uint32_t bytes_remaining
= (count
& 0x00000001);
470 uint32_t address
= bank
->base
+ offset
;
471 uint32_t bytes_written
= 0;
474 uint32_t check_address
= offset
;
478 if (bank
->target
->state
!= TARGET_HALTED
) {
479 LOG_ERROR("Target not halted");
480 return ERROR_TARGET_NOT_HALTED
;
484 LOG_WARNING("offset 0x%" PRIx32
" breaks required 2-byte alignment", offset
);
485 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
488 for (i
= 0; i
< bank
->num_sectors
; i
++) {
489 uint32_t sec_start
= bank
->sectors
[i
].offset
;
490 uint32_t sec_end
= sec_start
+ bank
->sectors
[i
].size
;
492 /* check if destination falls within the current sector */
493 if ((check_address
>= sec_start
) && (check_address
< sec_end
)) {
494 /* check if destination ends in the current sector */
495 if (offset
+ count
< sec_end
)
496 check_address
= offset
+ count
;
498 check_address
= sec_end
;
502 if (check_address
!= offset
+ count
)
503 return ERROR_FLASH_DST_OUT_OF_BANK
;
505 /* multiple half words (2-byte) to be programmed? */
506 if (words_remaining
> 0) {
507 /* try using a block write */
508 retval
= str9x_write_block(bank
, buffer
, offset
, words_remaining
);
509 if (retval
!= ERROR_OK
) {
510 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
511 /* if block write failed (no sufficient working area),
512 * we use normal (slow) single dword accesses */
513 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
514 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
515 LOG_ERROR("flash writing failed");
516 return ERROR_FLASH_OPERATION_FAILED
;
519 buffer
+= words_remaining
* 2;
520 address
+= words_remaining
* 2;
525 while (words_remaining
> 0) {
526 bank_adr
= address
& ~0x03;
528 /* write data command */
529 target_write_u16(target
, bank_adr
, 0x40);
530 target_write_memory(target
, address
, 2, 1, buffer
+ bytes_written
);
532 /* get status command */
533 target_write_u16(target
, bank_adr
, 0x70);
536 for (timeout
= 0; timeout
< 1000; timeout
++) {
537 target_read_u8(target
, bank_adr
, &status
);
542 if (timeout
== 1000) {
543 LOG_ERROR("write timed out");
547 /* clear status reg and read array */
548 target_write_u16(target
, bank_adr
, 0x50);
549 target_write_u16(target
, bank_adr
, 0xFF);
552 return ERROR_FLASH_OPERATION_FAILED
;
553 else if (status
& 0x02)
554 return ERROR_FLASH_OPERATION_FAILED
;
561 if (bytes_remaining
) {
562 uint8_t last_halfword
[2] = {0xff, 0xff};
564 /* copy the last remaining bytes into the write buffer */
565 memcpy(last_halfword
, buffer
+bytes_written
, bytes_remaining
);
567 bank_adr
= address
& ~0x03;
569 /* write data command */
570 target_write_u16(target
, bank_adr
, 0x40);
571 target_write_memory(target
, address
, 2, 1, last_halfword
);
573 /* query status command */
574 target_write_u16(target
, bank_adr
, 0x70);
577 for (timeout
= 0; timeout
< 1000; timeout
++) {
578 target_read_u8(target
, bank_adr
, &status
);
583 if (timeout
== 1000) {
584 LOG_ERROR("write timed out");
588 /* clear status reg and read array */
589 target_write_u16(target
, bank_adr
, 0x50);
590 target_write_u16(target
, bank_adr
, 0xFF);
593 return ERROR_FLASH_OPERATION_FAILED
;
594 else if (status
& 0x02)
595 return ERROR_FLASH_OPERATION_FAILED
;
601 static int str9x_probe(struct flash_bank
*bank
)
607 COMMAND_HANDLER(str9x_handle_part_id_command
)
613 static int get_str9x_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
615 snprintf(buf
, buf_size
, "str9x flash driver info");
619 COMMAND_HANDLER(str9x_handle_flash_config_command
)
621 struct target
*target
= NULL
;
624 return ERROR_COMMAND_SYNTAX_ERROR
;
626 struct flash_bank
*bank
;
627 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
628 if (ERROR_OK
!= retval
)
631 uint32_t bbsr
, nbbsr
, bbadr
, nbbadr
;
632 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], bbsr
);
633 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], nbbsr
);
634 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[3], bbadr
);
635 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[4], nbbadr
);
637 target
= bank
->target
;
639 if (bank
->target
->state
!= TARGET_HALTED
) {
640 LOG_ERROR("Target not halted");
641 return ERROR_TARGET_NOT_HALTED
;
644 /* config flash controller */
645 target_write_u32(target
, FLASH_BBSR
, bbsr
);
646 target_write_u32(target
, FLASH_NBBSR
, nbbsr
);
647 target_write_u32(target
, FLASH_BBADR
, bbadr
>> 2);
648 target_write_u32(target
, FLASH_NBBADR
, nbbadr
>> 2);
650 /* set bit 18 instruction TCM order as per flash programming manual */
651 arm966e_write_cp15(target
, 62, 0x40000);
653 /* enable flash bank 1 */
654 target_write_u32(target
, FLASH_CR
, 0x18);
658 static const struct command_registration str9x_config_command_handlers
[] = {
660 .name
= "flash_config",
661 .handler
= str9x_handle_flash_config_command
,
662 .mode
= COMMAND_EXEC
,
663 .help
= "Configure str9x flash controller, prior to "
664 "programming the flash.",
665 .usage
= "bank_id BBSR NBBSR BBADR NBBADR",
667 COMMAND_REGISTRATION_DONE
670 static const struct command_registration str9x_command_handlers
[] = {
674 .help
= "str9x flash command group",
676 .chain
= str9x_config_command_handlers
,
678 COMMAND_REGISTRATION_DONE
681 struct flash_driver str9x_flash
= {
683 .commands
= str9x_command_handlers
,
684 .flash_bank_command
= str9x_flash_bank_command
,
685 .erase
= str9x_erase
,
686 .protect
= str9x_protect
,
687 .write
= str9x_write
,
688 .read
= default_flash_read
,
689 .probe
= str9x_probe
,
690 .auto_probe
= str9x_probe
,
691 .erase_check
= default_flash_blank_check
,
692 .protect_check
= str9x_protect_check
,
693 .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)