From c3413ff0f45a609a2cb8668485ced2f06b8d6311 Mon Sep 17 00:00:00 2001
From: Stefan Rueger <stefan.rueger@urclocks.com>
Date: Wed, 23 Nov 2022 19:53:55 +0000
Subject: [PATCH 1/2] Fix shell exit value when chip erase is delayed to next
 flash write

---
 src/avr.c        | 20 ++++++++++++++------
 src/libavrdude.h |  4 ++++
 src/main.c       | 10 +++++++---
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/src/avr.c b/src/avr.c
index dee653c0..ade46a0a 100644
--- a/src/avr.c
+++ b/src/avr.c
@@ -1257,16 +1257,24 @@ void avr_add_mem_order(const char *str) {
   exit(1);
 }
 
+int avr_memtype_is_flash_type(const char *memtype) {
+  return memtype && (
+     strcmp(memtype, "flash") == 0 ||
+     strcmp(memtype, "application") == 0 ||
+     strcmp(memtype, "apptable") == 0 ||
+     strcmp(memtype, "boot") == 0);
+}
+
 int avr_mem_is_flash_type(const AVRMEM *mem) {
-  return
-     strcmp(mem->desc, "flash") == 0 ||
-     strcmp(mem->desc, "application") == 0 ||
-     strcmp(mem->desc, "apptable") == 0 ||
-     strcmp(mem->desc, "boot") == 0;
+  return avr_memtype_is_flash_type(mem->desc);
+}
+
+int avr_memtype_is_eeprom_type(const char *memtype) {
+  return memtype && strcmp(memtype, "eeprom") == 0;
 }
 
 int avr_mem_is_eeprom_type(const AVRMEM *mem) {
-  return strcmp(mem->desc, "eeprom") == 0;
+  return avr_memtype_is_eeprom_type(mem->desc);
 }
 
 int avr_mem_is_known(const char *str) {
diff --git a/src/libavrdude.h b/src/libavrdude.h
index 83556af3..ddda1865 100644
--- a/src/libavrdude.h
+++ b/src/libavrdude.h
@@ -897,8 +897,12 @@ int avr_put_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int cycles);
 
 void avr_add_mem_order(const char *str);
 
+int avr_memtype_is_flash_type(const char *mem);
+
 int avr_mem_is_flash_type(const AVRMEM *mem);
 
+int avr_memtype_is_eeprom_type(const char *mem);
+
 int avr_mem_is_eeprom_type(const AVRMEM *mem);
 
 int avr_mem_is_known(const char *str);
diff --git a/src/main.c b/src/main.c
index e249800e..86291013 100644
--- a/src/main.c
+++ b/src/main.c
@@ -495,6 +495,7 @@ int main(int argc, char * argv [])
   int     ispdelay;    /* Specify the delay for ISP clock */
   int     init_ok;     /* Device initialization worked well */
   int     is_open;     /* Device open succeeded */
+  int     ce_delayed;  /* Chip erase delayed */
   char  * logfile;     /* Use logfile rather than stderr for diagnostics */
   enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */
 
@@ -574,6 +575,7 @@ int main(int argc, char * argv [])
   bitclock      = 0.0;
   ispdelay      = 0;
   is_open       = 0;
+  ce_delayed    = 0;
   logfile       = NULL;
 
   len = strlen(progname) + 2;
@@ -1400,7 +1402,8 @@ int main(int argc, char * argv [])
       exitrc = avr_chip_erase(pgm, p);
       if(exitrc == LIBAVRDUDE_SOFTFAIL) {
         imsg_info("delaying chip erase until first -U upload to flash\n");
-        exitrc = 1;
+        ce_delayed = 1;
+        exitrc = 0;
       } else if(exitrc)
         goto main_exit;
     }
@@ -1428,7 +1431,8 @@ int main(int argc, char * argv [])
     if (rc && rc != LIBAVRDUDE_SOFTFAIL) {
       exitrc = 1;
       break;
-    }
+    } else if(rc == 0 && upd->op == DEVICE_WRITE && avr_memtype_is_flash_type(upd->memtype))
+      ce_delayed = 0;           // Redeemed chip erase promise
   }
 
 main_exit:
@@ -1449,5 +1453,5 @@ main_exit:
 
   msg_info("\n%s done.  Thank you.\n\n", progname);
 
-  return exitrc;
+  return ce_delayed? 1: exitrc;
 }

From 2b3534ea8a9f097ad5ec761e1d2f91ec9ab32226 Mon Sep 17 00:00:00 2001
From: Stefan Rueger <stefan.rueger@urclocks.com>
Date: Thu, 24 Nov 2022 12:36:49 +0000
Subject: [PATCH 2/2] Remove tabs and reformat

---
 src/avr.c | 104 ++++++++++++++++++++++++++----------------------------
 1 file changed, 50 insertions(+), 54 deletions(-)

diff --git a/src/avr.c b/src/avr.c
index ade46a0a..010e65c3 100644
--- a/src/avr.c
+++ b/src/avr.c
@@ -49,7 +49,7 @@ int avr_tpi_poll_nvmbsy(const PROGRAMMER *pgm) {
 
 /* TPI chip erase sequence */
 int avr_tpi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
-	int err;
+  int err;
   AVRMEM *mem;
 
   if (p->prog_modes & PM_TPI) {
@@ -62,27 +62,27 @@ int avr_tpi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
       return -1;
     }
 
-		unsigned char cmd[] = {
-			/* write pointer register high byte */
-			(TPI_CMD_SSTPR | 0),
-			((mem->offset & 0xFF) | 1),
-			/* and low byte */
-			(TPI_CMD_SSTPR | 1),
-			((mem->offset >> 8) & 0xFF),
-	    /* write CHIP_ERASE command to NVMCMD register */
-			(TPI_CMD_SOUT | TPI_SIO_ADDR(TPI_IOREG_NVMCMD)),
-			TPI_NVMCMD_CHIP_ERASE,
-			/* write dummy value to start erase */
-			TPI_CMD_SST,
-			0xFF
-		};
+    unsigned char cmd[] = {
+      /* write pointer register high byte */
+      (TPI_CMD_SSTPR | 0),
+      ((mem->offset & 0xFF) | 1),
+      /* and low byte */
+      (TPI_CMD_SSTPR | 1),
+      ((mem->offset >> 8) & 0xFF),
+      /* write CHIP_ERASE command to NVMCMD register */
+      (TPI_CMD_SOUT | TPI_SIO_ADDR(TPI_IOREG_NVMCMD)),
+      TPI_NVMCMD_CHIP_ERASE,
+      /* write dummy value to start erase */
+      TPI_CMD_SST,
+      0xFF
+    };
 
     while (avr_tpi_poll_nvmbsy(pgm))
         ;
 
     err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
     if(err)
-	return err;
+      return err;
 
     while (avr_tpi_poll_nvmbsy(pgm));
 
@@ -97,56 +97,56 @@ int avr_tpi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
 
 /* TPI program enable sequence */
 int avr_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p, unsigned char guard_time) {
-	int err, retry;
-	unsigned char cmd[2];
-	unsigned char response;
+  int err, retry;
+  unsigned char cmd[2];
+  unsigned char response;
 
-	if(p->prog_modes & PM_TPI) {
-		/* set guard time */
-		cmd[0] = (TPI_CMD_SSTCS | TPI_REG_TPIPCR);
-		cmd[1] = guard_time;
+  if(p->prog_modes & PM_TPI) {
+    /* set guard time */
+    cmd[0] = (TPI_CMD_SSTCS | TPI_REG_TPIPCR);
+    cmd[1] = guard_time;
 
-		err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
+    err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
     if(err)
-			return err;
+      return err;
 
-		/* read TPI ident reg */
+    /* read TPI ident reg */
     cmd[0] = (TPI_CMD_SLDCS | TPI_REG_TPIIR);
-		err = pgm->cmd_tpi(pgm, cmd, 1, &response, sizeof(response));
+    err = pgm->cmd_tpi(pgm, cmd, 1, &response, sizeof(response));
     if (err || response != TPI_IDENT_CODE) {
       pmsg_error("TPIIR not correct\n");
       return -1;
     }
 
-		/* send SKEY command + SKEY */
-		err = pgm->cmd_tpi(pgm, tpi_skey_cmd, sizeof(tpi_skey_cmd), NULL, 0);
-		if(err)
-			return err;
+    /* send SKEY command + SKEY */
+    err = pgm->cmd_tpi(pgm, tpi_skey_cmd, sizeof(tpi_skey_cmd), NULL, 0);
+    if(err)
+      return err;
 
-		/* check if device is ready */
-		for(retry = 0; retry < 10; retry++)
-		{
-			cmd[0] =  (TPI_CMD_SLDCS | TPI_REG_TPISR);
-			err = pgm->cmd_tpi(pgm, cmd, 1, &response, sizeof(response));
-			if(err || !(response & TPI_REG_TPISR_NVMEN))
-				continue;
+    /* check if device is ready */
+    for(retry = 0; retry < 10; retry++)
+    {
+      cmd[0] =  (TPI_CMD_SLDCS | TPI_REG_TPISR);
+      err = pgm->cmd_tpi(pgm, cmd, 1, &response, sizeof(response));
+      if(err || !(response & TPI_REG_TPISR_NVMEN))
+        continue;
 
-			return 0;
-		}
+      return 0;
+    }
 
-		pmsg_error("target does not reply when enabling TPI external programming mode\n");
-		return -1;
+    pmsg_error("target does not reply when enabling TPI external programming mode\n");
+    return -1;
 
-	} else {
-		pmsg_error("part has no TPI\n");
-		return -1;
-	}
+  } else {
+    pmsg_error("part has no TPI\n");
+    return -1;
+  }
 }
 
 /* TPI: setup NVMCMD register and pointer register (PR) for read/write/erase */
 static int avr_tpi_setup_rw(const PROGRAMMER *pgm, const AVRMEM *mem,
-			    unsigned long addr, unsigned char nvmcmd)
-{
+  unsigned long addr, unsigned char nvmcmd) {
+
   unsigned char cmd[4];
   int rc;
 
@@ -444,9 +444,7 @@ int avr_read_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, con
   }
 
   for (i=0; i < mem->size; i++) {
-    if (vmem == NULL ||
-	(vmem->tags[i] & TAG_ALLOCATED) != 0)
-    {
+    if (vmem == NULL || (vmem->tags[i] & TAG_ALLOCATED) != 0) {
       rc = pgm->read_byte(pgm, p, mem, i, mem->buf + i);
       if (rc != LIBAVRDUDE_SUCCESS) {
         pmsg_error("unable to read byte at address 0x%04lx\n", i);
@@ -707,9 +705,7 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
       gettimeofday (&tv, NULL);
       start_time = (tv.tv_sec * 1000000) + tv.tv_usec;
       do {
-        /*
-         * Do polling, but timeout after max_write_delay.
-	 */
+        // Do polling, but timeout after max_write_delay
         rc = pgm->read_byte(pgm, p, mem, addr, &r);
         if (rc != 0) {
           pgm->pgm_led(pgm, OFF);