Merge commit 'd594b42976e3b9640b64ef1cb2da3f74067930b8' into sam-update

# Conflicts:
#	README.md
#	src/platforms/common/cdcacm.c
#	src/target/adiv5_swdp.c
This commit is contained in:
Jason Kotzin 2022-08-10 20:39:54 -07:00
commit e174c5b503
17 changed files with 417 additions and 282 deletions

View File

@ -1 +1 @@
See https://github.com/blacksphere/blackmagic/wiki/Hacking See https://github.com/blackmagic-debug/blackmagic/wiki/Hacking

View File

@ -23,12 +23,12 @@ from time import sleep
class stm32_boot: class stm32_boot:
def __init__(self, port, baud=115200): def __init__(self, port, baud=115200):
self.serial = serial.Serial(port, baud, 8, 'E', 1, self.serial = serial.Serial(port, baud, 8, 'E', 1,
timeout=1) timeout=1)
# Turn on target device in SystemMemory boot mode # Turn on target device in SystemMemory boot mode
self.serial.setDTR(1) self.serial.setDTR(1)
sleep(0.1); sleep(0.1)
self._sync() self._sync()
@ -98,7 +98,6 @@ class stm32_boot:
# Send data # Send data
self._send(chr(len(data)-1) + data) self._send(chr(len(data)-1) + data)
self._checkack() self._checkack()
def write_protect(self, sectors): def write_protect(self, sectors):
# Send WP cmd # Send WP cmd
@ -134,11 +133,11 @@ if __name__ == "__main__":
from getopt import getopt from getopt import getopt
if platform == "linux2": if platform == "linux2":
print "\x1b\x5b\x48\x1b\x5b\x32\x4a" # clear terminal screen print("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
print "STM32 SystemMemory Production Programmer -- version 1.1" print("STM32 SystemMemory Production Programmer -- version 1.1")
print "Copyright (C) 2011 Black Sphere Technologies" print("Copyright (C) 2011 Black Sphere Technologies")
print "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>" print("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>")
print print()
dev = "COM1" if platform == "win32" else "/dev/ttyUSB0" dev = "COM1" if platform == "win32" else "/dev/ttyUSB0"
baud = 115200 baud = 115200
@ -152,38 +151,38 @@ if __name__ == "__main__":
progfile = args[0] progfile = args[0]
except: except:
print "Usage %s [-d <dev>] [-b <baudrate>] [-a <address>] <filename>" % argv[0] print("Usage %s [-d <dev>] [-b <baudrate>] [-a <address>] <filename>" % argv[0])
print "\t-d : Use target on interface <dev> (default: %s)" % dev print("\t-d : Use target on interface <dev> (default: %s)" % dev)
print "\t-b : Set device baudrate (default: %d)" % baud print("\t-b : Set device baudrate (default: %d)" % baud)
print "\t-a : Set programming address (default: 0x%X)" % addr print("\t-a : Set programming address (default: 0x%X)" % addr)
print print()
exit(-1) exit(-1)
prog = open(progfile, "rb").read() prog = open(progfile, "rb").read()
boot = stm32_boot(dev, baud) boot = stm32_boot(dev, baud)
cmds = boot.get() cmds = boot.get()
print "Target bootloader version: %d.%d\n" % (ord(cmds[0]) >> 4, ord(cmds[0]) % 0xf) print("Target bootloader version: %d.%d\n" % (ord(cmds[0]) >> 4, ord(cmds[0]) % 0xf))
print "Removing device protection..." print("Removing device protection...")
boot.read_unprotect() boot.read_unprotect()
boot.write_unprotect() boot.write_unprotect()
print "Erasing target device..." print("Erasing target device...")
boot.eraseall() boot.eraseall()
addr = 0x8000000 addr = 0x8000000
while prog: while prog:
print ("Programming address 0x%08X..0x%08X...\r" % (addr, addr + min(len(prog), 255))), print("Programming address 0x%08X..0x%08X...\r" % (addr, addr + min(len(prog), 255)), end=' ')
stdout.flush(); stdout.flush()
boot.write(addr, prog[:256]) boot.write(addr, prog[:256])
addr += 256 addr += 256
prog = prog[256:] prog = prog[256:]
print print
print "Enabling device protection..." print("Enabling device protection...")
boot.write_protect(range(0,2)) boot.write_protect(range(0,2))
#boot.read_protect() #boot.read_protect()
print "All operations completed." print("All operations completed.")
print print

View File

@ -3,7 +3,7 @@
# gdb.py: Python module for low level GDB protocol implementation # gdb.py: Python module for low level GDB protocol implementation
# Copyright (C) 2009 Black Sphere Technologies # Copyright (C) 2009 Black Sphere Technologies
# Written by Gareth McMullin <gareth@blacksphere.co.nz> # Written by Gareth McMullin <gareth@blacksphere.co.nz>
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
@ -24,24 +24,18 @@ import struct
import time import time
def hexify(s): def hexify(s):
"""Convert a binary string into hex representation""" """Convert a bytes object into hex bytes representation"""
ret = '' return s.hex().encode()
for c in s:
ret += "%02X" % ord(c)
return ret
def unhexify(s): def unhexify(s):
"""Convert a hex string into binary representation""" """Convert a hex-encoded bytes into bytes object"""
ret = '' return bytes.fromhex(s.decode())
for i in range(0, len(s), 2):
ret += chr(int(s[i:i+2], 16))
return ret
class FakeSocket: class FakeSocket:
"""Emulate socket functions send and recv on a file object""" """Emulate socket functions send and recv on a file object"""
def __init__(self, file): def __init__(self, file):
self.file = file self.file = file
def send(self, data): def send(self, data):
self.file.write(data) self.file.write(data)
@ -52,148 +46,186 @@ class Target:
def __init__(self, sock): def __init__(self, sock):
if "send" in dir(sock): if "send" in dir(sock):
self.sock = sock self.sock = sock
else: else:
self.sock = FakeSocket(sock) self.sock = FakeSocket(sock)
self.PacketSize=0x100 # default
def getpacket(self): def getpacket(self):
"""Return the first correctly received packet from GDB target""" """Return the first correctly received packet from GDB target"""
while True: while True:
while self.sock.recv(1) != '$': pass while self.sock.recv(1) != b'$':
pass
csum = 0 csum = 0
packet = '' packet = [] # list-of-small-int
while True: while True:
c = self.sock.recv(1) c, = self.sock.recv(1)
if c == '#': break if c == ord('#'):
break
if c == '$': if c == ord('$'):
packet = '' packet = []
csum = 0 csum = 0
continue continue
if c == '}': if c == ord('}'):
c = self.sock.recv(1) c, = self.sock.recv(1)
csum += ord(c) + ord('}') csum += c + ord('}')
packet += chr(ord(c) ^ 0x20) packet.append(c ^ 0x20)
continue continue
packet += c packet.append(c)
csum += ord(c) csum += c
if (csum & 0xFF) == int(self.sock.recv(2),16): break if (csum & 0xFF) == int(self.sock.recv(2),16):
break
self.sock.send('-') self.sock.send(b'-')
self.sock.send('+')
return packet
self.sock.send(b'+')
return bytes(packet)
def putpacket(self, packet): def putpacket(self, packet):
"""Send packet to GDB target and wait for acknowledge""" """Send packet to GDB target and wait for acknowledge
packet is bytes or string"""
if type(packet) == str:
packet = packet.encode()
while True: while True:
self.sock.send('$') out = []
csum = 0
for c in packet: for c in packet:
if (c == '$') or (c == '#') or (c == '}'): if (c in b'$#}'):
self.sock.send('}') out.append(ord('}'))
self.sock.send(chr(ord(c) ^ 0x20)) out.append(c ^ 0x20)
csum += (ord(c) ^ 0x20) + ord('}')
else: else:
self.sock.send(c) out.append(c)
csum += ord(c)
self.sock.send('#') csum = sum(out)
self.sock.send("%02X" % (csum & 0xFF)) outb = b'$'+bytes(out)+b'#%02X' % (csum & 0xff)
if self.sock.recv(1) == '+': break
self.sock.send(outb)
if self.sock.recv(1) == b'+':
break
def monitor(self, cmd): def monitor(self, cmd):
"""Send gdb "monitor" command to target""" """Send gdb "monitor" command to target"""
if type(cmd) == str:
cmd = cmd.encode()
ret = [] ret = []
self.putpacket("qRcmd," + hexify(cmd)) self.putpacket(b"qRcmd," + hexify(cmd))
while True: while True:
s = self.getpacket() s = self.getpacket()
if s == '': return None
if s == 'OK': return ret if s == b'':
if s.startswith('O'): ret.append(unhexify(s[1:])) return None
if s == b'OK':
return ret
if s.startswith(b'O'):
ret.append(unhexify(s[1:]))
else: else:
raise Exception('Invalid GDB stub response') raise Exception('Invalid GDB stub response %r'%s.decode())
def attach(self, pid): def attach(self, pid):
"""Attach to target process (gdb "attach" command)""" """Attach to target process (gdb "attach" command)"""
self.putpacket("vAttach;%08X" % pid) self.putpacket(b"vAttach;%08X" % pid)
reply = self.getpacket() reply = self.getpacket()
if (len(reply) == 0) or (reply[0] == 'E'): if (reply == b'') or (reply[:1] == b'E'):
raise Exception('Failed to attach to remote pid %d' % pid) raise Exception('Failed to attach to remote pid %d' % pid)
def detach(self): def detach(self):
"""Detach from target process (gdb "detach" command)""" """Detach from target process (gdb "detach" command)"""
self.putpacket("D") self.putpacket(b"D")
if self.getpacket() != 'OK': if self.getpacket() != b'OK':
raise Exception("Failed to detach from remote process") raise Exception("Failed to detach from remote process")
def reset(self): def reset(self):
"""Reset the target system""" """Reset the target system"""
self.putpacket("r") self.putpacket(b"r")
def read_mem(self, addr, length): def read_mem(self, addr, length):
"""Read length bytes from target at address addr""" """Read length bytes from target at address addr"""
self.putpacket("m%08X,%08X" % (addr, length)) ret = b''
reply = self.getpacket() while length:
if (len(reply) == 0) or (reply[0] == 'E'): # print "Read"
raise Exception('Error reading memory at 0x%08X' % addr) packlen = min(length,self.PacketSize//2)
try: self.putpacket(b"m%08X,%08X" % (addr, packlen))
data = unhexify(reply) reply = self.getpacket()
except Excpetion: if (reply == b'') or (reply[:1] == b'E'):
raise Exception('Invalid response to memory read packet: %r' % reply) raise Exception('Error reading memory at 0x%08X' % addr)
return data try:
data = unhexify(reply)
except Exception:
raise Exception('Invalid response to memory read packet: %r' % reply)
ret += data
length -= packlen
addr += packlen
return ret
def write_mem(self, addr, data): def write_mem(self, addr, data):
"""Write data to target at address addr""" """Write data to target at address addr"""
self.putpacket("X%08X,%08X:%s" % (addr, len(data), data)) data = bytes(data)
if self.getpacket() != 'OK':
raise Exception('Error writing to memory at 0x%08X' % addr) while data:
d = data[:self.PacketSize-44]
data = data[len(d):]
#print("Writing %d bytes at 0x%X" % (len(d), addr))
pack = b"X%08X,%08X:%s" % (addr, len(d), d)
self.putpacket(pack)
if self.getpacket() != b'OK':
raise Exception('Error writing to memory at 0x%08X' % addr)
addr += len(d)
def read_regs(self): def read_regs(self):
"""Read target core registers""" """Read target core registers"""
self.putpacket("g") self.putpacket(b"g")
reply = self.getpacket() reply = self.getpacket()
if (len(reply) == 0) or (reply[0] == 'E'): if (reply == b'') or (reply[:1] == b'E'):
raise Exception('Error reading memory at 0x%08X' % addr) raise Exception('Error reading memory at 0x%08X' % addr)
try: try:
data = unhexify(reply) data = unhexify(reply)
except Excpetion: except Exception:
raise Exception('Invalid response to memory read packet: %r' % reply) raise Exception('Invalid response to memory read packet: %r' % reply)
return struct.unpack("=20L", data) ret = array.array('I',data)
return ret
def write_regs(self, *regs): def write_regs(self, *regs):
"""Write target core registers""" """Write target core registers"""
data = struct.pack("=%dL" % len(regs), *regs) data = struct.pack("=%dL" % len(regs), *regs)
self.putpacket("G" + hexify(data)) self.putpacket(b"G" + hexify(data))
if self.getpacket() != 'OK': if self.getpacket() != b'OK':
raise Exception('Error writing to target core registers') raise Exception('Error writing to target core registers')
def memmap_read(self): def memmap_read(self):
"""Read the XML memory map from target""" """Read the XML memory map from target"""
offset = 0 offset = 0
ret = '' ret = b''
while True: while True:
self.putpacket("qXfer:memory-map:read::%08X,%08X" % (offset, 512)) self.putpacket(b"qXfer:memory-map:read::%08X,%08X" % (offset, 512))
reply = self.getpacket() reply = self.getpacket()
if (reply[0] == 'm') or (reply[0] == 'l'): if (reply[0] in b'ml'):
offset += len(reply) - 1 offset += len(reply) - 1
ret += reply[1:] ret += reply[1:]
else: else:
raise Exception("Invalid GDB stub response") raise Exception('Invalid GDB stub response %r'%reply)
if reply[:1] == b'l':
return ret
if reply[0] == 'l': return ret
def resume(self): def resume(self):
"""Resume target execution""" """Resume target execution"""
self.putpacket("c") self.putpacket(b'c')
def interrupt(self): def interrupt(self):
"""Interrupt target execution""" """Interrupt target execution"""
self.sock.send("\x03") self.sock.send(b'\x03')
def run_stub(self, stub, address, *args): def run_stub(self, stub, address, *args):
"""Execute a binary stub at address, passing args in core registers.""" """Execute a binary stub at address, passing args in core registers."""
@ -205,11 +237,19 @@ class Target:
regs[15] = address regs[15] = address
self.write_regs(*regs) self.write_regs(*regs)
self.resume() self.resume()
reply = self.getpacket() reply = None
while not reply: while not reply:
reply = self.getpacket() reply = self.getpacket()
if not reply.startswith("T05"): if not reply.startswith(b"T05"):
raise Exception("Invalid stop response: %r" % reply) message = "Invalid stop response: %r" % reply
try:
message += {'T02':' (SIGINT)',
'T05':' (SIGTRAP)',
'T0B':' (SIGSEGV)',
'T1D':' (SIGLOST)'}[reply]
except KeyError:
pass
raise Exception(message)
class FlashMemory: class FlashMemory:
def __init__(self, target, offset, length, blocksize): def __init__(self, target, offset, length, blocksize):
@ -217,27 +257,30 @@ class Target:
self.offset = offset self.offset = offset
self.length = length self.length = length
self.blocksize = blocksize self.blocksize = blocksize
self.blocks = list(None for i in range(length / blocksize)) self.blocks = list(None for i in range(length // blocksize))
def prog(self, offset, data): def prog(self, offset, data):
assert ((offset >= self.offset) and assert type(data)==bytes
assert ((offset >= self.offset) and
(offset + len(data) <= self.offset + self.length)) (offset + len(data) <= self.offset + self.length))
while data: while data:
index = (offset - self.offset) / self.blocksize index = (offset - self.offset) // self.blocksize
bloffset = (offset - self.offset) % self.blocksize bloffset = (offset - self.offset) % self.blocksize
bldata = data[:self.blocksize-bloffset] bldata = data[:self.blocksize-bloffset]
data = data[len(bldata):]; offset += len(bldata) data = data[len(bldata):]; offset += len(bldata)
if self.blocks[index] is None: # Initialize a clear block if self.blocks[index] is None: # Initialize a clear block
self.blocks[index] = "".join(chr(0xff) for i in range(self.blocksize)) self.blocks[index] = bytes(0xff for i in range(self.blocksize))
self.blocks[index] = (self.blocks[index][:bloffset] + bldata + self.blocks[index] = (self.blocks[index][:bloffset] + bldata +
self.blocks[index][bloffset+len(bldata):]) self.blocks[index][bloffset+len(bldata):])
def commit(self, progress_cb=None): def commit(self, progress_cb=None):
totalblocks = 0 totalblocks = 0
for b in self.blocks: for b in self.blocks:
if b is not None: totalblocks += 1 if b is not None:
totalblocks += 1
block = 0 block = 0
for i in range(len(self.blocks)): for i in range(len(self.blocks)):
block += 1 block += 1
@ -247,35 +290,37 @@ class Target:
# Erase the block # Erase the block
data = self.blocks[i] data = self.blocks[i]
addr = self.offset + self.blocksize * i addr = self.offset + self.blocksize * i
if data is None: continue if data is None:
continue
#print "Erasing flash at 0x%X" % (self.offset + self.blocksize*i) #print "Erasing flash at 0x%X" % (self.offset + self.blocksize*i)
self.target.putpacket("vFlashErase:%08X,%08X" % self.target.putpacket(b"vFlashErase:%08X,%08X" %
(self.offset + self.blocksize*i, self.blocksize)) (self.offset + self.blocksize*i, self.blocksize))
if self.target.getpacket() != 'OK': if self.target.getpacket() != b'OK':
raise Exception("Failed to erase flash") raise Exception("Failed to erase flash")
while data: while data:
d = data[0:980] d = data[0:980]
data = data[len(d):] data = data[len(d):]
#print "Writing %d bytes at 0x%X" % (len(d), addr) #print "Writing %d bytes at 0x%X" % (len(d), addr)
self.target.putpacket("vFlashWrite:%08X:%s" % (addr, d)) self.target.putpacket(b"vFlashWrite:%08X:%s" % (addr, d))
addr += len(d) addr += len(d)
if self.target.getpacket() != 'OK': if self.target.getpacket() != b'OK':
raise Exception("Failed to write flash") raise Exception("Failed to write flash")
self.target.putpacket("vFlashDone") self.target.putpacket(b"vFlashDone")
if self.target.getpacket() != 'OK': if self.target.getpacket() != b'OK':
raise Exception("Failed to commit") raise Exception("Failed to commit")
self.blocks = list(None for i in range(self.length / self.blocksize)) self.blocks = list(None for i in range(self.length // self.blocksize))
def flash_probe(self): def flash_probe(self):
self.mem = [] self.mem = []
xmldom = parseString(self.memmap_read()) xmldom = parseString(self.memmap_read())
for memrange in xmldom.getElementsByTagName("memory"): for memrange in xmldom.getElementsByTagName("memory"):
if memrange.getAttribute("type") != "flash": continue if memrange.getAttribute("type") != "flash":
continue
offset = eval(memrange.getAttribute("start")) offset = eval(memrange.getAttribute("start"))
length = eval(memrange.getAttribute("length")) length = eval(memrange.getAttribute("length"))
for property in memrange.getElementsByTagName("property"): for property in memrange.getElementsByTagName("property"):
@ -297,5 +342,3 @@ class Target:
def flash_commit(self, progress_cb=None): def flash_commit(self, progress_cb=None):
for m in self.mem: for m in self.mem:
m.commit(progress_cb) m.commit(progress_cb)

View File

@ -5,56 +5,52 @@ pasting into blackmagic's nrf51.c
""" """
import subprocess,re import subprocess
import re
import io
cmd = 'git archive --remote=git://git.code.sf.net/p/openocd/code HEAD src/flash/nor/nrf51.c | tar -xO' cmd = 'git archive --remote=git://git.code.sf.net/p/openocd/code HEAD src/flash/nor/nrf5.c | tar -xO'
class Spec(): class Spec():
def __repr__(self): def __repr__(self):
return "0x%04X: /* %s %s %s */"%(self.hwid,self.comment, self.variant,self.build_code) return "0x%04X: /* %s %s %s */"%(self.hwid,self.comment, self.variant,self.build_code)
fd = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE).stdout proc = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE)
specdict={} specdict = {}
specs=[] specs = []
spec=Spec() spec = Spec()
for line in fd.read().split('\n'): for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
m=re.search('/\*(.*)\*/',line) m = re.search('/\*(.*)\*/',line)
if m: if m:
lastcomment=m.group(1) lastcomment=m.group(1)
m=re.search('.hwid.*=\s*(0x[0-9A-F]*),',line) m = re.search('NRF51_DEVICE_DEF\((0x[0-9A-F]*),\s*"(.*)",\s*"(.*)",\s*"(.*)",\s*([0-9]*)\s*\),', line)
if m: if m:
spec.hwid=int(m.group(1),base=0) spec.hwid = int(m.group(1), base=0)
m=re.search('.variant.*=\s*"(.*)",',line) spec.variant = m.group(3)
if m: spec.build_code = m.group(4)
spec.variant=m.group(1) spec.flash_size_kb = int(m.group(5), base=0)
m=re.search('.build_code.*=\s*"(.*)",',line) ram, flash = {'AA':(16,256),
if m: 'AB':(16,128),
spec.build_code=m.group(1) 'AC':(32,256)}[spec.variant[-2:]]
m=re.search('.flash_size_kb.*=\s*([0-9]*),',line) assert flash == spec.flash_size_kb
if m:
spec.flash_size_kb=int(m.group(1),base=0)
ram,flash = {'AA':(16,256),
'AB':(16,128),
'AC':(32,256)}[spec.variant[-2:]]
assert flash==spec.flash_size_kb
spec.ram_size_kb = ram spec.ram_size_kb = ram
nicecomment =lastcomment.strip().replace('IC ','').replace('Devices ','').replace('.','') nicecomment = lastcomment.strip().replace('IC ','').replace('Devices ','').replace('.','')
spec.comment=nicecomment spec.comment = nicecomment
specdict.setdefault((ram,flash),[]).append(spec) specdict.setdefault((ram,flash),[]).append(spec)
specs.append(spec) specs.append(spec)
spec=Spec() spec=Spec()
for (ram,flash),specs in specdict.iteritems(): for (ram,flash),specs in specdict.items():
specs.sort(key=lambda x:x.hwid) specs.sort(key=lambda x:x.hwid)
for spec in specs: for spec in specs:
print "\tcase",spec print("\tcase",spec)
print '\t\tt->driver = "Nordic nRF51";' print('\t\tt->driver = "Nordic nRF51";')
print '\t\ttarget_add_ram(t, 0x20000000, 0x%X);'%(1024*ram) print('\t\ttarget_add_ram(t, 0x20000000, 0x%X);'%(1024*ram))
print '\t\tnrf51_add_flash(t, 0x00000000, 0x%X, NRF51_PAGE_SIZE);'%(1024*flash) print('\t\tnrf51_add_flash(t, 0x00000000, 0x%X, NRF51_PAGE_SIZE);'%(1024*flash))
print '\t\tnrf51_add_flash(t, NRF51_UICR, 0x100, 0x100);' print('\t\tnrf51_add_flash(t, NRF51_UICR, 0x100, 0x100);')
print '\t\ttarget_add_commands(t, nrf51_cmd_list, "nRF51");' print('\t\ttarget_add_commands(t, nrf51_cmd_list, "nRF51");')
print '\t\treturn true;' print('\t\treturn true;')

View File

@ -3,7 +3,7 @@
# hexprog.py: Python application to flash a target with an Intel hex file # hexprog.py: Python application to flash a target with an Intel hex file
# Copyright (C) 2011 Black Sphere Technologies # Copyright (C) 2011 Black Sphere Technologies
# Written by Gareth McMullin <gareth@blacksphere.co.nz> # Written by Gareth McMullin <gareth@blacksphere.co.nz>
# #
# This program is free software: you can redistribute it and/or modify # 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 # it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or # the Free Software Foundation, either version 3 of the License, or
@ -31,15 +31,16 @@ def flash_write_hex(target, hexfile, progress_cb=None):
f = open(hexfile) f = open(hexfile)
addrhi = 0 addrhi = 0
for line in f: for line in f:
if line[0] != ':': raise Exception("Error in hex file") if line[0] != ':':
raise Exception("Error in hex file")
reclen = int(line[1:3], 16) reclen = int(line[1:3], 16)
addrlo = int(line[3:7], 16) addrlo = int(line[3:7], 16)
rectype = int(line[7:9], 16); rectype = int(line[7:9], 16);
if sum(ord(x) for x in gdb.unhexify(line[1:11+reclen*2])) & 0xff != 0: if sum(x for x in bytes.fromhex(line[1:11+reclen*2])) & 0xff != 0:
raise Exception("Checksum error in hex file") raise Exception("Checksum error in hex file")
if rectype == 0: # Data record if rectype == 0: # Data record
addr = (addrhi << 16) + addrlo addr = (addrhi << 16) + addrlo
data = gdb.unhexify(line[9:9+reclen*2]) data = bytes.fromhex(line[9:9+reclen*2])
target.flash_write_prepare(addr, data) target.flash_write_prepare(addr, data)
pass pass
elif rectype == 4: # High address record elif rectype == 4: # High address record
@ -48,16 +49,16 @@ def flash_write_hex(target, hexfile, progress_cb=None):
elif rectype == 5: # Entry record elif rectype == 5: # Entry record
pass pass
elif rectype == 1: # End of file record elif rectype == 1: # End of file record
break break
else: else:
raise Exception("Invalid record in hex file") raise Exception("Invalid record in hex file")
try: try:
target.flash_commit(progress_cb) target.flash_commit(progress_cb)
except: except:
print "Flash write failed! Is device protected?\n" print("Flash write failed! Is device protected?\n")
exit(-1) exit(-1)
if __name__ == "__main__": if __name__ == "__main__":
from serial import Serial, SerialException from serial import Serial, SerialException
@ -67,8 +68,8 @@ if __name__ == "__main__":
if platform == "linux2": if platform == "linux2":
print ("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen print ("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
print("Black Magic Probe -- Target Production Programming Tool -- version 1.0") print("Black Magic Probe -- Target Production Programming Tool -- version 1.0")
print "Copyright (C) 2011 Black Sphere Technologies" print("Copyright (C) 2011 Black Sphere Technologies")
print "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>" print("License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>")
print("") print("")
dev = "COM1" if platform == "win32" else "/dev/ttyACM0" dev = "COM1" if platform == "win32" else "/dev/ttyACM0"
@ -80,13 +81,20 @@ if __name__ == "__main__":
try: try:
opts, args = getopt(argv[1:], "sd:b:t:rR") opts, args = getopt(argv[1:], "sd:b:t:rR")
for opt in opts: for opt in opts:
if opt[0] == "-s": scan = "swdp_scan" if opt[0] == "-s":
elif opt[0] == "-b": baud = int(opt[1]) scan = "swdp_scan"
elif opt[0] == "-d": dev = opt[1] elif opt[0] == "-b":
elif opt[0] == "-t": targetno = int(opt[1]) baud = int(opt[1])
elif opt[0] == "-r": unprot = True elif opt[0] == "-d":
elif opt[0] == "-R": prot = True dev = opt[1]
else: raise Exception() 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] hexfile = args[0]
except: except:
@ -101,39 +109,44 @@ if __name__ == "__main__":
exit(-1) exit(-1)
try: try:
s = Serial(dev, baud, timeout=3) s = Serial(dev) #, baud, timeout=0.1)
s.setDTR(1) #s.setDTR(1)
while s.read(1024): #s.flushInput()
pass
#while s.read(1024):
# pass
target = gdb.Target(s) target = gdb.Target(s)
except SerialException, e: except SerialException as e:
print("FATAL: Failed to open serial device!\n%s\n" % e[0]) print("FATAL: Failed to open serial device!\n%s\n" % e[0])
exit(-1) exit(-1)
try: try:
r = target.monitor("version") r = target.monitor("version")
for s in r: print s, for s in r:
except SerialException, e: print(s.decode(), end=' ')
except SerialException as e:
print("FATAL: Serial communication failure!\n%s\n" % e[0]) print("FATAL: Serial communication failure!\n%s\n" % e[0])
exit(-1) exit(-1)
except: pass #except: pass
print "Target device scan:" print("Target device scan:")
targetlist = None targetlist = None
r = target.monitor(scan) r = target.monitor(scan)
for s in r: for s in r:
print s, print(s.decode(), end=' ')
print print()
r = target.monitor("targets") r = target.monitor("targets")
for s in r: for s in r:
if s.startswith("No. Att Driver"): targetlist = [] if s.startswith(b"No. Att Driver"):
targetlist = []
try: try:
if type(targetlist) is list: if type(targetlist) is list:
targetlist.append(int(s[:2])) targetlist.append(int(s[:2]))
except: pass except:
pass
#if not targetlist: #if not targetlist:
# print("FATAL: No usable targets found!\n") # print("FATAL: No usable targets found!\n")
@ -161,7 +174,7 @@ if __name__ == "__main__":
print("FLASH memory -- Offset: 0x%X BlockSize:0x%X\n" % (m.offset, m.blocksize)) print("FLASH memory -- Offset: 0x%X BlockSize:0x%X\n" % (m.offset, m.blocksize))
def progress(percent): def progress(percent):
print ("Progress: %d%%\r" % percent), print("Progress: %d%%\r" % percent, end=' ')
stdout.flush() stdout.flush()
print("Programming target") print("Programming target")
@ -179,4 +192,3 @@ if __name__ == "__main__":
target.detach() target.detach()
print("\nAll operations complete!\n") print("\nAll operations complete!\n")

View File

@ -18,7 +18,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
from time import sleep from time import sleep
import struct import struct
import os import os
@ -72,7 +71,7 @@ def stm32_read(dev):
return data return data
def stm32_manifest(dev): def stm32_manifest(dev):
dev.download(0, "") dev.download(0, b"")
while True: while True:
try: try:
status = dev.get_status() status = dev.get_status()
@ -138,7 +137,7 @@ def stm32_scan(args, test):
product = dfudev.handle.getString(dfudev.dev.iProduct, 96).decode('utf8') product = dfudev.handle.getString(dfudev.dev.iProduct, 96).decode('utf8')
serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30).decode('utf8') serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30).decode('utf8')
if args.serial_target: if args.serial_target:
if man == "Black Sphere Technologies" and serial_no == args.serial_target: if man == "Black Sphere Technologies" and serial_no == args.serial_target:
break break
else: else:
if man == "Black Sphere Technologies": if man == "Black Sphere Technologies":
@ -236,7 +235,7 @@ if __name__ == "__main__":
bin = file.read() bin = file.read()
len = len(bin) len = len(bin)
addr = start addr = start
print("-") print("\n-")
while bin: while bin:
try: try:
stm32_set_address(dfudev, addr) stm32_set_address(dfudev, addr)
@ -251,7 +250,7 @@ if __name__ == "__main__":
else : else :
size = len size = len
if bin[:size] != bytearray(data[:size]) : if bin[:size] != bytearray(data[:size]) :
print ("\nMitmatch in block at 0x%08X" % addr) print ("\nMismatch in block at 0x%08X" % addr)
break; break;
bin = bin[1024:] bin = bin[1024:]
addr += 1024 addr += 1024

View File

@ -106,9 +106,11 @@ int generic_crc32(target *t, uint32_t *crc_res, uint32_t base, size_t len)
* 22 s @ 4k and 21 s @ 64k * 22 s @ 4k and 21 s @ 64k
*/ */
uint8_t bytes[0x1000]; uint8_t bytes[0x1000];
uint32_t start_time = platform_time_ms();
#else #else
uint8_t bytes[128]; uint8_t bytes[128];
#endif
#if defined(ENABLE_DEBUG)
uint32_t start_time = platform_time_ms();
#endif #endif
uint32_t last_time = platform_time_ms(); uint32_t last_time = platform_time_ms();
while (len) { while (len) {

View File

@ -24,6 +24,18 @@
* field firmware upgrade. * field firmware upgrade.
* *
* The device's unique id is used as the USB serial number string. * The device's unique id is used as the USB serial number string.
*
* Endpoint Usage
*
* 0 Control Endpoint
* IN 1 GDB CDC DATA
* OUT 1 GDB CDC DATA
* IN 2 GDB CDC CTR
* IN 3 UART CDC DATA
* OUT 3 UART CDC DATA
* OUT 4 UART CDC CTRL
* In 5 Trace Capture
*
*/ */
#include "general.h" #include "general.h"
@ -42,7 +54,15 @@
#include <libopencm3/cm3/scb.h> #include <libopencm3/cm3/scb.h>
#include <libopencm3/usb/dfu.h> #include <libopencm3/usb/dfu.h>
#define DFU_IF_NO 4 #define GDB_IF_NO 0
#define UART_IF_NO 2
#define DFU_IF_NO 4
#if defined(PLATFORM_HAS_TRACESWO)
# define TRACE_IF_NO 5
# define TOTAL_INTERFACES 6
#else
# define TOTAL_INTERFACES 5
#endif
usbd_device * usbdev; usbd_device * usbdev;
@ -78,7 +98,7 @@ static const struct usb_device_descriptor dev_desc = {
static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x82, .bEndpointAddress = (CDCACM_GDB_ENDPOINT + 1) | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 255, .bInterval = 255,
@ -87,14 +107,14 @@ static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{
static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ static const struct usb_endpoint_descriptor gdb_data_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x01, .bEndpointAddress = CDCACM_GDB_ENDPOINT,
.bmAttributes = USB_ENDPOINT_ATTR_BULK, .bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE, .wMaxPacketSize = CDCACM_PACKET_SIZE,
.bInterval = 1, .bInterval = 1,
}, { }, {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x81, .bEndpointAddress = CDCACM_GDB_ENDPOINT | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_BULK, .bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE, .wMaxPacketSize = CDCACM_PACKET_SIZE,
.bInterval = 1, .bInterval = 1,
@ -118,7 +138,7 @@ static const struct {
.bDescriptorType = CS_INTERFACE, .bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
.bmCapabilities = 0, .bmCapabilities = 0,
.bDataInterface = 1, .bDataInterface = GDB_IF_NO + 1,
}, },
.acm = { .acm = {
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
@ -130,8 +150,8 @@ static const struct {
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor), .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
.bDescriptorType = CS_INTERFACE, .bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_UNION, .bDescriptorSubtype = USB_CDC_TYPE_UNION,
.bControlInterface = 0, .bControlInterface = GDB_IF_NO,
.bSubordinateInterface0 = 1, .bSubordinateInterface0 = GDB_IF_NO + 1,
} }
}; };
@ -155,7 +175,7 @@ static const struct usb_interface_descriptor gdb_comm_iface[] = {{
static const struct usb_interface_descriptor gdb_data_iface[] = {{ static const struct usb_interface_descriptor gdb_data_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE, .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 1, .bInterfaceNumber = GDB_IF_NO + 1,
.bAlternateSetting = 0, .bAlternateSetting = 0,
.bNumEndpoints = 2, .bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_DATA, .bInterfaceClass = USB_CLASS_DATA,
@ -169,7 +189,7 @@ static const struct usb_interface_descriptor gdb_data_iface[] = {{
static const struct usb_iface_assoc_descriptor gdb_assoc = { static const struct usb_iface_assoc_descriptor gdb_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 0, .bFirstInterface = GDB_IF_NO,
.bInterfaceCount = 2, .bInterfaceCount = 2,
.bFunctionClass = USB_CLASS_CDC, .bFunctionClass = USB_CLASS_CDC,
.bFunctionSubClass = USB_CDC_SUBCLASS_ACM, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
@ -181,7 +201,7 @@ static const struct usb_iface_assoc_descriptor gdb_assoc = {
static const struct usb_endpoint_descriptor uart_comm_endp[] = {{ static const struct usb_endpoint_descriptor uart_comm_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x84, .bEndpointAddress = (CDCACM_UART_ENDPOINT + 1) | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
.wMaxPacketSize = 16, .wMaxPacketSize = 16,
.bInterval = 255, .bInterval = 255,
@ -190,14 +210,14 @@ static const struct usb_endpoint_descriptor uart_comm_endp[] = {{
static const struct usb_endpoint_descriptor uart_data_endp[] = {{ static const struct usb_endpoint_descriptor uart_data_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x03, .bEndpointAddress = CDCACM_UART_ENDPOINT,
.bmAttributes = USB_ENDPOINT_ATTR_BULK, .bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE / 2, .wMaxPacketSize = CDCACM_PACKET_SIZE / 2,
.bInterval = 1, .bInterval = 1,
}, { }, {
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x83, .bEndpointAddress = CDCACM_UART_ENDPOINT | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_BULK, .bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = CDCACM_PACKET_SIZE, .wMaxPacketSize = CDCACM_PACKET_SIZE,
.bInterval = 1, .bInterval = 1,
@ -221,7 +241,7 @@ static const struct {
.bDescriptorType = CS_INTERFACE, .bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
.bmCapabilities = 0, .bmCapabilities = 0,
.bDataInterface = 3, .bDataInterface = UART_IF_NO + 1,
}, },
.acm = { .acm = {
.bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor),
@ -233,15 +253,15 @@ static const struct {
.bFunctionLength = sizeof(struct usb_cdc_union_descriptor), .bFunctionLength = sizeof(struct usb_cdc_union_descriptor),
.bDescriptorType = CS_INTERFACE, .bDescriptorType = CS_INTERFACE,
.bDescriptorSubtype = USB_CDC_TYPE_UNION, .bDescriptorSubtype = USB_CDC_TYPE_UNION,
.bControlInterface = 2, .bControlInterface = UART_IF_NO,
.bSubordinateInterface0 = 3, .bSubordinateInterface0 = UART_IF_NO + 1,
} }
}; };
static const struct usb_interface_descriptor uart_comm_iface[] = {{ static const struct usb_interface_descriptor uart_comm_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE, .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 2, .bInterfaceNumber = UART_IF_NO,
.bAlternateSetting = 0, .bAlternateSetting = 0,
.bNumEndpoints = 1, .bNumEndpoints = 1,
.bInterfaceClass = USB_CLASS_CDC, .bInterfaceClass = USB_CLASS_CDC,
@ -258,7 +278,7 @@ static const struct usb_interface_descriptor uart_comm_iface[] = {{
static const struct usb_interface_descriptor uart_data_iface[] = {{ static const struct usb_interface_descriptor uart_data_iface[] = {{
.bLength = USB_DT_INTERFACE_SIZE, .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 3, .bInterfaceNumber = UART_IF_NO + 1,
.bAlternateSetting = 0, .bAlternateSetting = 0,
.bNumEndpoints = 2, .bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_DATA, .bInterfaceClass = USB_CLASS_DATA,
@ -272,7 +292,7 @@ static const struct usb_interface_descriptor uart_data_iface[] = {{
static const struct usb_iface_assoc_descriptor uart_assoc = { static const struct usb_iface_assoc_descriptor uart_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 2, .bFirstInterface = UART_IF_NO,
.bInterfaceCount = 2, .bInterfaceCount = 2,
.bFunctionClass = USB_CLASS_CDC, .bFunctionClass = USB_CLASS_CDC,
.bFunctionSubClass = USB_CDC_SUBCLASS_ACM, .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
@ -307,7 +327,7 @@ const struct usb_interface_descriptor dfu_iface = {
static const struct usb_iface_assoc_descriptor dfu_assoc = { static const struct usb_iface_assoc_descriptor dfu_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 4, .bFirstInterface = DFU_IF_NO,
.bInterfaceCount = 1, .bInterfaceCount = 1,
.bFunctionClass = 0xFE, .bFunctionClass = 0xFE,
.bFunctionSubClass = 1, .bFunctionSubClass = 1,
@ -319,7 +339,7 @@ static const struct usb_iface_assoc_descriptor dfu_assoc = {
static const struct usb_endpoint_descriptor trace_endp[] = {{ static const struct usb_endpoint_descriptor trace_endp[] = {{
.bLength = USB_DT_ENDPOINT_SIZE, .bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT, .bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = 0x85, .bEndpointAddress = TRACE_ENDPOINT | USB_REQ_TYPE_IN,
.bmAttributes = USB_ENDPOINT_ATTR_BULK, .bmAttributes = USB_ENDPOINT_ATTR_BULK,
.wMaxPacketSize = 64, .wMaxPacketSize = 64,
.bInterval = 0, .bInterval = 0,
@ -328,7 +348,7 @@ static const struct usb_endpoint_descriptor trace_endp[] = {{
const struct usb_interface_descriptor trace_iface = { const struct usb_interface_descriptor trace_iface = {
.bLength = USB_DT_INTERFACE_SIZE, .bLength = USB_DT_INTERFACE_SIZE,
.bDescriptorType = USB_DT_INTERFACE, .bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 5, .bInterfaceNumber = TRACE_IF_NO,
.bAlternateSetting = 0, .bAlternateSetting = 0,
.bNumEndpoints = 1, .bNumEndpoints = 1,
.bInterfaceClass = 0xFF, .bInterfaceClass = 0xFF,
@ -342,7 +362,7 @@ const struct usb_interface_descriptor trace_iface = {
static const struct usb_iface_assoc_descriptor trace_assoc = { static const struct usb_iface_assoc_descriptor trace_assoc = {
.bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
.bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
.bFirstInterface = 5, .bFirstInterface = TRACE_IF_NO,
.bInterfaceCount = 1, .bInterfaceCount = 1,
.bFunctionClass = 0xFF, .bFunctionClass = 0xFF,
.bFunctionSubClass = 0xFF, .bFunctionSubClass = 0xFF,
@ -381,11 +401,7 @@ static const struct usb_config_descriptor config = {
.bLength = USB_DT_CONFIGURATION_SIZE, .bLength = USB_DT_CONFIGURATION_SIZE,
.bDescriptorType = USB_DT_CONFIGURATION, .bDescriptorType = USB_DT_CONFIGURATION,
.wTotalLength = 0, .wTotalLength = 0,
#if defined(PLATFORM_HAS_TRACESWO) .bNumInterfaces = TOTAL_INTERFACES,
.bNumInterfaces = 6,
#else
.bNumInterfaces = 5,
#endif
.bConfigurationValue = 1, .bConfigurationValue = 1,
.iConfiguration = 0, .iConfiguration = 0,
.bmAttributes = 0x80, .bmAttributes = 0x80,
@ -437,7 +453,7 @@ static enum usbd_request_return_codes cdcacm_control_request(usbd_device *dev,
case USB_CDC_REQ_SET_CONTROL_LINE_STATE: case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
cdcacm_set_modem_state(dev, req->wIndex, true, true); cdcacm_set_modem_state(dev, req->wIndex, true, true);
/* Ignore if not for GDB interface */ /* Ignore if not for GDB interface */
if(req->wIndex != 0) if(req->wIndex != GDB_IF_NO)
return USBD_REQ_HANDLED; return USBD_REQ_HANDLED;
cdcacm_gdb_dtr = req->wValue & 1; cdcacm_gdb_dtr = req->wValue & 1;
@ -448,10 +464,10 @@ static enum usbd_request_return_codes cdcacm_control_request(usbd_device *dev,
return USBD_REQ_NOTSUPP; return USBD_REQ_NOTSUPP;
switch(req->wIndex) { switch(req->wIndex) {
case 2: case UART_IF_NO:
usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf); usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf);
return USBD_REQ_HANDLED; return USBD_REQ_HANDLED;
case 0: case GDB_IF_NO:
return USBD_REQ_HANDLED; /* Ignore on GDB Port */ return USBD_REQ_HANDLED; /* Ignore on GDB Port */
default: default:
return USBD_REQ_NOTSUPP; return USBD_REQ_NOTSUPP;
@ -501,6 +517,7 @@ static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool d
notif->wLength = 2; notif->wLength = 2;
buf[8] = (dsr ? 2 : 0) | (dcd ? 1 : 0); buf[8] = (dsr ? 2 : 0) | (dcd ? 1 : 0);
buf[9] = 0; buf[9] = 0;
/* FIXME: Remove magic numbers */
usbd_ep_write_packet(dev, 0x82 + iface, buf, 10); usbd_ep_write_packet(dev, 0x82 + iface, buf, 10);
} }
@ -510,26 +527,29 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
/* GDB interface */ /* GDB interface */
#if defined(STM32F4) || defined(LM4F) || defined(SAMD) #if defined(STM32F4) || defined(LM4F) || defined(SAMD)
usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, usbd_ep_setup(dev, CDCACM_GDB_ENDPOINT, USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE, gdb_usb_out_cb); CDCACM_PACKET_SIZE, gdb_usb_out_cb);
#else #else
usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, usbd_ep_setup(dev, CDCACM_GDB_ENDPOINT, USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE, NULL); CDCACM_PACKET_SIZE, NULL);
#endif #endif
usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, usbd_ep_setup(dev, CDCACM_GDB_ENDPOINT | USB_REQ_TYPE_IN,
CDCACM_PACKET_SIZE, NULL); USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, NULL);
usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); usbd_ep_setup(dev, (CDCACM_GDB_ENDPOINT + 1) | USB_REQ_TYPE_IN,
USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
/* Serial interface */ /* Serial interface */
usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK, usbd_ep_setup(dev, CDCACM_UART_ENDPOINT, USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE / 2, usbuart_usb_out_cb); CDCACM_PACKET_SIZE / 2, usbuart_usb_out_cb);
usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK, usbd_ep_setup(dev, CDCACM_UART_ENDPOINT | USB_REQ_TYPE_IN,
USB_ENDPOINT_ATTR_BULK,
CDCACM_PACKET_SIZE, usbuart_usb_in_cb); CDCACM_PACKET_SIZE, usbuart_usb_in_cb);
usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); usbd_ep_setup(dev, (CDCACM_UART_ENDPOINT + 1) | USB_REQ_TYPE_IN,
USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
#if defined(PLATFORM_HAS_TRACESWO) #if defined(PLATFORM_HAS_TRACESWO)
/* Trace interface */ /* Trace interface */
usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, usbd_ep_setup(dev, TRACE_ENDPOINT | USB_REQ_TYPE_IN, USB_ENDPOINT_ATTR_BULK,
64, trace_buf_drain); 64, trace_buf_drain);
#endif #endif
@ -541,8 +561,8 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue)
/* Notify the host that DCD is asserted. /* Notify the host that DCD is asserted.
* Allows the use of /dev/tty* devices on *BSD/MacOS * Allows the use of /dev/tty* devices on *BSD/MacOS
*/ */
cdcacm_set_modem_state(dev, 0, true, true); cdcacm_set_modem_state(dev, GDB_IF_NO, true, true);
cdcacm_set_modem_state(dev, 2, true, true); cdcacm_set_modem_state(dev, UART_IF_NO, true, true);
} }
/* We need a special large control buffer for this device: */ /* We need a special large control buffer for this device: */

View File

@ -34,6 +34,7 @@
#define CDCACM_GDB_ENDPOINT 1 #define CDCACM_GDB_ENDPOINT 1
#define CDCACM_UART_ENDPOINT 3 #define CDCACM_UART_ENDPOINT 3
#define TRACE_ENDPOINT 5
extern usbd_device *usbdev; extern usbd_device *usbdev;

View File

@ -169,7 +169,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
continue; continue;
} }
/* Exclude hubs from testing. Probably more classes could be excluded here!*/ /* Exclude hubs from testing. Probably more classes could be excluded here!*/
if (desc.bDeviceClass == LIBUSB_CLASS_HUB) { switch (desc.bDeviceClass) {
case LIBUSB_CLASS_HUB:
case LIBUSB_CLASS_WIRELESS:
continue; continue;
} }
libusb_device_handle *handle; libusb_device_handle *handle;

View File

@ -48,7 +48,7 @@ int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc) {return -1;}
int dap_swdptap_init(ADIv5_DP_t *dp) {return -1;} int dap_swdptap_init(ADIv5_DP_t *dp) {return -1;}
int dap_jtag_dp_init(ADIv5_DP_t *dp) {return -1;} int dap_jtag_dp_init(ADIv5_DP_t *dp) {return -1;}
void dap_swd_configure(uint8_t cfg) {}; void dap_swd_configure(uint8_t cfg) {};
void dap_srst_set_val(assert) {}; void dap_srst_set_val(bool assert) {};
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif

View File

@ -290,7 +290,6 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
opt->opt_targetid = strtol(optarg, NULL, 0); opt->opt_targetid = strtol(optarg, NULL, 0);
break; break;
case 'M': case 'M':
opt->opt_mode = BMP_MODE_MONITOR;
if (optarg) if (optarg)
opt->opt_monitor = optarg; opt->opt_monitor = optarg;
break; break;
@ -321,7 +320,11 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
if (opt->opt_mode == BMP_MODE_DEBUG) if (opt->opt_mode == BMP_MODE_DEBUG)
opt->opt_mode = BMP_MODE_FLASH_WRITE; opt->opt_mode = BMP_MODE_FLASH_WRITE;
opt->opt_flash_file = argv[optind]; opt->opt_flash_file = argv[optind];
} else if ((opt->opt_mode == BMP_MODE_DEBUG) &&
(opt->opt_monitor)) {
opt->opt_mode = BMP_MODE_MONITOR; // To avoid DEBUG mode
} }
/* Checks */ /* Checks */
if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) || if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) ||
(opt->opt_mode == BMP_MODE_SWJ_TEST) || (opt->opt_mode == BMP_MODE_SWJ_TEST) ||
@ -448,10 +451,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
default: default:
DEBUG_WARN("No test for this core type yet\n"); DEBUG_WARN("No test for this core type yet\n");
} }
} else if (opt->opt_mode == BMP_MODE_MONITOR) {
res = command_process(t, opt->opt_monitor);
if (res)
DEBUG_WARN("Command \"%s\" failed\n", opt->opt_monitor);
} }
if ((opt->opt_mode == BMP_MODE_TEST) || if ((opt->opt_mode == BMP_MODE_TEST) ||
(opt->opt_mode == BMP_MODE_SWJ_TEST)) (opt->opt_mode == BMP_MODE_SWJ_TEST))
@ -480,9 +479,14 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
if (opt->opt_flash_size < map.size) if (opt->opt_flash_size < map.size)
/* restrict to size given on command line */ /* restrict to size given on command line */
map.size = opt->opt_flash_size; map.size = opt->opt_flash_size;
if (opt->opt_monitor) {
res = command_process(t, opt->opt_monitor);
if (res)
DEBUG_WARN("Command \"%s\" failed\n", opt->opt_monitor);
}
if (opt->opt_mode == BMP_MODE_RESET) { if (opt->opt_mode == BMP_MODE_RESET) {
target_reset(t); target_reset(t);
} else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) { } else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) {
DEBUG_INFO("Erase %zu bytes at 0x%08" PRIx32 "\n", opt->opt_flash_size, DEBUG_INFO("Erase %zu bytes at 0x%08" PRIx32 "\n", opt->opt_flash_size,
opt->opt_flash_start); opt->opt_flash_start);
unsigned int erased = target_flash_erase(t, opt->opt_flash_start, unsigned int erased = target_flash_erase(t, opt->opt_flash_start,
@ -510,6 +514,8 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
unsigned int flashed = target_flash_write(t, opt->opt_flash_start, unsigned int flashed = target_flash_write(t, opt->opt_flash_start,
map.data, map.size); map.data, map.size);
/* Buffered write cares for padding*/ /* Buffered write cares for padding*/
if (!flashed)
flashed = target_flash_done(t);
if (flashed) { if (flashed) {
DEBUG_WARN("Flashing failed!\n"); DEBUG_WARN("Flashing failed!\n");
res = -1; res = -1;
@ -518,7 +524,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
DEBUG_INFO("Success!\n"); DEBUG_INFO("Success!\n");
} }
} }
target_flash_done(t);
uint32_t end_time = platform_time_ms(); uint32_t end_time = platform_time_ms();
DEBUG_WARN("Flash Write succeeded for %d bytes, %8.3f kiB/s\n", DEBUG_WARN("Flash Write succeeded for %d bytes, %8.3f kiB/s\n",
(int)map.size, (((map.size * 1.0)/(end_time - start_time)))); (int)map.size, (((map.size * 1.0)/(end_time - start_time))));

View File

@ -398,7 +398,7 @@ static uint32_t cortexm_initial_halt(ADIv5_AP_t *ap)
*/ */
static bool cortexm_prepare(ADIv5_AP_t *ap) static bool cortexm_prepare(ADIv5_AP_t *ap)
{ {
#if PC_HOSTED == 1 #if ((PC_HOSTED == 1) || (ENABLE_DEBUG == 1))
uint32_t start_time = platform_time_ms(); uint32_t start_time = platform_time_ms();
#endif #endif
uint32_t dhcsr = cortexm_initial_halt(ap); uint32_t dhcsr = cortexm_initial_halt(ap);
@ -834,9 +834,15 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
adiv5_ap_unref(ap); adiv5_ap_unref(ap);
} }
/* We halted at least CortexM for Romtable scan. /* We halted at least CortexM for Romtable scan.
* Release the devices now. Attach() will halt them again.*/ * With connect under reset, keep the devices halted.
for (target *t = target_list; t; t = t->next) * Otherwise, release the devices now.
target_halt_resume(t, false); * Attach() will halt them again.
*/
for (target *t = target_list; t; t = t->next) {
if (!connect_assert_srst) {
target_halt_resume(t, false);
}
}
adiv5_dp_unref(dp); adiv5_dp_unref(dp);
} }

View File

@ -471,8 +471,6 @@ bool cortexm_probe(ADIv5_AP_t *ap)
PROBE(lpc17xx_probe); PROBE(lpc17xx_probe);
} }
#undef PROBE #undef PROBE
/* Restart the CortexM we stopped for Romtable scan. Allow pure debug.*/
target_halt_resume(t, 0);
return true; return true;
} }
@ -1217,8 +1215,8 @@ static int cortexm_hostio_request(target *t)
t->tc->interrupted = false; t->tc->interrupted = false;
target_regs_read(t, arm_regs); target_regs_read(t, arm_regs);
target_mem_read(t, params, arm_regs[1], sizeof(params));
uint32_t syscall = arm_regs[0]; uint32_t syscall = arm_regs[0];
if (syscall != SYS_EXIT) target_mem_read(t, params, arm_regs[1], sizeof(params));
int32_t ret = 0; int32_t ret = 0;
DEBUG_INFO("syscall 0"PRIx32"%"PRIx32" (%"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32")\n", DEBUG_INFO("syscall 0"PRIx32"%"PRIx32" (%"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32")\n",
@ -1608,7 +1606,7 @@ static int cortexm_hostio_request(target *t)
#endif #endif
case SYS_EXIT: /* _exit() */ case SYS_EXIT: /* _exit() */
tc_printf(t, "_exit(0x%x)\n", params[0]); tc_printf(t, "_exit(0x%x)\n", arm_regs[1]);
target_halt_resume(t, 1); target_halt_resume(t, 1);
break; break;

View File

@ -22,6 +22,7 @@
* programming. * programming.
* *
* Tested with * Tested with
* * SAMD09D14A (rev B)
* * SAMD20E17A (rev C) * * SAMD20E17A (rev C)
* * SAMD20J18A (rev B) * * SAMD20J18A (rev B)
* * SAMD21J18A (rev B) * * SAMD21J18A (rev B)
@ -128,7 +129,7 @@ const struct command_s samd_cmd_list[] = {
#define SAMD_STATUSB_PROT (1 << 16) #define SAMD_STATUSB_PROT (1 << 16)
/* Device Identification Register (DID) */ /* Device Identification Register (DID) */
#define SAMD_DID_MASK 0xFF3C0000 #define SAMD_DID_MASK 0xFF380000
#define SAMD_DID_CONST_VALUE 0x10000000 #define SAMD_DID_CONST_VALUE 0x10000000
#define SAMD_DID_DEVSEL_MASK 0xFF #define SAMD_DID_DEVSEL_MASK 0xFF
#define SAMD_DID_DEVSEL_POS 0 #define SAMD_DID_DEVSEL_POS 0
@ -341,6 +342,8 @@ struct samd_descr {
uint8_t series; uint8_t series;
char revision; char revision;
char pin; char pin;
uint32_t ram_size;
uint32_t flash_size;
uint8_t mem; uint8_t mem;
char variant; char variant;
char package[3]; char package[3];
@ -351,6 +354,8 @@ struct samd_descr samd_parse_device_id(uint32_t did)
uint8_t i = 0; uint8_t i = 0;
const struct samd_part *parts = samd_d21_parts; const struct samd_part *parts = samd_d21_parts;
memset(samd.package, 0, 3); memset(samd.package, 0, 3);
samd.ram_size = 0x8000;
samd.flash_size = 0x40000;
uint8_t family = (did >> SAMD_DID_FAMILY_POS) uint8_t family = (did >> SAMD_DID_FAMILY_POS)
& SAMD_DID_FAMILY_MASK; & SAMD_DID_FAMILY_MASK;
@ -380,6 +385,7 @@ struct samd_descr samd_parse_device_id(uint32_t did)
} }
break; break;
case 3: samd.series = 11; break; case 3: samd.series = 11; break;
case 4: samd.series = 9; break;
default: samd.series = 0; break; default: samd.series = 0; break;
} }
/* Revision */ /* Revision */
@ -419,6 +425,23 @@ struct samd_descr samd_parse_device_id(uint32_t did)
samd.mem = 14 - (devsel % 3); samd.mem = 14 - (devsel % 3);
samd.variant = 'A'; samd.variant = 'A';
break; break;
case 9: /* SAM D09 */
samd.ram_size = 4096;
switch (devsel) {
case 0:
samd.pin = 'D';
samd.mem = 14;
samd.flash_size = 16384;
samd.package[0] = 'M';
break;
case 7:
samd.pin = 'C';
samd.mem = 13;
samd.flash_size = 8192;
break;
}
samd.variant = 'A';
break;
} }
return samd; return samd;
@ -475,14 +498,14 @@ bool samd_probe(target *t)
/* Part String */ /* Part String */
if (protected) { if (protected) {
sprintf(priv_storage->samd_variant_string, sprintf(priv_storage->samd_variant_string,
"Atmel SAM%c%d%c%d%c%s (rev %c) (PROT=1)", "Atmel SAM%c%02d%c%d%c%s (rev %c) (PROT=1)",
samd.family, samd.family,
samd.series, samd.pin, samd.mem, samd.series, samd.pin, samd.mem,
samd.variant, samd.variant,
samd.package, samd.revision); samd.package, samd.revision);
} else { } else {
sprintf(priv_storage->samd_variant_string, sprintf(priv_storage->samd_variant_string,
"Atmel SAM%c%d%c%d%c%s (rev %c)", "Atmel SAM%c%02d%c%d%c%s (rev %c)",
samd.family, samd.family,
samd.series, samd.pin, samd.mem, samd.series, samd.pin, samd.mem,
samd.variant, samd.variant,
@ -513,8 +536,8 @@ bool samd_probe(target *t)
t->attach = samd_protected_attach; t->attach = samd_protected_attach;
} }
target_add_ram(t, 0x20000000, 0x8000); target_add_ram(t, 0x20000000, samd.ram_size);
samd_add_flash(t, 0x00000000, 0x40000); samd_add_flash(t, 0x00000000, samd.flash_size);
target_add_commands(t, samd_cmd_list, "SAMD"); target_add_commands(t, samd_cmd_list, "SAMD");
/* If we're not in reset here */ /* If we're not in reset here */

View File

@ -52,6 +52,9 @@
#define FLASH_MEMORY_SIZE 0x1FFF75E0 #define FLASH_MEMORY_SIZE 0x1FFF75E0
#define FLASH_PAGE_SIZE 0x800 #define FLASH_PAGE_SIZE 0x800
#define FLASH_BANK2_START_PAGE_NB 256U #define FLASH_BANK2_START_PAGE_NB 256U
#define FLASH_OTP_START 0x1FFF7000
#define FLASH_OTP_SIZE 0x400
#define FLASH_OTP_BLOCKSIZE 0x8
#define FLASH_SIZE_MAX_G03_4 (64U * 1024U) // 64 kiB #define FLASH_SIZE_MAX_G03_4 (64U * 1024U) // 64 kiB
#define FLASH_SIZE_MAX_G05_6 (64U * 1024U) // 64 kiB #define FLASH_SIZE_MAX_G05_6 (64U * 1024U) // 64 kiB
#define FLASH_SIZE_MAX_G07_8 (128U * 1024U) // 128 kiB #define FLASH_SIZE_MAX_G07_8 (128U * 1024U) // 128 kiB
@ -189,7 +192,7 @@ static void stm32g0_add_flash(target *t, uint32_t addr, size_t length,
f->blocksize = blocksize; f->blocksize = blocksize;
f->erase = stm32g0_flash_erase; f->erase = stm32g0_flash_erase;
f->write = stm32g0_flash_write; f->write = stm32g0_flash_write;
f->buf_size = FLASH_PAGE_SIZE; f->buf_size = blocksize;
f->erased = 0xFF; f->erased = 0xFF;
target_add_flash(t, f); target_add_flash(t, f);
} }
@ -249,6 +252,9 @@ bool stm32g0_probe(target *t)
priv_storage->irreversible_enabled = false; priv_storage->irreversible_enabled = false;
t->target_storage = (void*)priv_storage; t->target_storage = (void*)priv_storage;
/* OTP Flash area */
stm32g0_add_flash(t, FLASH_OTP_START, FLASH_OTP_SIZE, FLASH_OTP_BLOCKSIZE);
return true; return true;
} }
@ -311,6 +317,7 @@ static void stm32g0_flash_lock(target *t)
/* /*
* Flash erasure function. * Flash erasure function.
* OTP case: this function clears any previous error and returns.
*/ */
static int stm32g0_flash_erase(struct target_flash *f, target_addr addr, static int stm32g0_flash_erase(struct target_flash *f, target_addr addr,
size_t len) size_t len)
@ -328,11 +335,6 @@ static int stm32g0_flash_erase(struct target_flash *f, target_addr addr,
if (len == (size_t)0U) if (len == (size_t)0U)
goto exit_cleanup; goto exit_cleanup;
nb_pages_to_erase = (uint16_t)((len - 1U) / f->blocksize) + 1U;
if (t->idcode == STM32G0B_C) // Dual-bank devices
bank1_end_page_nb = ((f->length / 2U) - 1U) / f->blocksize;
page_nb = (uint16_t)((addr - f->start) / f->blocksize);
/* Wait for Flash ready */ /* Wait for Flash ready */
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY_MASK) { while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY_MASK) {
if (target_check_error(t)) if (target_check_error(t))
@ -342,6 +344,14 @@ static int stm32g0_flash_erase(struct target_flash *f, target_addr addr,
/* Clear any previous programming error */ /* Clear any previous programming error */
target_mem_write32(t, FLASH_SR, target_mem_read32(t, FLASH_SR)); target_mem_write32(t, FLASH_SR, target_mem_read32(t, FLASH_SR));
if (addr >= (target_addr)FLASH_OTP_START)
goto exit_cleanup;
nb_pages_to_erase = (uint16_t)((len - 1U) / f->blocksize) + 1U;
if (t->idcode == STM32G0B_C) // Dual-bank devices
bank1_end_page_nb = ((f->length / 2U) - 1U) / f->blocksize;
page_nb = (uint16_t)((addr - f->start) / f->blocksize);
stm32g0_flash_unlock(t); stm32g0_flash_unlock(t);
do { do {
@ -392,12 +402,20 @@ exit_cleanup:
* The SR is supposed to be ready and free of any error. * The SR is supposed to be ready and free of any error.
* After a successful programming, the EMPTY bit is cleared to allow rebooting * After a successful programming, the EMPTY bit is cleared to allow rebooting
* in Main Flash memory without power cycle. * in Main Flash memory without power cycle.
* OTP area is programmed as the "program" area. It can be programmed 8-bytes
* by 8-bytes.
*/ */
static int stm32g0_flash_write(struct target_flash *f, target_addr dest, static int stm32g0_flash_write(struct target_flash *f, target_addr dest,
const void *src, size_t len) const void *src, size_t len)
{ {
target *t = f->t; target *t = f->t;
int ret = 0; int ret = 0;
struct stm32g0_priv_s *ps = (struct stm32g0_priv_s*)t->target_storage;
if ((dest >= (target_addr)FLASH_OTP_START) && !ps->irreversible_enabled) {
tc_printf(t, "Irreversible operations disabled\n");
goto exit_error;
}
stm32g0_flash_unlock(t); stm32g0_flash_unlock(t);

View File

@ -671,8 +671,12 @@ static const uint8_t g4_i2offset[11] = {
0x20, 0x24, 0x28, 0x2c, 0x30, 0x70, 0x44, 0x48, 0x4c, 0x50, 0x74 0x20, 0x24, 0x28, 0x2c, 0x30, 0x70, 0x44, 0x48, 0x4c, 0x50, 0x74
}; };
static const uint8_t wl_i2offset[7] = {
0x20, 0x24, 0x28, 0x2c, 0x30, 0x34, 0x38
};
static bool stm32l4_option_write( static bool stm32l4_option_write(
target *t,const uint32_t *values, int len, const uint8_t *i2offset) target *t,const uint32_t *values, int len, const uint8_t *i2offset, uint32_t fpec_base)
{ {
tc_printf(t, "Device will lose connection. Rescan!\n"); tc_printf(t, "Device will lose connection. Rescan!\n");
stm32l4_flash_unlock(t); stm32l4_flash_unlock(t);
@ -682,7 +686,7 @@ static bool stm32l4_option_write(
if(target_check_error(t)) if(target_check_error(t))
return true; return true;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
target_mem_write32(t, L4_FPEC_BASE + i2offset[i], values[i]); target_mem_write32(t, fpec_base + i2offset[i], values[i]);
stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_OPTSTRT); stm32l4_flash_write32(t, FLASH_CR, FLASH_CR_OPTSTRT);
while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY)
if(target_check_error(t)) if(target_check_error(t))
@ -717,10 +721,6 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
tc_printf(t, "STM32L5 options not implemented!\n"); tc_printf(t, "STM32L5 options not implemented!\n");
return false; return false;
} }
if (t->idcode == ID_STM32WLXX) {
tc_printf(t, "STM32WLxx options not implemented!\n");
return false;
}
if (t->idcode == ID_STM32WBXX) { if (t->idcode == ID_STM32WBXX) {
tc_printf(t, "STM32WBxx options not implemented!\n"); tc_printf(t, "STM32WBxx options not implemented!\n");
return false; return false;
@ -733,12 +733,17 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
0xFFFFFFFF, 0xFFFFFFFF, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FF00 0xFFFFFFFF, 0xFFFFFFFF, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FF00
}; };
static const uint32_t wl_values[11] = {
0x3FEFF0AA, 0xFFFFFFFF, 0xFFFFFF00, 0xFF80FFFF, 0xFF80FFFF, 0xFFFFFFFF,
0xFFFFFF00
};
uint32_t val; uint32_t val;
uint32_t values[11] = { 0xFFEFF8AA, 0xFFFFFFFF, 0, 0x000000ff, uint32_t values[11] = { 0xFFEFF8AA, 0xFFFFFFFF, 0, 0x000000ff,
0x000000ff, 0xffffffff, 0, 0x000000ff, 0x000000ff }; 0x000000ff, 0xffffffff, 0, 0x000000ff, 0x000000ff };
int len; int len;
bool res = false; bool res = false;
uint32_t fpec_base = L4_FPEC_BASE;
const uint8_t *i2offset = l4_i2offset; const uint8_t *i2offset = l4_i2offset;
if (t->idcode == ID_STM32L43) {/* L43x */ if (t->idcode == ID_STM32L43) {/* L43x */
len = 5; len = 5;
@ -753,24 +758,30 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
len = 6; len = 6;
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
values[i] = g4_values[i]; values[i] = g4_values[i];
} else if (t->idcode == ID_STM32WLXX) {/* WLxx */
len = 7;
i2offset = wl_i2offset;
fpec_base = WL_FPEC_BASE;
for (int i = 0; i < len; i++)
values[i] = wl_values[i];
} else { } else {
len = 9; len = 9;
} }
if ((argc == 2) && !strcmp(argv[1], "erase")) { if ((argc == 2) && !strcmp(argv[1], "erase")) {
res = stm32l4_option_write(t, values, len, i2offset); res = stm32l4_option_write(t, values, len, i2offset, fpec_base);
} else if ((argc > 2) && !strcmp(argv[1], "write")) { } else if ((argc > 2) && !strcmp(argv[1], "write")) {
int i; int i;
for (i = 2; i < argc; i++) for (i = 2; i < argc; i++)
values[i - 2] = strtoul(argv[i], NULL, 0); values[i - 2] = strtoul(argv[i], NULL, 0);
for (i = i - 2; i < len; i++) { for (i = i - 2; i < len; i++) {
uint32_t addr = L4_FPEC_BASE + i2offset[i]; uint32_t addr = fpec_base + i2offset[i];
values[i] = target_mem_read32(t, addr); values[i] = target_mem_read32(t, addr);
} }
if ((values[0] & 0xff) == 0xCC) { if ((values[0] & 0xff) == 0xCC) {
values[0]++; values[0]++;
tc_printf(t, "Changing Level 2 request to Level 1!"); tc_printf(t, "Changing Level 2 request to Level 1!");
} }
res = stm32l4_option_write(t, values, len, i2offset); res = stm32l4_option_write(t, values, len, i2offset, fpec_base);
} else { } else {
tc_printf(t, "usage: monitor option erase\n"); tc_printf(t, "usage: monitor option erase\n");
tc_printf(t, "usage: monitor option write <value> ...\n"); tc_printf(t, "usage: monitor option write <value> ...\n");
@ -780,8 +791,8 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[])
return false; return false;
} }
for (int i = 0; i < len; i ++) { for (int i = 0; i < len; i ++) {
uint32_t addr = L4_FPEC_BASE + i2offset[i]; uint32_t addr = fpec_base + i2offset[i];
val = target_mem_read32(t, L4_FPEC_BASE + i2offset[i]); val = target_mem_read32(t, fpec_base + i2offset[i]);
tc_printf(t, "0x%08X: 0x%08X\n", addr, val); tc_printf(t, "0x%08X: 0x%08X\n", addr, val);
} }
return true; return true;