 + *
 + * We want to leverage the second half of this utility and distribute a new firmware package that's
 + * been copied into the upgrade partition, rather than via a USB/TFTP connection.
++ *
++ * Returns:
++ *    0 - An upgrade package was successfully installed
++ *   -1 - No upgrade package could be installed (either because of system error or because no package exists)
 + */
  
  int update_kubos(void)
  {
-@@ -75,9 +42,9 @@ int update_kubos(void)
+@@ -75,40 +47,42 @@ int update_kubos(void)
  	char * file;
  	char * env_addr;
  	loff_t actlen;

-		}
+			ret = update_tftp(addr, "mmc", "0");
 
+			if(ret)
+			{
+				error("System update failed - %d\n", ret);
+				return -1;
+			}
+		}
 	}
 
 	return 0;
diff --git a/include/configs/at91sam9g20isis.h b/include/configs/at91sam9g20isis.h
index 71a0aed..eb5fc40 100644
--- a/include/configs/at91sam9g20isis.h
+++ b/include/configs/at91sam9g20isis.h
@@ -76,6 +76,7 @@
 #define CONFIG_BLUE_LED     AT91_PIN_PC15   /* Unused */
 
 /* File updates */
+#define CONFIG_USB_FUNCTION_DFU
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE 500 * SZ_1K /* File transfer chunk size */
 #define CONFIG_SYS_DFU_MAX_FILE_SIZE 2 * SZ_1M   /* Maximum size for a single file.  Currently zImage (~1M) */
 #define CONFIG_UPDATE_KUBOS
@@ -136,10 +137,10 @@
 #endif
 
 /* EXT4 */
-/* #ifdef CONFIG_CMD_EXT4 */
+#ifdef CONFIG_CMD_EXT4
 #define CONFIG_EXT4
 #define CONFIG_EXT4_WRITE
-/* #endif */
+#endif
 
 /* USB */
 #define CONFIG_USB_ATMEL
@@ -199,6 +200,5 @@
 /*
  * Size of malloc() pool
  */
-/*#define CONFIG_SYS_MALLOC_LEN		ROUND(3 * CONFIG_ENV_SIZE + 128*1024, 0x1000)*/
 #define CONFIG_SYS_MALLOC_LEN 	 	10 * SZ_1M
 #endif
-- 
2.7.4


From 1a4334730eb7beaad74214bb395944800b2516a5 Mon Sep 17 00:00:00 2001
From: Catherine <catherine@kubos.co>
Date: Fri, 24 Feb 2017 10:58:19 -0600
Subject: [PATCH 03/10] Adding watchdog_force and extra calls to within i/o

---
 board/kubos/at91sam9g20isis/at91sam9g20isis.c | 48 +++++++++++++++++++++++++++
 drivers/mtd/cfi_flash.c                       |  7 ++++
 include/configs/at91sam9g20isis.h             |  4 +++
 include/watchdog.h                            |  1 +
 4 files changed, 60 insertions(+)

diff --git a/board/kubos/at91sam9g20isis/at91sam9g20isis.c b/board/kubos/at91sam9g20isis/at91sam9g20isis.c
index 9b7dfb8..f2683be 100644
--- a/board/kubos/at91sam9g20isis/at91sam9g20isis.c
+++ b/board/kubos/at91sam9g20isis/at91sam9g20isis.c
@@ -62,6 +62,10 @@ int board_init(void)
 
 	at91_seriald_hw_init();
 
+#if defined(CONFIG_HW_WATCHDOG)
+	hw_watchdog_init();
+#endif
+
 	return 0;
 }
 
@@ -87,3 +91,47 @@ int board_eth_init(bd_t *bis)
 #endif
 	return rc;
 }
+
+void hw_watchdog_init(void)
+{
+	/* Mark watchdog pin as output */
+	wdc = 0;
+	at91_set_pio_output(AT91_PIO_PORTA, 30, 1);
+
+	hw_watchdog_force();
+}
+
+static int wdc;
+
+void hw_watchdog_reset(void)
+{
+	int i = 0;
+
+	if((wdc % 100000) == 0)
+	{
+
+		for(i = 0; i < 10; i++)
+		{
+			at91_set_pio_value(AT91_PIO_PORTA, 30, 0);
+			at91_set_pio_value(AT91_PIO_PORTA, 30, 1);
+		}
+
+		wdc = 0;
+	}
+
+	wdc++;
+	return;
+}
+
+
+void hw_watchdog_force(void)
+{
+	wdc = 0;
+
+	printf("FWD\n");
+	hw_watchdog_reset();
+
+	return;
+}
+
+}
diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c
index 33c4a93..63fdb74 100644
--- a/drivers/mtd/cfi_flash.c
+++ b/drivers/mtd/cfi_flash.c
@@ -1392,6 +1392,13 @@ int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
 #else
 	while (cnt >= info->portwidth) {
 		cword.w32 = 0;
+
+		/* Kubos: Need to make sure to keep the watchdog alive during the write process */
+		if( cnt % 1000 == 0)
+		{
+			hw_watchdog_force();
+		}
+
 		for (i = 0; i < info->portwidth; i++) {
 			flash_add_byte (info, &cword, *src++);
 		}
diff --git a/include/configs/at91sam9g20isis.h b/include/configs/at91sam9g20isis.h
index eb5fc40..8c6a171 100644
--- a/include/configs/at91sam9g20isis.h
+++ b/include/configs/at91sam9g20isis.h
@@ -62,6 +62,9 @@
 #define CONFIG_AT91_GPIO
 #define CONFIG_AT91_GPIO_PULLUP	1	/* keep pullups on peripheral pins */
 
+/* external watchdog */
+#define CONFIG_HW_WATCHDOG
+
 /* serial console */
 #define CONFIG_ATMEL_USART
 #define CONFIG_USART_BASE		ATMEL_BASE_DBGU
@@ -77,6 +80,7 @@
 
 /* File updates */
 #define CONFIG_USB_FUNCTION_DFU
+#define CONFIG_DFU_MMC
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE 500 * SZ_1K /* File transfer chunk size */
 #define CONFIG_SYS_DFU_MAX_FILE_SIZE 2 * SZ_1M   /* Maximum size for a single file.  Currently zImage (~1M) */
 #define CONFIG_UPDATE_KUBOS
diff --git a/include/watchdog.h b/include/watchdog.h
index 174c894..2f2102b 100644
--- a/include/watchdog.h
+++ b/include/watchdog.h
@@ -41,6 +41,7 @@ int init_func_watchdog_reset(void);
 		#define WATCHDOG_RESET bl hw_watchdog_reset
 	#else
 		extern void hw_watchdog_reset(void);
+		extern void hw_watchdog_force(void);
 
 		#define WATCHDOG_RESET hw_watchdog_reset
 	#endif /* __ASSEMBLY__ */
-- 
2.7.4


From c188a2b14de3bceb8de173b561a809d2bec23636 Mon Sep 17 00:00:00 2001
From: Catherine <catherine@kubos.co>
Date: Fri, 24 Feb 2017 11:08:37 -0600
Subject: [PATCH 04/10] minor fix

---
 board/kubos/at91sam9g20isis/at91sam9g20isis.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/board/kubos/at91sam9g20isis/at91sam9g20isis.c b/board/kubos/at91sam9g20isis/at91sam9g20isis.c
index f2683be..6d3c731 100644
--- a/board/kubos/at91sam9g20isis/at91sam9g20isis.c
+++ b/board/kubos/at91sam9g20isis/at91sam9g20isis.c
@@ -92,6 +92,8 @@ int board_eth_init(bd_t *bis)
 	return rc;
 }
 
+static int wdc;
+
 void hw_watchdog_init(void)
 {
 	/* Mark watchdog pin as output */
@@ -101,8 +103,6 @@ void hw_watchdog_init(void)
 	hw_watchdog_force();
 }
 
-static int wdc;
-
 void hw_watchdog_reset(void)
 {
 	int i = 0;
@@ -128,10 +128,7 @@ void hw_watchdog_force(void)
 {
 	wdc = 0;
 
-	printf("FWD\n");
 	hw_watchdog_reset();
 
 	return;
 }
-
-}
-- 
2.7.4


From 10b59da627fc51351b8c603794c96492f5ef354b Mon Sep 17 00:00:00 2001
From: Catherine <catherine@kubos.co>
Date: Fri, 24 Feb 2017 14:37:15 -0600
Subject: [PATCH 05/10] Adding more wd kicks

---
 drivers/mmc/gen_atmel_mci.c | 6 ++++++
 fs/ext4/ext4fs.c            | 6 ++++++
 2 files changed, 12 insertions(+)

diff --git a/drivers/mmc/gen_atmel_mci.c b/drivers/mmc/gen_atmel_mci.c
index 20d4bdc..da08881 100644
--- a/drivers/mmc/gen_atmel_mci.c
+++ b/drivers/mmc/gen_atmel_mci.c
@@ -280,6 +280,12 @@ mci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 				block_count < data->blocks && !status;
 				block_count++) {
 			word_count = 0;
+
+			if (block_count % 1000 == 0)
+			{
+				hw_watchdog_force();
+			}
+
 			do {
 				status = mci_data_op(mci, ioptr, error_flags);
 				word_count++;
diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c
index 3078737..d7772b4 100644
--- a/fs/ext4/ext4fs.c
+++ b/fs/ext4/ext4fs.c
@@ -75,6 +75,12 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
 		int blockoff = pos - (blocksize * i);
 		int blockend = blocksize;
 		int skipfirst = 0;
+
+		if (i % 1000 == 0)
+		{
+			hw_watchdog_force();
+		}
+
 		blknr = read_allocated_block(&(node->inode), i);
 		if (blknr < 0)
 			return -1;
-- 
2.7.4


From 3f40db4d3c00c30449dbf0ecba1cb6b5e3d5375b Mon Sep 17 00:00:00 2001
From: Catherine <catherine@kubos.co>
Date: Fri, 24 Feb 2017 16:08:51 -0600
Subject: [PATCH 06/10] Adding more kicking and adding reboot after successful
 upgrade

---
 common/main.c         | 10 +++++++++-
 common/update_kubos.c |  9 +++++++++
 lib/crc32.c           |  7 +++++++
 lib/sha1.c            |  6 ++++++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/common/main.c b/common/main.c
index a45c2e7..adc1a79 100644
--- a/common/main.c
+++ b/common/main.c
@@ -60,7 +60,15 @@ void main_loop(void)
 #endif /* CONFIG_UPDATE_TFTP */
 
 #if defined(CONFIG_UPDATE_KUBOS)
-	update_kubos();
+	if(update_kubos() == 0)
+	{
+		/* 
+		 * If everything goes well, we want to reboot into the new
+		 * files.  The watchdog gets tripped if we try to boot the
+		 * new kernel from here, so we reboot instead.
+		 */
+		do_reset(NULL, 0, 0, NULL);
+	}
 #endif /* CONFIG_UPDATE_KUBOS */
 
 	s = bootdelay_process();
diff --git a/common/update_kubos.c b/common/update_kubos.c
index 3df9ea0..aaad614 100644
--- a/common/update_kubos.c
+++ b/common/update_kubos.c
@@ -139,6 +139,15 @@ int update_kubos(void)
 			}
 		}
 	}
+	else
+	{
+		debug("INFO: No upgrade file found\n");

 
 int ext4fs_symlinknest;
 struct ext_filesystem ext_fs;
@@ -75,6 +76,13 @@ int ext4fs_read_file(struct ext2fs_node *node, loff_t pos,
 		int blockoff = pos - (blocksize * i);
 		int blockend = blocksize;
 		int skipfirst = 0;
+
+#ifdef CONFIG_AT91SAM9G20ISIS
+		WATCHDOG_RESET_COUNT(1000);
+#else
+		WATCHDOG_RESET();
+#endif
+
 		blknr = read_allocated_block(&(node->inode), i);
 		if (blknr < 0)
 			return -1;
diff --git a/include/common.h b/include/common.h
index a8d833b..39739ce 100644
--- a/include/common.h
+++ b/include/common.h
@@ -95,6 +95,8 @@ typedef volatile unsigned char	vu_char;
 #define CONFIG_SYS_SUPPORT_64BIT_DATA
 #endif
 
+/*#define DEBUG 1*/
+
 #ifdef DEBUG
 #define _DEBUG	1
 #else
diff --git a/include/configs/at91sam9g20isis.h b/include/configs/at91sam9g20isis.h
index 71a0aed..4ba035c 100644
--- a/include/configs/at91sam9g20isis.h
+++ b/include/configs/at91sam9g20isis.h
@@ -62,6 +62,9 @@
 #define CONFIG_AT91_GPIO
 #define CONFIG_AT91_GPIO_PULLUP	1	/* keep pullups on peripheral pins */
 
+/* external watchdog */
+#define CONFIG_HW_WATCHDOG
+
 /* serial console */
 #define CONFIG_ATMEL_USART
 #define CONFIG_USART_BASE		ATMEL_BASE_DBGU
@@ -76,6 +79,8 @@
 #define CONFIG_BLUE_LED     AT91_PIN_PC15   /* Unused */
 
 /* File updates */
+#define CONFIG_USB_FUNCTION_DFU
+#define CONFIG_DFU_MMC
 #define CONFIG_SYS_DFU_DATA_BUF_SIZE 500 * SZ_1K /* File transfer chunk size */
 #define CONFIG_SYS_DFU_MAX_FILE_SIZE 2 * SZ_1M   /* Maximum size for a single file.  Currently zImage (~1M) */
 #define CONFIG_UPDATE_KUBOS
@@ -136,10 +141,10 @@
 #endif
 
 /* EXT4 */
-/* #ifdef CONFIG_CMD_EXT4 */
+#ifdef CONFIG_CMD_EXT4
 #define CONFIG_EXT4
 #define CONFIG_EXT4_WRITE
-/* #endif */
+#endif
 
 /* USB */
 #define CONFIG_USB_ATMEL
@@ -198,7 +203,9 @@
 
 /*
  * Size of malloc() pool
+ * Update: This size was increased to accommodate the DFU buffers. I'm not sure of the exact
+ * equation that would determine the optimum size.  Through trial and error I found that it
+ * should be more than 5MB, but less than 20MB.
  */
-/*#define CONFIG_SYS_MALLOC_LEN		ROUND(3 * CONFIG_ENV_SIZE + 128*1024, 0x1000)*/
 #define CONFIG_SYS_MALLOC_LEN 	 	10 * SZ_1M
 #endif
diff --git a/include/kubos.h b/include/kubos.h
new file mode 100644
index 0000000..6eeb552
--- /dev/null
+++ b/include/kubos.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 Kubos Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * update_kubos
+ *
+ * U-Boot has a DFU utility which currently allows a board to download a new firmware package and
+ * distribute the package components to the appropriate end-point locations.
+ *
+ * We want to leverage the second half of this utility and distribute a new firmware package that's
+ * been copied into the upgrade partition, rather than via a USB/TFTP connection.
+ *
+ * Returns:
+ *    0 - An upgrade package was successfully installed
+ *   -1 - No upgrade package could be installed (either because of system error or because no package exists)
+ */
+
+#ifndef __KUBOS_H__
+#define __KUBOS_H__
+
+#ifdef CONFIG_UPDATE_KUBOS
+int update_kubos(void);
+#endif
+
+#endif /* __KUBOS_H__ */
diff --git a/include/net.h b/include/net.h
index e8eee22..06320c6 100644
--- a/include/net.h
+++ b/include/net.h
@@ -844,8 +844,6 @@ unsigned int random_port(void);
  */
 int update_tftp(ulong addr, char *interface, char *devstring);
 
-int update_kubos(void);
-
 /**********************************************************************/
 
 #endif /* __NET_H__ */
diff --git a/include/watchdog.h b/include/watchdog.h
index 174c894..686ed4c 100644
--- a/include/watchdog.h
+++ b/include/watchdog.h
@@ -41,8 +41,15 @@ int init_func_watchdog_reset(void);
 		#define WATCHDOG_RESET bl hw_watchdog_reset
 	#else
 		extern void hw_watchdog_reset(void);
+		extern void hw_watchdog_force(void);
 
 		#define WATCHDOG_RESET hw_watchdog_reset
+
+        #ifdef CONFIG_AT91SAM9G20ISIS
+            extern void hw_watchdog_reset_count(int val);
+
+            #define WATCHDOG_RESET_COUNT hw_watchdog_reset_count
+        #endif
 	#endif /* __ASSEMBLY__ */
 #else
 	/*
diff --git a/lib/crc32.c b/lib/crc32.c
index 9759212..8993c5c 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -243,7 +243,11 @@ uint32_t ZEXPORT crc32_wd (uint32_t crc,
 			chunk = chunk_sz;
 		crc = crc32 (crc, curr, chunk);
 		curr += chunk;
+#ifdef CONFIG_AT91SAM9G20ISIS
+		WATCHDOG_RESET_COUNT(10);
+#else
 		WATCHDOG_RESET ();
+#endif
 	}
 #else
 	crc = crc32 (crc, buf, len);
diff --git a/lib/sha1.c b/lib/sha1.c
index 72c5dea..9f79509 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -328,7 +328,11 @@ void sha1_csum_wd(const unsigned char *input, unsigned int ilen,
 			chunk = chunk_sz;
 		sha1_update (&ctx, curr, chunk);
 		curr += chunk;
+#ifdef CONFIG_AT91SAM9G20ISIS
+		WATCHDOG_RESET_COUNT(5);
+#else
 		WATCHDOG_RESET ();
+#endif
 	}
 #else
 	sha1_update (&ctx, input, ilen);
diff --git a/tools/env/fw_env_main.c b/tools/env/fw_env_main.c
index 7a17b28..24b074e 100644
--- a/tools/env/fw_env_main.c
+++ b/tools/env/fw_env_main.c
@@ -237,7 +237,7 @@ int main(int argc, char *argv[])
 
 	lockfd = open(lockname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
 	if (-1 == lockfd) {
-		fprintf(stderr, "Error opening lock file %s\n", lockname);
+		fprintf(stderr, "Error opening lock file %s rc=%d\n", lockname, errno);
 		return EXIT_FAILURE;
 	}
 
-- 
2.7.4

