X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstr9x.c;h=8f8e83c885c249e3e1165e739f0b121ae86dfeef;hb=ae68ddc25e11a88edee09aa547c2816231a9e636;hp=528e52e26901c0e32d0d05a8c98be5a35da982b3;hpb=b05ae413314f48832dd12c994b85c9aad8632967;p=openocd.git diff --git a/src/flash/nor/str9x.c b/src/flash/nor/str9x.c index 528e52e269..8f8e83c885 100644 --- a/src/flash/nor/str9x.c +++ b/src/flash/nor/str9x.c @@ -28,11 +28,45 @@ #endif #include "imp.h" -#include "str9x.h" #include #include +/* Flash registers */ + +#define FLASH_BBSR 0x54000000 /* Boot Bank Size Register */ +#define FLASH_NBBSR 0x54000004 /* Non-Boot Bank Size Register */ +#define FLASH_BBADR 0x5400000C /* Boot Bank Base Address Register */ +#define FLASH_NBBADR 0x54000010 /* Non-Boot Bank Base Address Register */ +#define FLASH_CR 0x54000018 /* Control Register */ +#define FLASH_SR 0x5400001C /* Status Register */ +#define FLASH_BCE5ADDR 0x54000020 /* BC Fifth Entry Target Address Register */ + + +struct str9x_flash_bank +{ + uint32_t *sector_bits; + int variant; + int bank1; + struct working_area *write_algorithm; +}; + +enum str9x_status_codes +{ + STR9X_CMD_SUCCESS = 0, + STR9X_INVALID_COMMAND = 1, + STR9X_SRC_ADDR_ERROR = 2, + STR9X_DST_ADDR_ERROR = 3, + STR9X_SRC_ADDR_NOT_MAPPED = 4, + STR9X_DST_ADDR_NOT_MAPPED = 5, + STR9X_COUNT_ERROR = 6, + STR9X_INVALID_SECTOR = 7, + STR9X_SECTOR_NOT_BLANK = 8, + STR9X_SECTOR_NOT_PREPARED = 9, + STR9X_COMPARE_ERROR = 10, + STR9X_BUSY = 11 +}; + static uint32_t bank1start = 0x00080000; static int str9x_build_block_list(struct flash_bank *bank) @@ -223,6 +257,7 @@ static int str9x_erase(struct flash_bank *bank, int first, int last) uint32_t adr; uint8_t status; uint8_t erase_cmd; + int total_timeout; if (bank->target->state != TARGET_HALTED) { @@ -230,16 +265,27 @@ static int str9x_erase(struct flash_bank *bank, int first, int last) return ERROR_TARGET_NOT_HALTED; } - /*A slower but stable way of erasing*/ - /* Erase sector command */ - erase_cmd = 0x20; + /* Check if we can erase whole bank */ + if ((first == 0) && (last == (bank->num_sectors - 1))) + { + /* Optimize to run erase bank command instead of sector */ + erase_cmd = 0x80; + /* Add timeout duration since erase bank takes more time */ + total_timeout = 1000 * bank->num_sectors; + } + else + { + /* Erase sector command */ + erase_cmd = 0x20; + total_timeout = 1000; + } for (i = first; i <= last; i++) { int retval; adr = bank->base + bank->sectors[i].offset; - /* erase sectors */ + /* erase sectors or block */ if ((retval = target_write_u16(target, adr, erase_cmd)) != ERROR_OK) { return retval; @@ -256,7 +302,8 @@ static int str9x_erase(struct flash_bank *bank, int first, int last) } int timeout; - for (timeout = 0; timeout < 1000; timeout++) { + for (timeout = 0; timeout < total_timeout; timeout++) + { if ((retval = target_read_u8(target, adr, &status)) != ERROR_OK) { return retval; @@ -265,7 +312,7 @@ static int str9x_erase(struct flash_bank *bank, int first, int last) break; alive_sleep(1); } - if (timeout == 1000) + if (timeout == total_timeout) { LOG_ERROR("erase timed out"); return ERROR_FAIL; @@ -288,6 +335,10 @@ static int str9x_erase(struct flash_bank *bank, int first, int last) LOG_ERROR("error erasing flash bank, status: 0x%x", status); return ERROR_FLASH_OPERATION_FAILED; } + + /* If we ran erase bank command, we are finished */ + if (erase_cmd == 0x80) + break; } for (i = first; i <= last; i++) @@ -347,6 +398,8 @@ static int str9x_write_block(struct flash_bank *bank, struct arm_algorithm armv4_5_info; int retval = ERROR_OK; + /* see contib/loaders/flash/str9x.s for src */ + static const uint32_t str9x_flash_write_code[] = { /* write: */ 0xe3c14003, /* bic r4, r1, #3 */