# HG changeset patch # User Windel Bouwman # Date 1357583401 -3600 # Node ID 90b03bc018cf9267667e135b81531f1801ed747d # Parent 92b2bf0da1ec4bde867cdf9d68baf22407a470b8 Added loader code from openocd diff -r 92b2bf0da1ec -r 90b03bc018cf python/st-flash.py --- a/python/st-flash.py Sun Jan 06 18:13:17 2013 +0100 +++ b/python/st-flash.py Mon Jan 07 19:30:01 2013 +0100 @@ -9,19 +9,24 @@ return int(s, 16) return int(s) -parser = argparse.ArgumentParser(description='ST-link flash utility') +parser = argparse.ArgumentParser( + description='ST-link flash utility by Windel Bouwman') subparsers = parser.add_subparsers(title='commands', description='possible commands', dest='command') readparser = subparsers.add_parser('read', help='read flash contents') -readparser.add_argument('filename', type=argparse.FileType(mode='wb')) +readparser.add_argument('filename', type=argparse.FileType('wb', 0)) readparser.add_argument('address', type=hex2int) readparser.add_argument('size', type=hex2int) writeparser = subparsers.add_parser('write', help='write flash contents') -writeparser.add_argument('filename', type=argparse.FileType(mode='rb')) +writeparser.add_argument('filename', type=argparse.FileType('rb')) writeparser.add_argument('address', type=hex2int) +verifyparser = subparsers.add_parser('verify', help='verify flash contents') +verifyparser.add_argument('filename', type=argparse.FileType('rb')) +verifyparser.add_argument('address', type=hex2int) + eraseparser = subparsers.add_parser('erase', help='erase flash contents') args = parser.parse_args() @@ -32,11 +37,7 @@ # In any command case, open a device: stl = stlink.STLink() -try: - stl.open() -except stlink.STLinkException as e: - print(e) - sys.exit(2) +stl.open() # Enter the right mode: if stl.CurrentMode == stlink.DFU_MODE: @@ -50,13 +51,16 @@ sys.exit(2) if args.command == 'read': - print('Reading!') + dev_content = stl.readFlash(args.address, args.size) + args.filename.write(dev_content) elif args.command == 'write': content = args.filename.read() - print('Write flash :)', len(content)) stl.writeFlash(args.address, content) +elif args.command == 'verify': + content = args.filename.read() + stl.verifyFlash(args.address, content) elif args.command == 'erase': - print('erase') + stl.eraseFlash() else: print('unknown command', args.command) diff -r 92b2bf0da1ec -r 90b03bc018cf python/stlink.py --- a/python/stlink.py Sun Jan 06 18:13:17 2013 +0100 +++ b/python/stlink.py Mon Jan 07 19:30:01 2013 +0100 @@ -24,6 +24,7 @@ DEBUG_EXIT = 0x21 DEBUG_ENTER_SWD = 0xa3 DEBUG_GETSTATUS = 0x01 +DEBUG_RESETSYS = 0x03 DEBUG_READREG = 0x5 DEBUG_WRITEREG = 0x6 DEBUG_READMEM_32BIT = 0x7 @@ -39,19 +40,44 @@ STM32_FLASH_BASE = 0x08000000 STM32_SRAM_BASE = 0x20000000 +FLASH_KEY1 = 0x45670123 +FLASH_KEY2 = 0xcdef89ab # flash registers: -FLASH_F4_REGS_ADDR = 0x400223c0 +FLASH_F4_REGS_ADDR = 0x40023c00 +FLASH_F4_KEYR = FLASH_F4_REGS_ADDR + +0x04 FLASH_F4_SR = FLASH_F4_REGS_ADDR + 0x0c FLASH_F4_CR = FLASH_F4_REGS_ADDR + 0x10 FLASH_F4_CR_START = 16 FLASH_F4_CR_LOCK = 31 FLASH_F4_CR_SER = 1 +FLASH_CR_MER = 2 FLASH_F4_CR_SNB = 3 FLASH_F4_CR_SNB_MASK = 0x38 FLASH_F4_SR_BSY = 16 +# flashloaders/stm32f4.s +loader_code_stm32f4 = bytes([ + 0x07, 0x4b, + + 0x62, 0xb1, + 0x04, 0x68, + 0x0c, 0x60, + + 0xdc, 0x89, + 0x14, 0xf0, 0x01, 0x0f, + 0xfb, 0xd1, + 0x00, 0xf1, 0x04, 0x00, + 0x01, 0xf1, 0x04, 0x01, + 0xa2, 0xf1, 0x01, 0x02, + 0xf1, 0xe7, + + 0x00, 0xbe, + + 0x00, 0x3c, 0x02, 0x40 +]) + def calculate_F4_sector(address): """ from 0x8000000 to 0x80FFFFF @@ -97,6 +123,13 @@ if self.devHandle.Configuration != 1: self.devHandle.Configuration = 1 self.devHandle.claimInterface(0) + + # First initialization: + if self.CurrentMode == DFU_MODE: + self.exitDfuMode() + if self.CurrentMode != DEBUG_MODE: + self.enterSwdMode() + self.reset() def close(self): pass @@ -157,6 +190,10 @@ cmd[0:2] = DEBUG_COMMAND, DEBUG_GETSTATUS reply = self.send_recv(cmd, 2) return reply[0] + def reset(self): + cmd = bytearray(16) + cmd[0:2] = DEBUG_COMMAND, DEBUG_RESETSYS + self.send_recv(cmd, 2) # debug commands: def step(self): @@ -196,8 +233,12 @@ self.eraseFlashSector(sector) # program pages: + self.initFlashLoader() + self.unlockFlashIf() # TODO + self.lockFlash() + # verfify program: self.verifyFlash(address, content) def eraseFlashSector(self, sector): @@ -207,33 +248,50 @@ self.setFlashCrStart() self.waitFlashBusy() self.lockFlash() + def eraseFlash(self): + self.waitFlashBusy() + self.unlockFlashIf() + self.setFlashCrMer() + self.setFlashCrStart() + self.waitFlashBusy() + self.clearFlashCrMer() + self.lockFlash() def verifyFlash(self, address, content): - print('verifying', address, len(content)) + device_content = self.readFlash(address, len(content)) + ok = content == device_content + print('Verify:', ok) + def readFlash(self, address, size): + print('reading', address, size) offset = 0 - cmp_size = 0x1800 + tmp_size = 0x1800 t1 = time.time() - while offset < len(content): + image = bytes() + while offset < size: # Correct for last page: - if offset + cmp_size > len(content): - cmp_size = len(content) - offset + if offset + tmp_size > size: + tmp_size = size - offset # align size to 4 bytes: - aligned_size = cmp_size + aligned_size = tmp_size while aligned_size % 4 != 0: aligned_size += 1 mem = self.read_mem32(address + offset, aligned_size) - ok = mem[:cmp_size] == content[offset:offset+cmp_size] + image += mem[:tmp_size] # indicate progress: - okc = '.' if ok else 'x' - print(okc, end='', flush=True) + print('.', end='', flush=True) # increase for next piece: - offset += cmp_size + offset += tmp_size t2 = time.time() - print('done! {0} bytes/second'.format(len(content)/(t2-t1))) - return content == mem + assert size == len(image) + print('done! {0} bytes/second'.format(size/(t2-t1))) + return image + def initFlashLoader(self): + # TODO: support other loader code. + self.write_mem32(STM32_SRAM_BASE, loader_code_stm32f4) + self.bufAddress = STM32_SRAM_BASE + len(loader_code_stm32f4) def readFlashSr(self): return self.read_debug32(FLASH_F4_SR) def readFlashCr(self): @@ -244,6 +302,14 @@ x |= sector << FLASH_F4_CR_SNB x |= 1 << FLASH_F4_CR_SER self.write_debug32(FLASH_F4_CR, x) + def setFlashCrMer(self): + x = self.readFlashCr() + x |= 1 << FLASH_CR_MER + self.write_debug32(FLASH_F4_CR, x) + def clearFlashCrMer(self): + x = self.readFlashCr() + x &= ~(1 << FLASH_CR_MER) + self.write_debug32(FLASH_F4_CR, x) def setFlashCrStart(self): x = self.readFlashCr() x |= 1 << FLASH_F4_CR_START @@ -262,14 +328,15 @@ return cr & mask == mask def unlockFlashIf(self): if self.isFlashLocked(): + print('unlocking') self.write_debug32(FLASH_F4_KEYR, FLASH_KEY1) self.write_debug32(FLASH_F4_KEYR, FLASH_KEY2) if self.isFlashLocked(): raise STLinkException('Failed to unlock') - def lockFlash(self): - # TODO - pass + print('locking') + x = self.readFlashCr() | (1 << FLASH_F4_CR_LOCK) + self.write_debug32(FLASH_F4_CR, x) # Helper 1 functions: def write_debug32(self, address, value): @@ -294,6 +361,14 @@ cmd[0:3] = DEBUG_COMMAND, DEBUG_READREG, reg reply = self.send_recv(cmd, 4) return struct.unpack(' 0: return self.devHandle.bulkRead(1, rxsize) # read from endpoint 1 @@ -339,9 +414,9 @@ # test registers: sl.write_reg(3, 0x1337) - sl.write_reg(1, 0x1332) + sl.write_reg(2, 0x1332) assert sl.read_reg(3) == 0x1337 - assert sl.read_reg(1) == 0x1332 + assert sl.read_reg(2) == 0x1332 sl.exitDebugMode() print('mode at end:', sl.CurrentModeString)