This is an automated email from Gerrit.

"Dan Stahlke <d...@stahlke.org>" just uploaded a new patch set to Gerrit, which 
you can find at https://review.openocd.org/c/openocd/+/7391

-- gerrit

commit 3894c5c3f9896f513029b78a224f98ddd173e3f6
Author: Dan Stahlke <d...@stahlke.org>
Date:   Sun Dec 4 18:12:16 2022 -0800

    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 <d...@stahlke.org>
    Change-Id: I19745dae4d3fc6e3a7611dcac628e067cb41e0f0

diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c
index f213444d1f..23b1eacb0a 100644
--- a/src/flash/nor/at91samd.c
+++ b/src/flash/nor/at91samd.c
@@ -12,6 +12,7 @@
 #include "imp.h"
 #include "helper/binarybuffer.h"
 
+#include <helper/time_support.h>
 #include <jtag/jtag.h>
 #include <target/cortex_m.h>
 
@@ -31,7 +32,7 @@
 #define SAMD_NVMCTRL_CTRLA             0x00    /* NVM control A register */
 #define SAMD_NVMCTRL_CTRLB             0x04    /* NVM control B register */
 #define SAMD_NVMCTRL_PARAM             0x08    /* NVM parameters register */
-#define SAMD_NVMCTRL_INTFLAG   0x18    /* NVM Interrupt Flag Status & Clear */
+#define SAMD_NVMCTRL_INTFLAG   0x14    /* NVM Interrupt Flag Status & Clear */
 #define SAMD_NVMCTRL_STATUS            0x18    /* NVM status register */
 #define SAMD_NVMCTRL_ADDR              0x1C    /* NVM address register */
 #define SAMD_NVMCTRL_LOCK              0x20    /* NVM Lock section register */
@@ -497,7 +498,27 @@ static int samd_probe(struct flash_bank *bank)
 static int samd_check_error(struct target *target)
 {
        int ret, ret2;
+       uint8_t intflag;
        uint16_t status;
+       int timeout_ms = 1000;
+       int64_t ts_start = timeval_ms();
+
+       do {
+               ret = target_read_u8(target,
+                       SAMD_NVMCTRL + SAMD_NVMCTRL_INTFLAG, &intflag);
+               if (ret != ERROR_OK) {
+                       LOG_ERROR("Can't read NVM intflag");
+                       return ret;
+               }
+               if(intflag & 1) // READY
+                       break;
+               keep_alive();
+       } while (timeval_ms() - ts_start < timeout_ms);
+
+       if (!(intflag & 1)) {
+               LOG_ERROR("SAMD: NVM programming timed out");
+               ret = ERROR_FLASH_OPERATION_FAILED;
+       }
 
        ret = target_read_u16(target,
                        SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status);

-- 

Reply via email to