Hi I did this optimization some time ago, and I'm sorry it contains a bug as you discovered. The problem is the timeout.
Thanks alot to Henrik Persson at Securitas Direct who spotted the bug in
the first place and patched it.
The timeout is currently set to 1000 eventhough the bank-erase takes alot
more time than the sector-erase.
Its needed to multiply the timeout with the number of sectors erased, then
its still fast and the optimization works fine.
Sorry for this.
This is the patch that fix the timeout issue:
-------------START------------
diff --git a/src/flash/nor/str9x.c b/src/flash/nor/str9x.c
index 0875851..ca4bd27 100644
--- a/src/flash/nor/str9x.c
+++ b/src/flash/nor/str9x.c
@@ -223,6 +223,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 +231,26 @@ 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;
+ 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 +267,7 @@ 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 +276,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 +299,11 @@ 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++)
-------------END-------------
Thanks/Fredrik
> The docs say a maximum timeout of 11.5secs for the largest bank (512k).
My problem with these sort of optimizations is that they *must* be
balanced
with an equal amount of testing. IMHO, since we discovered this on
a simple smoketest, there just isn't enough testing done to justify
having that extra codepath.
--
Øyvind Harboe
US toll free 1-866-980-3434 / International +47 51 63 25 00
http://www.zylin.com/zy1000.html
ARM7 ARM9 ARM11 XScale Cortex
JTAG debugger and flash programmer
str9x_erase.patch
Description: Binary data
_______________________________________________ Openocd-development mailing list [email protected] https://lists.berlios.de/mailman/listinfo/openocd-development
