You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

194 lines
5.5 KiB

#!/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 <gareth@blacksphere.co.nz>
#
# 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 <http://www.gnu.org/licenses/>.
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 <http://gnu.org/licenses/gpl.html>")
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 <dev>] [-b <baudrate>] [-t <n>] <filename>" % argv[0])
print("\t-s : Use SW-DP instead of JTAG-DP")
print("\t-d : Use target on interface <dev> (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")