flash/nor/atsame5: Fix a timeout when erasing

According to the datasheet, erasing a block can take up to 200 ms.
When using a Segger J-Link with a 2 MHz clock the current loop
finishes after < 50 ms, ignores the timeout, and then fails when
erasing the next block.

Switch to a time based check, add an explicit yield, and report an
error on timeout.

Change-Id: I8255401d1e59f427a08d2cccb8a66143dcdbb324
Signed-off-by: Michael Hope <mlhx@google.com>
Reviewed-on: http://openocd.zylin.com/5706
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
This commit is contained in:
Michael Hope 2020-05-29 22:30:44 +02:00 committed by Tomas Vanek
parent 7c88e76a76
commit a2e6982a18
1 changed files with 16 additions and 6 deletions

View File

@ -27,6 +27,7 @@
#include "imp.h" #include "imp.h"
#include "helper/binarybuffer.h" #include "helper/binarybuffer.h"
#include <helper/time_support.h>
#include <target/cortex_m.h> #include <target/cortex_m.h>
/* A note to prefixing. /* A note to prefixing.
@ -338,20 +339,29 @@ static int same5_probe(struct flash_bank *bank)
static int same5_wait_and_check_error(struct target *target) static int same5_wait_and_check_error(struct target *target)
{ {
int ret, ret2; int ret, ret2;
int rep_cnt = 100; /* Table 54-40 lists the maximum erase block time as 200 ms.
* Include some margin.
*/
int timeout_ms = 200 * 5;
int64_t ts_start = timeval_ms();
uint16_t intflag; uint16_t intflag;
do { do {
ret = target_read_u16(target, ret = target_read_u16(target,
SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, &intflag); SAMD_NVMCTRL + SAME5_NVMCTRL_INTFLAG, &intflag);
if (ret == ERROR_OK && intflag & SAME5_NVMCTRL_INTFLAG_DONE)
break;
} while (--rep_cnt);
if (ret != ERROR_OK) { if (ret != ERROR_OK) {
LOG_ERROR("Can't read NVM INTFLAG"); LOG_ERROR("SAM: error reading the NVMCTRL_INTFLAG register");
return ret; return ret;
} }
if (intflag & SAME5_NVMCTRL_INTFLAG_DONE)
break;
keep_alive();
} while (timeval_ms() - ts_start < timeout_ms);
if (!(intflag & SAME5_NVMCTRL_INTFLAG_DONE)) {
LOG_ERROR("SAM: NVM programming timed out");
ret = ERROR_FLASH_OPERATION_FAILED;
}
#if 0 #if 0
if (intflag & SAME5_NVMCTRL_INTFLAG_ECCSE) if (intflag & SAME5_NVMCTRL_INTFLAG_ECCSE)
LOG_ERROR("SAM: ECC Single Error"); LOG_ERROR("SAM: ECC Single Error");