Added checksumming to bootloader
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Sun, 9 Jul 2017 00:45:48 +0000 (17:45 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Sun, 9 Jul 2017 00:45:48 +0000 (17:45 -0700)
avr/src/boot/boot.c
avr/src/boot/boot.h
scripts/avr109-flash.py

index 885ef7462483b537e5460ae4ff3659aa605f4442..a0ac310e1704876dc72705521d3f5d1933931a32 100644 (file)
@@ -258,17 +258,15 @@ int main() {
       break;
     }
 
-    case CMD_CHIP_ERASE:
-      // Erase the application section
+    case CMD_FLASH_ERASE:
       SP_EraseApplicationSection();
-
-      // Wait for completion
       nvm_wait();
+      send_char(REPLY_ACK);
+      break;
 
-      // Erase EEPROM
+    case CMD_EEPROM_ERASE:
       NVM.CMD = NVM_CMD_ERASE_EEPROM_gc;
       nvm_exec();
-
       send_char(REPLY_ACK);
       break;
 
@@ -371,7 +369,7 @@ int main() {
 
     case CMD_VERSION:
       send_char('0');
-      send_char('1');
+      send_char('2');
       break;
 
     case CMD_READ_SIGNATURE:
@@ -380,6 +378,48 @@ int main() {
       send_char(SIGNATURE_0);
       break;
 
+    case CMD_READ_CHECKSUM:
+      // Setup
+      nvm_wait();
+
+      // Reset CRC
+      CRC_CTRL |= CRC_RESET_RESET1_gc;
+      CRC.CHECKSUM0 = CRC.CHECKSUM1 = CRC.CHECKSUM2 = CRC.CHECKSUM3 = 0xff;
+
+      // 32-bit mode, flash source
+      CRC_CTRL = CRC_CRC32_bm | CRC_SOURCE_FLASH_gc;
+
+      // Start address
+      NVM.ADDR0 = (uint8_t)(APP_SECTION_START >> 0);
+      NVM.ADDR1 = (uint8_t)(APP_SECTION_START >> 8);
+      NVM.ADDR2 = 0;
+
+      // End address
+      NVM.DATA0 = (uint8_t)(APP_SECTION_END >> 0);
+      NVM.DATA1 = (uint8_t)(APP_SECTION_END >> 8);
+      NVM.DATA2 = (uint8_t)(APP_SECTION_END >> 16);
+
+      NVM.CMD = NVM_CMD_FLASH_RANGE_CRC_gc;
+      CCP = CCP_IOREG_gc;
+      NVM.CTRLA = NVM_CMDEX_bm;
+
+      // Compute
+      nvm_wait();
+      while (CRC.STATUS & CRC_BUSY_bm) continue;
+
+      // Send 32-bit checksum
+      send_char(CRC.CHECKSUM3);
+      send_char(CRC.CHECKSUM2);
+      send_char(CRC.CHECKSUM1);
+      send_char(CRC.CHECKSUM0);
+      break;
+
+    case CMD_FLASH_LENGTH:
+      send_char((uint8_t)(APP_SECTION_SIZE >> 16));
+      send_char((uint8_t)(APP_SECTION_SIZE >> 8));
+      send_char((uint8_t)(APP_SECTION_SIZE >> 0));
+      break;
+
     case CMD_BLOCK_CRC:
       send_char(block_crc >> 8);
       send_char((uint8_t)block_crc);
index b966c1ddc99002f46e2ce84bc642305866943930..2af4be1c8ed50d240a138587da7a49e65258bf8f 100644 (file)
@@ -53,13 +53,16 @@ enum {
   CMD_VERSION             = 'V',
   CMD_HW_VERSION          = 'v', // Unsupported extension
   CMD_READ_SIGNATURE      = 's',
+  CMD_READ_CHECKSUM       = 'X',
+  CMD_FLASH_LENGTH        = 'n',
 
   // Addressing
   CMD_SET_ADDRESS         = 'A',
   CMD_SET_EXT_ADDRESS     = 'H',
 
   // Erase
-  CMD_CHIP_ERASE          = 'e',
+  CMD_FLASH_ERASE         = 'e',
+  CMD_EEPROM_ERASE        = '_',
 
   // Block Access
   CMD_BLOCK_LOAD          = 'B',
index 87b919d0d14b1ec0362035ec0fbc228fad2df497..111d812b485b66e7d1c6b7722a55f8e3d1d2f0d8 100755 (executable)
@@ -25,6 +25,17 @@ def crc16(data):
     return crc
 
 
+def avr_crc32(data, length):
+    mem = [0xff] * length
+
+    for addr, chunk in data:
+        for x in chunk:
+            mem[addr] = x
+            addr += 1
+
+    return binascii.crc32(bytes(mem))
+
+
 def read_intel_hex(f):
     base = 0
     pos = 0
@@ -82,7 +93,7 @@ def recv_int(size):
 
 
 # Read firmware hex file
-data = read_intel_hex(open(sys.argv[1], 'r'))
+data = list(read_intel_hex(open(sys.argv[1], 'r')))
 
 # Open serial  port
 sp = serial.Serial(dev, baud, timeout = 10)
@@ -105,12 +116,39 @@ send('S')
 if boot_id != recv(len(boot_id)):
     raise Exception('Failed to communicate with bootloader')
 
+# Get version
+send('V')
+major = int(recv(1))
+minor = int(recv(1))
+print('Bootloader version: %d.%d' % (major, minor))
+
+# If bootloader is new enough compare checksums
+if 0 < major or 1 < minor:
+    # Get flash length
+    send('n')
+    flash_len = recv_int(3)
+
+    # Get current flash CRC
+    send('X')
+    new_crc = avr_crc32(data, flash_len)
+    old_crc = recv_int(4)
+    if old_crc == new_crc:
+        print('Flash already up to date')
+        sys.exit(0)
+
+    print('CRC: old=0x%08x new=0x%08x' % (old_crc, new_crc))
+
+    # Erase
+    send('e')
+    if recv(1) != '\r': raise Exception('Flash erase failed')
+
 # Get page size
 send('b')
 if recv(1) != 'Y': raise Exception('Cannot get page size')
 page_size = recv_int(2)
 print('Page size:', page_size)
 
+
 # Program
 print('Programming', end = '')
 count = 0