#!/usr/bin/env python3 # hexprog.py: Python application to flash a target with an Intel hex file # Copyright (C) 2011 Black Sphere Technologies # Written by Gareth McMullin # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import gdb import time # Microcode sequence to erase option bytes stub_opterase = '\nH\x0bIA`\x0bIA`\tI\x81`\tI\x81`\x01iA\xf0 \x01\x01aA\xf0@\x01\x01a\xc4hO\xf0\x01\x064B\xfa\xd1\x00\xbe\x00 \x02@#\x01gE\xab\x89\xef\xcd' # Microcode sequence to program option bytes stub_optprog = '\tJ\nKS`\nKS`\x08K\x93`\x08K\x93`\x13iC\xf0\x10\x03\x13a\x01\x80\xd4hO\xf0\x01\x064B\xfa\xd1\x00\xbe\x00 \x02@#\x01gE\xab\x89\xef\xcd' def flash_write_hex(target, hexfile, progress_cb=None): target.flash_probe() f = open(hexfile) addrhi = 0 for line in f: if line[0] != ':': raise Exception("Error in hex file") reclen = int(line[1:3], 16) addrlo = int(line[3:7], 16) rectype = int(line[7:9], 16) if sum(x for x in bytes.fromhex(line[1:11+reclen*2])) & 0xff != 0: raise Exception("Checksum error in hex file") if rectype == 0: # Data record addr = (addrhi << 16) + addrlo data = bytes.fromhex(line[9:9+reclen*2]) target.flash_write_prepare(addr, data) pass elif rectype == 4: # High address record addrhi = int(line[9:13], 16) pass elif rectype == 5: # Entry record pass elif rectype == 1: # End of file record break else: raise Exception("Invalid record in hex file") try: target.flash_commit(progress_cb) except: print("Flash write failed! Is device protected?\n") exit(-1) if __name__ == "__main__": from serial import Serial, SerialException from sys import argv, platform, stdout from getopt import getopt if platform == "linux": print("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen print("Black Magic Probe -- Target Production Programming Tool -- version 1.0") print("Copyright (C) 2011 Black Sphere Technologies") print("License GPLv3+: GNU GPL version 3 or later ") print("") dev = "COM1" if platform == "win32" else "/dev/ttyACM0" baud = 115200 scan = "jtag_scan" targetno = 1 unprot = False; prot = False try: opts, args = getopt(argv[1:], "sd:b:t:rR") for opt in opts: if opt[0] == "-s": scan = "swdp_scan" elif opt[0] == "-b": baud = int(opt[1]) elif opt[0] == "-d": dev = opt[1] elif opt[0] == "-t": targetno = int(opt[1]) elif opt[0] == "-r": unprot = True elif opt[0] == "-R": prot = True else: raise Exception() hexfile = args[0] except: print("Usage %s [-s] [-d ] [-b ] [-t ] " % argv[0]) print("\t-s : Use SW-DP instead of JTAG-DP") print("\t-d : Use target on interface (default: %s)" % dev) print("\t-b : Set device baudrate (default: %d)" % baud) print("\t-t : Connect to target #n (default: %d)" % targetno) print("\t-r : Clear flash read protection before programming") print("\t-R : Enable flash read protection after programming (requires power-on reset)") print("") exit(-1) try: s = Serial(dev) #, baud, timeout=0.1) #s.setDTR(1) #s.flushInput() #while s.read(1024): # pass target = gdb.Target(s) except SerialException as e: print("FATAL: Failed to open serial device!\n%s\n" % e[0]) exit(-1) try: r = target.monitor("version") for s in r: print(s.decode(), end=' ') except SerialException as e: print("FATAL: Serial communication failure!\n%s\n" % e[0]) exit(-1) #except: pass print("Target device scan:") targetlist = None r = target.monitor(scan) for s in r: print(s.decode(), end=' ') print() r = target.monitor("targets") for s in r: if s.startswith(b"No. Att Driver"): targetlist = [] try: if type(targetlist) is list: targetlist.append(int(s[:2])) except: pass #if not targetlist: # print("FATAL: No usable targets found!\n") # exit(-1) if targetlist and (targetno not in targetlist): print("WARNING: Selected target %d not available, using %d" % (targetno, targetlist[0])) targetno = targetlist[0] print("Attaching to target %d." % targetno) target.attach(targetno) time.sleep(0.1) if unprot: print("Removing device protection.") # Save option bytes for later #optbytes = struct.unpack("8H", target.read_mem(0x1FFFF800, 16)) # Remove protection target.run_stub(stub_opterase, 0x20000000) target.run_stub(stub_optprog, 0x20000000, 0x1FFFF800, 0x5aa5) target.reset() time.sleep(0.1) for m in target.flash_probe(): print("FLASH memory -- Offset: 0x%X BlockSize:0x%X\n" % (m.offset, m.blocksize)) def progress(percent): print("Progress: %d%%\r" % percent, end=' ') stdout.flush() print("Programming target") flash_write_hex(target, hexfile, progress) print("Resetting target") target.reset() if prot: print("Enabling device protection.") target.run_stub(stub_opterase, 0x20000000) target.run_stub(stub_optprog, 0x20000000, 0x1FFFF800, 0x00ff) target.reset() target.detach() print("\nAll operations complete!\n")