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;
case CMD_VERSION:
send_char('0');
- send_char('1');
+ send_char('2');
break;
case CMD_READ_SIGNATURE:
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);
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',
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
# 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)
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