Skip to content

Commit 77c7abe

Browse files
dstahlkeborneoa
authored andcommitted
at91samd: wait for nvm ready
Flashing a SAMD21J17D was failing during NVM erase. The samd21 datasheet specifies that one cause of error conditions is executing an NVM command while the previous command is still running. The solution is to wait for INTFLAG.READY after a command is issued. SAMD21J17A was not exhibiting this problem. Perhaps the later silicon revision has slower NVM erase times. Signed-off-by: Dan Stahlke <[email protected]> Change-Id: I19745dae4d3fc6e3a7611dcac628e067cb41e0f0 Reviewed-on: https://review.openocd.org/c/openocd/+/7391 Tested-by: jenkins Reviewed-by: Antonio Borneo <[email protected]> Reviewed-by: Tomas Vanek <[email protected]>
1 parent 0a829ef commit 77c7abe

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

src/flash/nor/at91samd.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "imp.h"
1313
#include "helper/binarybuffer.h"
1414

15+
#include <helper/time_support.h>
1516
#include <jtag/jtag.h>
1617
#include <target/cortex_m.h>
1718

@@ -31,7 +32,7 @@
3132
#define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */
3233
#define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */
3334
#define SAMD_NVMCTRL_PARAM 0x08 /* NVM parameters register */
34-
#define SAMD_NVMCTRL_INTFLAG 0x18 /* NVM Interrupt Flag Status & Clear */
35+
#define SAMD_NVMCTRL_INTFLAG 0x14 /* NVM Interrupt Flag Status & Clear */
3536
#define SAMD_NVMCTRL_STATUS 0x18 /* NVM status register */
3637
#define SAMD_NVMCTRL_ADDR 0x1C /* NVM address register */
3738
#define SAMD_NVMCTRL_LOCK 0x20 /* NVM Lock section register */
@@ -55,6 +56,9 @@
5556
/* NVMCTRL bits */
5657
#define SAMD_NVM_CTRLB_MANW 0x80
5758

59+
/* NVMCTRL_INTFLAG bits */
60+
#define SAMD_NVM_INTFLAG_READY 0x01
61+
5862
/* Known identifiers */
5963
#define SAMD_PROCESSOR_M0 0x01
6064
#define SAMD_FAMILY_D 0x00
@@ -497,7 +501,27 @@ static int samd_probe(struct flash_bank *bank)
497501
static int samd_check_error(struct target *target)
498502
{
499503
int ret, ret2;
504+
uint8_t intflag;
500505
uint16_t status;
506+
int timeout_ms = 1000;
507+
int64_t ts_start = timeval_ms();
508+
509+
do {
510+
ret = target_read_u8(target,
511+
SAMD_NVMCTRL + SAMD_NVMCTRL_INTFLAG, &intflag);
512+
if (ret != ERROR_OK) {
513+
LOG_ERROR("Can't read NVM intflag");
514+
return ret;
515+
}
516+
if (intflag & SAMD_NVM_INTFLAG_READY)
517+
break;
518+
keep_alive();
519+
} while (timeval_ms() - ts_start < timeout_ms);
520+
521+
if (!(intflag & SAMD_NVM_INTFLAG_READY)) {
522+
LOG_ERROR("SAMD: NVM programming timed out");
523+
return ERROR_FLASH_OPERATION_FAILED;
524+
}
501525

502526
ret = target_read_u16(target,
503527
SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);

0 commit comments

Comments
 (0)