1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
7 * Copyright (C) 2008 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
10 * Copyright (C) 2008 by Oyvind Harboe *
11 * oyvind.harboe@zylin.com *
12 ***************************************************************************/
19 #include <target/arm966e.h>
20 #include <target/algorithm.h>
24 #define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */
25 #define FLASH_NBBSR 0x54000004 /* Non-Boot Bank Size Register */
26 #define FLASH_BBADR 0x5400000C /* Boot Bank Base Address Register */
27 #define FLASH_NBBADR 0x54000010 /* Non-Boot Bank Base Address Register */
28 #define FLASH_CR 0x54000018 /* Control Register */
29 #define FLASH_SR 0x5400001C /* Status Register */
30 #define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */
32 struct str9x_flash_bank
{
33 uint32_t *sector_bits
;
38 enum str9x_status_codes
{
39 STR9X_CMD_SUCCESS
= 0,
40 STR9X_INVALID_COMMAND
= 1,
41 STR9X_SRC_ADDR_ERROR
= 2,
42 STR9X_DST_ADDR_ERROR
= 3,
43 STR9X_SRC_ADDR_NOT_MAPPED
= 4,
44 STR9X_DST_ADDR_NOT_MAPPED
= 5,
45 STR9X_COUNT_ERROR
= 6,
46 STR9X_INVALID_SECTOR
= 7,
47 STR9X_SECTOR_NOT_BLANK
= 8,
48 STR9X_SECTOR_NOT_PREPARED
= 9,
49 STR9X_COMPARE_ERROR
= 10,
53 static uint32_t bank1start
= 0x00080000;
55 static int str9x_build_block_list(struct flash_bank
*bank
)
57 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
60 unsigned int num_sectors
;
61 int b0_sectors
= 0, b1_sectors
= 0;
64 /* set if we have large flash str9 */
65 str9x_info
->variant
= 0;
66 str9x_info
->bank1
= 0;
76 bank1start
= 0x00100000;
77 str9x_info
->variant
= 1;
81 bank1start
= 0x00200000;
82 str9x_info
->variant
= 1;
86 str9x_info
->variant
= 1;
87 str9x_info
->bank1
= 1;
89 bank1start
= bank
->base
;
92 str9x_info
->bank1
= 1;
94 bank1start
= bank
->base
;
97 LOG_ERROR("BUG: unknown bank->size encountered");
101 num_sectors
= b0_sectors
+ b1_sectors
;
103 bank
->num_sectors
= num_sectors
;
104 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
105 str9x_info
->sector_bits
= malloc(sizeof(uint32_t) * num_sectors
);
109 for (i
= 0; i
< b0_sectors
; i
++) {
110 bank
->sectors
[num_sectors
].offset
= offset
;
111 bank
->sectors
[num_sectors
].size
= 0x10000;
112 offset
+= bank
->sectors
[i
].size
;
113 bank
->sectors
[num_sectors
].is_erased
= -1;
114 bank
->sectors
[num_sectors
].is_protected
= 1;
115 str9x_info
->sector_bits
[num_sectors
++] = (1 << i
);
118 for (i
= 0; i
< b1_sectors
; i
++) {
119 bank
->sectors
[num_sectors
].offset
= offset
;
120 bank
->sectors
[num_sectors
].size
= str9x_info
->variant
== 0 ? 0x2000 : 0x4000;
121 offset
+= bank
->sectors
[i
].size
;
122 bank
->sectors
[num_sectors
].is_erased
= -1;
123 bank
->sectors
[num_sectors
].is_protected
= 1;
124 if (str9x_info
->variant
)
125 str9x_info
->sector_bits
[num_sectors
++] = (1 << i
);
127 str9x_info
->sector_bits
[num_sectors
++] = (1 << (i
+ 8));
133 /* flash bank str9x <base> <size> 0 0 <target#>
135 FLASH_BANK_COMMAND_HANDLER(str9x_flash_bank_command
)
137 struct str9x_flash_bank
*str9x_info
;
140 return ERROR_COMMAND_SYNTAX_ERROR
;
142 str9x_info
= malloc(sizeof(struct str9x_flash_bank
));
143 bank
->driver_priv
= str9x_info
;
145 str9x_build_block_list(bank
);
150 static int str9x_protect_check(struct flash_bank
*bank
)
153 struct str9x_flash_bank
*str9x_info
= bank
->driver_priv
;
154 struct target
*target
= bank
->target
;
158 uint16_t hstatus
= 0;
160 if (bank
->target
->state
!= TARGET_HALTED
) {
161 LOG_ERROR("Target not halted");
162 return ERROR_TARGET_NOT_HALTED
;
165 /* read level one protection */
167 if (str9x_info
->variant
) {
168 if (str9x_info
->bank1
) {
169 adr
= bank1start
+ 0x18;
170 retval
= target_write_u16(target
, adr
, 0x90);
171 if (retval
!= ERROR_OK
)
173 retval
= target_read_u16(target
, adr
, &hstatus
);
174 if (retval
!= ERROR_OK
)
178 adr
= bank1start
+ 0x14;
179 retval
= target_write_u16(target
, adr
, 0x90);
180 if (retval
!= ERROR_OK
)
182 retval
= target_read_u32(target
, adr
, &status
);
183 if (retval
!= ERROR_OK
)
187 adr
= bank1start
+ 0x10;
188 retval
= target_write_u16(target
, adr
, 0x90);
189 if (retval
!= ERROR_OK
)
191 retval
= target_read_u16(target
, adr
, &hstatus
);
192 if (retval
!= ERROR_OK
)
197 /* read array command */
198 retval
= target_write_u16(target
, adr
, 0xFF);
199 if (retval
!= ERROR_OK
)
202 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
203 if (status
& str9x_info
->sector_bits
[i
])
204 bank
->sectors
[i
].is_protected
= 1;
206 bank
->sectors
[i
].is_protected
= 0;
212 static int str9x_erase(struct flash_bank
*bank
, unsigned int first
,
215 struct target
*target
= bank
->target
;
221 if (bank
->target
->state
!= TARGET_HALTED
) {
222 LOG_ERROR("Target not halted");
223 return ERROR_TARGET_NOT_HALTED
;
226 /* Check if we can erase whole bank */
227 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
228 /* Optimize to run erase bank command instead of sector */
230 /* Add timeout duration since erase bank takes more time */
231 total_timeout
= 1000 * bank
->num_sectors
;
233 /* Erase sector command */
235 total_timeout
= 1000;
238 /* this is so the compiler can *know* */
239 assert(total_timeout
> 0);
241 for (unsigned int i
= first
; i
<= last
; i
++) {
243 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
245 /* erase sectors or block */
246 retval
= target_write_u16(target
, adr
, erase_cmd
);
247 if (retval
!= ERROR_OK
)
249 retval
= target_write_u16(target
, adr
, 0xD0);
250 if (retval
!= ERROR_OK
)
254 retval
= target_write_u16(target
, adr
, 0x70);
255 if (retval
!= ERROR_OK
)
259 for (timeout
= 0; timeout
< total_timeout
; timeout
++) {
260 retval
= target_read_u8(target
, adr
, &status
);
261 if (retval
!= ERROR_OK
)
267 if (timeout
== total_timeout
) {
268 LOG_ERROR("erase timed out");
272 /* clear status, also clear read array */
273 retval
= target_write_u16(target
, adr
, 0x50);
274 if (retval
!= ERROR_OK
)
277 /* read array command */
278 retval
= target_write_u16(target
, adr
, 0xFF);
279 if (retval
!= ERROR_OK
)
283 LOG_ERROR("error erasing flash bank, status: 0x%x", status
);
284 return ERROR_FLASH_OPERATION_FAILED
;
287 /* If we ran erase bank command, we are finished */
288 if (erase_cmd
== 0x80)
295 static int str9x_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
298 struct target
*target
= bank
->target
;
302 if (bank
->target
->state
!= TARGET_HALTED
) {
303 LOG_ERROR("Target not halted");
304 return ERROR_TARGET_NOT_HALTED
;
307 for (unsigned int i
= first
; i
<= last
; i
++) {
308 /* Level One Protection */
310 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
312 target_write_u16(target
, adr
, 0x60);
314 target_write_u16(target
, adr
, 0x01);
316 target_write_u16(target
, adr
, 0xD0);
319 target_read_u8(target
, adr
, &status
);
321 /* clear status, also clear read array */
322 target_write_u16(target
, adr
, 0x50);
324 /* read array command */
325 target_write_u16(target
, adr
, 0xFF);
331 static int str9x_write_block(struct flash_bank
*bank
,
332 const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
334 struct target
*target
= bank
->target
;
335 uint32_t buffer_size
= 32768;
336 struct working_area
*write_algorithm
;
337 struct working_area
*source
;
338 uint32_t address
= bank
->base
+ offset
;
339 struct reg_param reg_params
[4];
340 struct arm_algorithm arm_algo
;
341 int retval
= ERROR_OK
;
343 /* see contrib/loaders/flash/str9x.s for src */
345 static const uint32_t str9x_flash_write_code
[] = {
347 0xe3c14003, /* bic r4, r1, #3 */
348 0xe3a03040, /* mov r3, #0x40 */
349 0xe1c430b0, /* strh r3, [r4, #0] */
350 0xe0d030b2, /* ldrh r3, [r0], #2 */
351 0xe0c130b2, /* strh r3, [r1], #2 */
352 0xe3a03070, /* mov r3, #0x70 */
353 0xe1c430b0, /* strh r3, [r4, #0] */
355 0xe5d43000, /* ldrb r3, [r4, #0] */
356 0xe3130080, /* tst r3, #0x80 */
357 0x0afffffc, /* beq busy */
358 0xe3a05050, /* mov r5, #0x50 */
359 0xe1c450b0, /* strh r5, [r4, #0] */
360 0xe3a050ff, /* mov r5, #0xFF */
361 0xe1c450b0, /* strh r5, [r4, #0] */
362 0xe3130012, /* tst r3, #0x12 */
363 0x1a000001, /* bne exit */
364 0xe2522001, /* subs r2, r2, #1 */
365 0x1affffed, /* bne write */
367 0xe1200070, /* bkpt #0 */
370 /* flash write code */
371 if (target_alloc_working_area(target
, sizeof(str9x_flash_write_code
),
372 &write_algorithm
) != ERROR_OK
) {
373 LOG_WARNING("no working area available, can't do block memory writes");
374 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
377 uint8_t code
[sizeof(str9x_flash_write_code
)];
378 target_buffer_set_u32_array(target
, code
, ARRAY_SIZE(str9x_flash_write_code
),
379 str9x_flash_write_code
);
380 target_write_buffer(target
, write_algorithm
->address
, sizeof(code
), code
);
383 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
385 if (buffer_size
<= 256) {
386 /* we already allocated the writing code, but failed to get a
387 * buffer, free the algorithm */
388 target_free_working_area(target
, write_algorithm
);
390 LOG_WARNING("no large enough working area available, can't do block memory writes");
391 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
395 arm_algo
.common_magic
= ARM_COMMON_MAGIC
;
396 arm_algo
.core_mode
= ARM_MODE_SVC
;
397 arm_algo
.core_state
= ARM_STATE_ARM
;
399 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
400 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
401 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
402 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
405 uint32_t thisrun_count
= (count
> (buffer_size
/ 2)) ? (buffer_size
/ 2) : count
;
407 target_write_buffer(target
, source
->address
, thisrun_count
* 2, buffer
);
409 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
410 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
411 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
413 retval
= target_run_algorithm(target
, 0, NULL
, 4, reg_params
,
414 write_algorithm
->address
,
415 0, 10000, &arm_algo
);
416 if (retval
!= ERROR_OK
) {
417 LOG_ERROR("error executing str9x flash write algorithm");
418 retval
= ERROR_FLASH_OPERATION_FAILED
;
422 if (buf_get_u32(reg_params
[3].value
, 0, 32) != 0x80) {
423 retval
= ERROR_FLASH_OPERATION_FAILED
;
427 buffer
+= thisrun_count
* 2;
428 address
+= thisrun_count
* 2;
429 count
-= thisrun_count
;
432 target_free_working_area(target
, source
);
433 target_free_working_area(target
, write_algorithm
);
435 destroy_reg_param(®_params
[0]);
436 destroy_reg_param(®_params
[1]);
437 destroy_reg_param(®_params
[2]);
438 destroy_reg_param(®_params
[3]);
443 static int str9x_write(struct flash_bank
*bank
,
444 const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
446 struct target
*target
= bank
->target
;
447 uint32_t words_remaining
= (count
/ 2);
448 uint32_t bytes_remaining
= (count
& 0x00000001);
449 uint32_t address
= bank
->base
+ offset
;
450 uint32_t bytes_written
= 0;
453 uint32_t check_address
= offset
;
456 if (bank
->target
->state
!= TARGET_HALTED
) {
457 LOG_ERROR("Target not halted");
458 return ERROR_TARGET_NOT_HALTED
;
462 LOG_WARNING("offset 0x%" PRIx32
" breaks required 2-byte alignment", offset
);
463 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
466 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
467 uint32_t sec_start
= bank
->sectors
[i
].offset
;
468 uint32_t sec_end
= sec_start
+ bank
->sectors
[i
].size
;
470 /* check if destination falls within the current sector */
471 if ((check_address
>= sec_start
) && (check_address
< sec_end
)) {
472 /* check if destination ends in the current sector */
473 if (offset
+ count
< sec_end
)
474 check_address
= offset
+ count
;
476 check_address
= sec_end
;
480 if (check_address
!= offset
+ count
)
481 return ERROR_FLASH_DST_OUT_OF_BANK
;
483 /* multiple half words (2-byte) to be programmed? */
484 if (words_remaining
> 0) {
485 /* try using a block write */
486 retval
= str9x_write_block(bank
, buffer
, offset
, words_remaining
);
487 if (retval
!= ERROR_OK
) {
488 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
489 /* if block write failed (no sufficient working area),
490 * we use normal (slow) single dword accesses */
491 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
492 } else if (retval
== ERROR_FLASH_OPERATION_FAILED
) {
493 LOG_ERROR("flash writing failed");
494 return ERROR_FLASH_OPERATION_FAILED
;
497 buffer
+= words_remaining
* 2;
498 address
+= words_remaining
* 2;
503 while (words_remaining
> 0) {
504 bank_adr
= address
& ~0x03;
506 /* write data command */
507 target_write_u16(target
, bank_adr
, 0x40);
508 target_write_memory(target
, address
, 2, 1, buffer
+ bytes_written
);
510 /* get status command */
511 target_write_u16(target
, bank_adr
, 0x70);
514 for (timeout
= 0; timeout
< 1000; timeout
++) {
515 target_read_u8(target
, bank_adr
, &status
);
520 if (timeout
== 1000) {
521 LOG_ERROR("write timed out");
525 /* clear status reg and read array */
526 target_write_u16(target
, bank_adr
, 0x50);
527 target_write_u16(target
, bank_adr
, 0xFF);
530 return ERROR_FLASH_OPERATION_FAILED
;
531 else if (status
& 0x02)
532 return ERROR_FLASH_OPERATION_FAILED
;
539 if (bytes_remaining
) {
540 uint8_t last_halfword
[2] = {0xff, 0xff};
542 /* copy the last remaining bytes into the write buffer */
543 memcpy(last_halfword
, buffer
+bytes_written
, bytes_remaining
);
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, last_halfword
);
551 /* query status command */
552 target_write_u16(target
, bank_adr
, 0x70);
555 for (timeout
= 0; timeout
< 1000; timeout
++) {
556 target_read_u8(target
, bank_adr
, &status
);
561 if (timeout
== 1000) {
562 LOG_ERROR("write timed out");
566 /* clear status reg and read array */
567 target_write_u16(target
, bank_adr
, 0x50);
568 target_write_u16(target
, bank_adr
, 0xFF);
571 return ERROR_FLASH_OPERATION_FAILED
;
572 else if (status
& 0x02)
573 return ERROR_FLASH_OPERATION_FAILED
;
579 static int str9x_probe(struct flash_bank
*bank
)
585 COMMAND_HANDLER(str9x_handle_part_id_command
)
591 COMMAND_HANDLER(str9x_handle_flash_config_command
)
593 struct target
*target
= NULL
;
596 return ERROR_COMMAND_SYNTAX_ERROR
;
598 struct flash_bank
*bank
;
599 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
600 if (retval
!= ERROR_OK
)
603 uint32_t bbsr
, nbbsr
, bbadr
, nbbadr
;
604 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], bbsr
);
605 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], nbbsr
);
606 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[3], bbadr
);
607 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[4], nbbadr
);
609 target
= bank
->target
;
611 if (bank
->target
->state
!= TARGET_HALTED
) {
612 LOG_ERROR("Target not halted");
613 return ERROR_TARGET_NOT_HALTED
;
616 /* config flash controller */
617 target_write_u32(target
, FLASH_BBSR
, bbsr
);
618 target_write_u32(target
, FLASH_NBBSR
, nbbsr
);
619 target_write_u32(target
, FLASH_BBADR
, bbadr
>> 2);
620 target_write_u32(target
, FLASH_NBBADR
, nbbadr
>> 2);
622 /* set bit 18 instruction TCM order as per flash programming manual */
623 arm966e_write_cp15(target
, 62, 0x40000);
625 /* enable flash bank 1 */
626 target_write_u32(target
, FLASH_CR
, 0x18);
630 static const struct command_registration str9x_config_command_handlers
[] = {
632 .name
= "flash_config",
633 .handler
= str9x_handle_flash_config_command
,
634 .mode
= COMMAND_EXEC
,
635 .help
= "Configure str9x flash controller, prior to "
636 "programming the flash.",
637 .usage
= "bank_id BBSR NBBSR BBADR NBBADR",
639 COMMAND_REGISTRATION_DONE
642 static const struct command_registration str9x_command_handlers
[] = {
646 .help
= "str9x flash command group",
648 .chain
= str9x_config_command_handlers
,
650 COMMAND_REGISTRATION_DONE
653 const struct flash_driver str9x_flash
= {
655 .commands
= str9x_command_handlers
,
656 .flash_bank_command
= str9x_flash_bank_command
,
657 .erase
= str9x_erase
,
658 .protect
= str9x_protect
,
659 .write
= str9x_write
,
660 .read
= default_flash_read
,
661 .probe
= str9x_probe
,
662 .auto_probe
= str9x_probe
,
663 .erase_check
= default_flash_blank_check
,
664 .protect_check
= str9x_protect_check
,
665 .free_driver_priv
= default_flash_free_driver_priv
,
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)