diff --git a/HACKING b/HACKING index f53c89ef..8f8cf385 100644 --- a/HACKING +++ b/HACKING @@ -1 +1 @@ -See https://github.com/blacksphere/blackmagic/wiki/Hacking +See https://github.com/blackmagic-debug/blackmagic/wiki/Hacking diff --git a/scripts/bootprog.py b/scripts/bootprog.py index ab783259..5baf82b0 100755 --- a/scripts/bootprog.py +++ b/scripts/bootprog.py @@ -23,12 +23,12 @@ from time import sleep class stm32_boot: 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) # Turn on target device in SystemMemory boot mode self.serial.setDTR(1) - sleep(0.1); + sleep(0.1) self._sync() @@ -98,7 +98,6 @@ class stm32_boot: # Send data self._send(chr(len(data)-1) + data) self._checkack() - def write_protect(self, sectors): # Send WP cmd @@ -134,11 +133,11 @@ if __name__ == "__main__": from getopt import getopt if platform == "linux2": - print "\x1b\x5b\x48\x1b\x5b\x32\x4a" # clear terminal screen - print "STM32 SystemMemory Production Programmer -- version 1.1" - print "Copyright (C) 2011 Black Sphere Technologies" - print "License GPLv3+: GNU GPL version 3 or later " - print + print("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen + print("STM32 SystemMemory Production Programmer -- version 1.1") + print("Copyright (C) 2011 Black Sphere Technologies") + print("License GPLv3+: GNU GPL version 3 or later ") + print() dev = "COM1" if platform == "win32" else "/dev/ttyUSB0" baud = 115200 @@ -152,38 +151,38 @@ if __name__ == "__main__": progfile = args[0] except: - print "Usage %s [-d ] [-b ] [-a
] " % argv[0] - print "\t-d : Use target on interface (default: %s)" % dev - print "\t-b : Set device baudrate (default: %d)" % baud - print "\t-a : Set programming address (default: 0x%X)" % addr - print + print("Usage %s [-d ] [-b ] [-a
] " % argv[0]) + print("\t-d : Use target on interface (default: %s)" % dev) + print("\t-b : Set device baudrate (default: %d)" % baud) + print("\t-a : Set programming address (default: 0x%X)" % addr) + print() exit(-1) prog = open(progfile, "rb").read() boot = stm32_boot(dev, baud) 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.write_unprotect() - print "Erasing target device..." + print("Erasing target device...") boot.eraseall() addr = 0x8000000 while prog: - print ("Programming address 0x%08X..0x%08X...\r" % (addr, addr + min(len(prog), 255))), - stdout.flush(); + print("Programming address 0x%08X..0x%08X...\r" % (addr, addr + min(len(prog), 255)), end=' ') + stdout.flush() boot.write(addr, prog[:256]) addr += 256 prog = prog[256:] print - print "Enabling device protection..." + print("Enabling device protection...") boot.write_protect(range(0,2)) #boot.read_protect() - print "All operations completed." + print("All operations completed.") print diff --git a/scripts/gdb.py b/scripts/gdb.py index 286627c2..6c6e02d0 100644 --- a/scripts/gdb.py +++ b/scripts/gdb.py @@ -3,7 +3,7 @@ # gdb.py: Python module for low level GDB protocol implementation # Copyright (C) 2009 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 @@ -24,24 +24,18 @@ import struct import time def hexify(s): - """Convert a binary string into hex representation""" - ret = '' - for c in s: - ret += "%02X" % ord(c) - return ret + """Convert a bytes object into hex bytes representation""" + return s.hex().encode() def unhexify(s): - """Convert a hex string into binary representation""" - ret = '' - for i in range(0, len(s), 2): - ret += chr(int(s[i:i+2], 16)) - return ret + """Convert a hex-encoded bytes into bytes object""" + return bytes.fromhex(s.decode()) class FakeSocket: """Emulate socket functions send and recv on a file object""" def __init__(self, file): self.file = file - + def send(self, data): self.file.write(data) @@ -52,148 +46,186 @@ class Target: def __init__(self, sock): if "send" in dir(sock): self.sock = sock - else: + else: self.sock = FakeSocket(sock) + self.PacketSize=0x100 # default + def getpacket(self): """Return the first correctly received packet from GDB target""" while True: - while self.sock.recv(1) != '$': pass + while self.sock.recv(1) != b'$': + pass + csum = 0 - packet = '' + packet = [] # list-of-small-int while True: - c = self.sock.recv(1) - if c == '#': break + c, = self.sock.recv(1) + if c == ord('#'): + break - if c == '$': - packet = '' + if c == ord('$'): + packet = [] csum = 0 continue - if c == '}': - c = self.sock.recv(1) - csum += ord(c) + ord('}') - packet += chr(ord(c) ^ 0x20) - continue + if c == ord('}'): + c, = self.sock.recv(1) + csum += c + ord('}') + packet.append(c ^ 0x20) + continue - packet += c - csum += ord(c) + packet.append(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('+') - return packet + self.sock.send(b'-') + self.sock.send(b'+') + return bytes(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: - self.sock.send('$') - csum = 0 + out = [] + for c in packet: - if (c == '$') or (c == '#') or (c == '}'): - self.sock.send('}') - self.sock.send(chr(ord(c) ^ 0x20)) - csum += (ord(c) ^ 0x20) + ord('}') + if (c in b'$#}'): + out.append(ord('}')) + out.append(c ^ 0x20) else: - self.sock.send(c) - csum += ord(c) - self.sock.send('#') - self.sock.send("%02X" % (csum & 0xFF)) - if self.sock.recv(1) == '+': break + out.append(c) + + csum = sum(out) + outb = b'$'+bytes(out)+b'#%02X' % (csum & 0xff) + + self.sock.send(outb) + if self.sock.recv(1) == b'+': + break def monitor(self, cmd): """Send gdb "monitor" command to target""" + if type(cmd) == str: + cmd = cmd.encode() + ret = [] - self.putpacket("qRcmd," + hexify(cmd)) + self.putpacket(b"qRcmd," + hexify(cmd)) while True: s = self.getpacket() - if s == '': return None - if s == 'OK': return ret - if s.startswith('O'): ret.append(unhexify(s[1:])) + + if s == b'': + return None + if s == b'OK': + return ret + if s.startswith(b'O'): + ret.append(unhexify(s[1:])) else: - raise Exception('Invalid GDB stub response') + raise Exception('Invalid GDB stub response %r'%s.decode()) def attach(self, pid): """Attach to target process (gdb "attach" command)""" - self.putpacket("vAttach;%08X" % pid) + self.putpacket(b"vAttach;%08X" % pid) 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) def detach(self): """Detach from target process (gdb "detach" command)""" - self.putpacket("D") - if self.getpacket() != 'OK': + self.putpacket(b"D") + if self.getpacket() != b'OK': raise Exception("Failed to detach from remote process") def reset(self): """Reset the target system""" - self.putpacket("r") + self.putpacket(b"r") def read_mem(self, addr, length): """Read length bytes from target at address addr""" - self.putpacket("m%08X,%08X" % (addr, length)) - reply = self.getpacket() - if (len(reply) == 0) or (reply[0] == 'E'): - raise Exception('Error reading memory at 0x%08X' % addr) - try: - data = unhexify(reply) - except Excpetion: - raise Exception('Invalid response to memory read packet: %r' % reply) - return data - + ret = b'' + while length: + # print "Read" + packlen = min(length,self.PacketSize//2) + self.putpacket(b"m%08X,%08X" % (addr, packlen)) + reply = self.getpacket() + if (reply == b'') or (reply[:1] == b'E'): + raise Exception('Error reading memory at 0x%08X' % addr) + 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): """Write data to target at address addr""" - self.putpacket("X%08X,%08X:%s" % (addr, len(data), data)) - if self.getpacket() != 'OK': - raise Exception('Error writing to memory at 0x%08X' % addr) + data = bytes(data) + + 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): """Read target core registers""" - self.putpacket("g") + self.putpacket(b"g") 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) try: data = unhexify(reply) - except Excpetion: + except Exception: 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): """Write target core registers""" data = struct.pack("=%dL" % len(regs), *regs) - self.putpacket("G" + hexify(data)) - if self.getpacket() != 'OK': + self.putpacket(b"G" + hexify(data)) + if self.getpacket() != b'OK': raise Exception('Error writing to target core registers') def memmap_read(self): """Read the XML memory map from target""" offset = 0 - ret = '' + ret = b'' 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() - if (reply[0] == 'm') or (reply[0] == 'l'): + if (reply[0] in b'ml'): offset += len(reply) - 1 ret += reply[1:] 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): """Resume target execution""" - self.putpacket("c") + self.putpacket(b'c') def interrupt(self): """Interrupt target execution""" - self.sock.send("\x03") + self.sock.send(b'\x03') def run_stub(self, stub, address, *args): """Execute a binary stub at address, passing args in core registers.""" @@ -205,11 +237,19 @@ class Target: regs[15] = address self.write_regs(*regs) self.resume() - reply = self.getpacket() + reply = None while not reply: reply = self.getpacket() - if not reply.startswith("T05"): - raise Exception("Invalid stop response: %r" % reply) + if not reply.startswith(b"T05"): + 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: def __init__(self, target, offset, length, blocksize): @@ -217,27 +257,30 @@ class Target: self.offset = offset self.length = length 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): - assert ((offset >= self.offset) and + assert type(data)==bytes + + assert ((offset >= self.offset) and (offset + len(data) <= self.offset + self.length)) while data: - index = (offset - self.offset) / self.blocksize + index = (offset - self.offset) // self.blocksize bloffset = (offset - self.offset) % self.blocksize bldata = data[:self.blocksize-bloffset] data = data[len(bldata):]; offset += len(bldata) 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] = (self.blocks[index][:bloffset] + bldata + + self.blocks[index] = bytes(0xff for i in range(self.blocksize)) + self.blocks[index] = (self.blocks[index][:bloffset] + bldata + self.blocks[index][bloffset+len(bldata):]) def commit(self, progress_cb=None): totalblocks = 0 for b in self.blocks: - if b is not None: totalblocks += 1 - + if b is not None: + totalblocks += 1 + block = 0 for i in range(len(self.blocks)): block += 1 @@ -247,35 +290,37 @@ class Target: # Erase the block data = self.blocks[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) - self.target.putpacket("vFlashErase:%08X,%08X" % + self.target.putpacket(b"vFlashErase:%08X,%08X" % (self.offset + self.blocksize*i, self.blocksize)) - if self.target.getpacket() != 'OK': + if self.target.getpacket() != b'OK': raise Exception("Failed to erase flash") while data: d = data[0:980] data = data[len(d):] #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) - if self.target.getpacket() != 'OK': + if self.target.getpacket() != b'OK': raise Exception("Failed to write flash") - - self.target.putpacket("vFlashDone") - if self.target.getpacket() != 'OK': + + self.target.putpacket(b"vFlashDone") + if self.target.getpacket() != b'OK': 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): self.mem = [] xmldom = parseString(self.memmap_read()) - + for memrange in xmldom.getElementsByTagName("memory"): - if memrange.getAttribute("type") != "flash": continue + if memrange.getAttribute("type") != "flash": + continue offset = eval(memrange.getAttribute("start")) length = eval(memrange.getAttribute("length")) for property in memrange.getElementsByTagName("property"): @@ -297,5 +342,3 @@ class Target: def flash_commit(self, progress_cb=None): for m in self.mem: m.commit(progress_cb) - - diff --git a/scripts/get_openocd_nrf51_ids.py b/scripts/get_openocd_nrf51_ids.py index 5c90a296..33bdd60e 100755 --- a/scripts/get_openocd_nrf51_ids.py +++ b/scripts/get_openocd_nrf51_ids.py @@ -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(): def __repr__(self): 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={} -specs=[] -spec=Spec() -for line in fd.read().split('\n'): - m=re.search('/\*(.*)\*/',line) +specdict = {} +specs = [] +spec = Spec() +for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"): + m = re.search('/\*(.*)\*/',line) if m: 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: - spec.hwid=int(m.group(1),base=0) - m=re.search('.variant.*=\s*"(.*)",',line) - if m: - spec.variant=m.group(1) - m=re.search('.build_code.*=\s*"(.*)",',line) - if m: - spec.build_code=m.group(1) - m=re.search('.flash_size_kb.*=\s*([0-9]*),',line) - 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.hwid = int(m.group(1), base=0) + spec.variant = m.group(3) + spec.build_code = m.group(4) + spec.flash_size_kb = int(m.group(5), 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 - nicecomment =lastcomment.strip().replace('IC ','').replace('Devices ','').replace('.','') - spec.comment=nicecomment + nicecomment = lastcomment.strip().replace('IC ','').replace('Devices ','').replace('.','') + spec.comment = nicecomment specdict.setdefault((ram,flash),[]).append(spec) specs.append(spec) spec=Spec() -for (ram,flash),specs in specdict.iteritems(): +for (ram,flash),specs in specdict.items(): specs.sort(key=lambda x:x.hwid) for spec in specs: - print "\tcase",spec - print '\t\tt->driver = "Nordic nRF51";' - 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, NRF51_UICR, 0x100, 0x100);' - print '\t\ttarget_add_commands(t, nrf51_cmd_list, "nRF51");' - print '\t\treturn true;' + print("\tcase",spec) + print('\t\tt->driver = "Nordic nRF51";') + 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, NRF51_UICR, 0x100, 0x100);') + print('\t\ttarget_add_commands(t, nrf51_cmd_list, "nRF51");') + print('\t\treturn true;') diff --git a/scripts/hexprog.py b/scripts/hexprog.py index ccfb43c5..43f9693e 100755 --- a/scripts/hexprog.py +++ b/scripts/hexprog.py @@ -3,7 +3,7 @@ # 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 @@ -31,15 +31,16 @@ def flash_write_hex(target, hexfile, progress_cb=None): f = open(hexfile) addrhi = 0 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) addrlo = int(line[3:7], 16) rectype = int(line[7:9], 16); - if sum(ord(x) for x in gdb.unhexify(line[1:11+reclen*2])) & 0xff != 0: - raise Exception("Checksum error in hex file") + 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 = gdb.unhexify(line[9:9+reclen*2]) + data = bytes.fromhex(line[9:9+reclen*2]) target.flash_write_prepare(addr, data) pass elif rectype == 4: # High address record @@ -48,16 +49,16 @@ def flash_write_hex(target, hexfile, progress_cb=None): elif rectype == 5: # Entry record pass elif rectype == 1: # End of file record - break + break else: raise Exception("Invalid record in hex file") try: target.flash_commit(progress_cb) except: - print "Flash write failed! Is device protected?\n" + print("Flash write failed! Is device protected?\n") exit(-1) - + if __name__ == "__main__": from serial import Serial, SerialException @@ -67,8 +68,8 @@ if __name__ == "__main__": if platform == "linux2": 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("Copyright (C) 2011 Black Sphere Technologies") + print("License GPLv3+: GNU GPL version 3 or later ") print("") dev = "COM1" if platform == "win32" else "/dev/ttyACM0" @@ -80,13 +81,20 @@ if __name__ == "__main__": 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() + 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: @@ -101,39 +109,44 @@ if __name__ == "__main__": exit(-1) try: - s = Serial(dev, baud, timeout=3) - s.setDTR(1) - while s.read(1024): - pass + s = Serial(dev) #, baud, timeout=0.1) + #s.setDTR(1) + #s.flushInput() + + #while s.read(1024): + # pass target = gdb.Target(s) - - except SerialException, e: + + 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, - except SerialException, e: + 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 + #except: pass - print "Target device scan:" + print("Target device scan:") targetlist = None r = target.monitor(scan) - for s in r: - print s, - print + for s in r: + print(s.decode(), end=' ') + print() r = target.monitor("targets") - for s in r: - if s.startswith("No. Att Driver"): targetlist = [] + for s in r: + if s.startswith(b"No. Att Driver"): + targetlist = [] try: - if type(targetlist) is list: + if type(targetlist) is list: targetlist.append(int(s[:2])) - except: pass + except: + pass #if not targetlist: # 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)) def progress(percent): - print ("Progress: %d%%\r" % percent), + print("Progress: %d%%\r" % percent, end=' ') stdout.flush() print("Programming target") @@ -179,4 +192,3 @@ if __name__ == "__main__": target.detach() print("\nAll operations complete!\n") - diff --git a/scripts/stm32_mem.py b/scripts/stm32_mem.py index 51a8537b..9f47df31 100755 --- a/scripts/stm32_mem.py +++ b/scripts/stm32_mem.py @@ -18,7 +18,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from __future__ import print_function from time import sleep import struct import os @@ -72,7 +71,7 @@ def stm32_read(dev): return data def stm32_manifest(dev): - dev.download(0, "") + dev.download(0, b"") while True: try: status = dev.get_status() @@ -138,7 +137,7 @@ def stm32_scan(args, test): product = dfudev.handle.getString(dfudev.dev.iProduct, 96).decode('utf8') serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30).decode('utf8') 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 else: if man == "Black Sphere Technologies": @@ -236,7 +235,7 @@ if __name__ == "__main__": bin = file.read() len = len(bin) addr = start - print("-") + print("\n-") while bin: try: stm32_set_address(dfudev, addr) @@ -251,7 +250,7 @@ if __name__ == "__main__": else : size = len if bin[:size] != bytearray(data[:size]) : - print ("\nMitmatch in block at 0x%08X" % addr) + print ("\nMismatch in block at 0x%08X" % addr) break; bin = bin[1024:] addr += 1024 diff --git a/src/crc32.c b/src/crc32.c index a56b9944..8ce25dff 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -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 */ uint8_t bytes[0x1000]; - uint32_t start_time = platform_time_ms(); #else uint8_t bytes[128]; +#endif +#if defined(ENABLE_DEBUG) + uint32_t start_time = platform_time_ms(); #endif uint32_t last_time = platform_time_ms(); while (len) { diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index 1457f1d0..6f7ff7b4 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -24,6 +24,18 @@ * field firmware upgrade. * * 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" @@ -42,7 +54,15 @@ #include #include -#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; @@ -78,7 +98,7 @@ static const struct usb_device_descriptor dev_desc = { static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, + .bEndpointAddress = (CDCACM_GDB_ENDPOINT + 1) | USB_REQ_TYPE_IN, .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, .wMaxPacketSize = 16, .bInterval = 255, @@ -87,14 +107,14 @@ static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, + .bEndpointAddress = CDCACM_GDB_ENDPOINT, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = CDCACM_PACKET_SIZE, .bInterval = 1, }, { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x81, + .bEndpointAddress = CDCACM_GDB_ENDPOINT | USB_REQ_TYPE_IN, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = CDCACM_PACKET_SIZE, .bInterval = 1, @@ -118,7 +138,7 @@ static const struct { .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, .bmCapabilities = 0, - .bDataInterface = 1, + .bDataInterface = GDB_IF_NO + 1, }, .acm = { .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), @@ -130,8 +150,8 @@ static const struct { .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 0, - .bSubordinateInterface0 = 1, + .bControlInterface = GDB_IF_NO, + .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[] = {{ .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, + .bInterfaceNumber = GDB_IF_NO + 1, .bAlternateSetting = 0, .bNumEndpoints = 2, .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 = { .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 0, + .bFirstInterface = GDB_IF_NO, .bInterfaceCount = 2, .bFunctionClass = USB_CLASS_CDC, .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[] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x84, + .bEndpointAddress = (CDCACM_UART_ENDPOINT + 1) | USB_REQ_TYPE_IN, .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, .wMaxPacketSize = 16, .bInterval = 255, @@ -190,14 +210,14 @@ static const struct usb_endpoint_descriptor uart_comm_endp[] = {{ static const struct usb_endpoint_descriptor uart_data_endp[] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x03, + .bEndpointAddress = CDCACM_UART_ENDPOINT, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = CDCACM_PACKET_SIZE / 2, .bInterval = 1, }, { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x83, + .bEndpointAddress = CDCACM_UART_ENDPOINT | USB_REQ_TYPE_IN, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = CDCACM_PACKET_SIZE, .bInterval = 1, @@ -221,7 +241,7 @@ static const struct { .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, .bmCapabilities = 0, - .bDataInterface = 3, + .bDataInterface = UART_IF_NO + 1, }, .acm = { .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), @@ -233,15 +253,15 @@ static const struct { .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), .bDescriptorType = CS_INTERFACE, .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 2, - .bSubordinateInterface0 = 3, + .bControlInterface = UART_IF_NO, + .bSubordinateInterface0 = UART_IF_NO + 1, } }; static const struct usb_interface_descriptor uart_comm_iface[] = {{ .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 2, + .bInterfaceNumber = UART_IF_NO, .bAlternateSetting = 0, .bNumEndpoints = 1, .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[] = {{ .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 3, + .bInterfaceNumber = UART_IF_NO + 1, .bAlternateSetting = 0, .bNumEndpoints = 2, .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 = { .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 2, + .bFirstInterface = UART_IF_NO, .bInterfaceCount = 2, .bFunctionClass = USB_CLASS_CDC, .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 = { .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 4, + .bFirstInterface = DFU_IF_NO, .bInterfaceCount = 1, .bFunctionClass = 0xFE, .bFunctionSubClass = 1, @@ -319,7 +339,7 @@ static const struct usb_iface_assoc_descriptor dfu_assoc = { static const struct usb_endpoint_descriptor trace_endp[] = {{ .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x85, + .bEndpointAddress = TRACE_ENDPOINT | USB_REQ_TYPE_IN, .bmAttributes = USB_ENDPOINT_ATTR_BULK, .wMaxPacketSize = 64, .bInterval = 0, @@ -328,7 +348,7 @@ static const struct usb_endpoint_descriptor trace_endp[] = {{ const struct usb_interface_descriptor trace_iface = { .bLength = USB_DT_INTERFACE_SIZE, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 5, + .bInterfaceNumber = TRACE_IF_NO, .bAlternateSetting = 0, .bNumEndpoints = 1, .bInterfaceClass = 0xFF, @@ -342,7 +362,7 @@ const struct usb_interface_descriptor trace_iface = { static const struct usb_iface_assoc_descriptor trace_assoc = { .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 5, + .bFirstInterface = TRACE_IF_NO, .bInterfaceCount = 1, .bFunctionClass = 0xFF, .bFunctionSubClass = 0xFF, @@ -381,11 +401,7 @@ static const struct usb_config_descriptor config = { .bLength = USB_DT_CONFIGURATION_SIZE, .bDescriptorType = USB_DT_CONFIGURATION, .wTotalLength = 0, -#if defined(PLATFORM_HAS_TRACESWO) - .bNumInterfaces = 6, -#else - .bNumInterfaces = 5, -#endif + .bNumInterfaces = TOTAL_INTERFACES, .bConfigurationValue = 1, .iConfiguration = 0, .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: cdcacm_set_modem_state(dev, req->wIndex, true, true); /* Ignore if not for GDB interface */ - if(req->wIndex != 0) + if(req->wIndex != GDB_IF_NO) return USBD_REQ_HANDLED; 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; switch(req->wIndex) { - case 2: + case UART_IF_NO: usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf); return USBD_REQ_HANDLED; - case 0: + case GDB_IF_NO: return USBD_REQ_HANDLED; /* Ignore on GDB Port */ default: 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; buf[8] = (dsr ? 2 : 0) | (dcd ? 1 : 0); buf[9] = 0; + /* FIXME: Remove magic numbers */ 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 */ #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); #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); #endif - usbd_ep_setup(dev, 0x81, 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 | USB_REQ_TYPE_IN, + USB_ENDPOINT_ATTR_BULK, CDCACM_PACKET_SIZE, NULL); + usbd_ep_setup(dev, (CDCACM_GDB_ENDPOINT + 1) | USB_REQ_TYPE_IN, + USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); /* 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); - 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); - 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) /* 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); #endif @@ -541,8 +561,8 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) /* Notify the host that DCD is asserted. * Allows the use of /dev/tty* devices on *BSD/MacOS */ - cdcacm_set_modem_state(dev, 0, true, true); - cdcacm_set_modem_state(dev, 2, true, true); + cdcacm_set_modem_state(dev, GDB_IF_NO, true, true); + cdcacm_set_modem_state(dev, UART_IF_NO, true, true); } /* We need a special large control buffer for this device: */ diff --git a/src/platforms/common/cdcacm.h b/src/platforms/common/cdcacm.h index f64399d2..7cdfe238 100644 --- a/src/platforms/common/cdcacm.h +++ b/src/platforms/common/cdcacm.h @@ -34,6 +34,7 @@ #define CDCACM_GDB_ENDPOINT 1 #define CDCACM_UART_ENDPOINT 3 +#define TRACE_ENDPOINT 5 extern usbd_device *usbdev; diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index d2949320..21ed9542 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -169,7 +169,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) continue; } /* 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; } libusb_device_handle *handle; diff --git a/src/platforms/hosted/cmsis_dap.h b/src/platforms/hosted/cmsis_dap.h index ed5c6c78..cd834d8e 100644 --- a/src/platforms/hosted/cmsis_dap.h +++ b/src/platforms/hosted/cmsis_dap.h @@ -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_jtag_dp_init(ADIv5_DP_t *dp) {return -1;} void dap_swd_configure(uint8_t cfg) {}; -void dap_srst_set_val(assert) {}; +void dap_srst_set_val(bool assert) {}; # pragma GCC diagnostic pop #endif diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 88e16a0c..7a438da1 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -290,7 +290,6 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->opt_targetid = strtol(optarg, NULL, 0); break; case 'M': - opt->opt_mode = BMP_MODE_MONITOR; if (optarg) opt->opt_monitor = optarg; break; @@ -321,7 +320,11 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) if (opt->opt_mode == BMP_MODE_DEBUG) opt->opt_mode = BMP_MODE_FLASH_WRITE; 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 */ if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) || (opt->opt_mode == BMP_MODE_SWJ_TEST) || @@ -448,10 +451,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) default: 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) || (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) /* restrict to size given on command line */ 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) { 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, 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, map.data, map.size); /* Buffered write cares for padding*/ + if (!flashed) + flashed = target_flash_done(t); if (flashed) { DEBUG_WARN("Flashing failed!\n"); res = -1; @@ -518,7 +524,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) DEBUG_INFO("Success!\n"); } } - target_flash_done(t); uint32_t end_time = platform_time_ms(); DEBUG_WARN("Flash Write succeeded for %d bytes, %8.3f kiB/s\n", (int)map.size, (((map.size * 1.0)/(end_time - start_time)))); diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 403ecc99..7d167093 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -398,7 +398,7 @@ static uint32_t cortexm_initial_halt(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(); #endif uint32_t dhcsr = cortexm_initial_halt(ap); @@ -834,9 +834,15 @@ void adiv5_dp_init(ADIv5_DP_t *dp) adiv5_ap_unref(ap); } /* We halted at least CortexM for Romtable scan. - * Release the devices now. Attach() will halt them again.*/ - for (target *t = target_list; t; t = t->next) - target_halt_resume(t, false); + * With connect under reset, keep the devices halted. + * Otherwise, release the devices now. + * 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); } diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 5ce3a3c6..2288063e 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -471,8 +471,6 @@ bool cortexm_probe(ADIv5_AP_t *ap) PROBE(lpc17xx_probe); } #undef PROBE - /* Restart the CortexM we stopped for Romtable scan. Allow pure debug.*/ - target_halt_resume(t, 0); return true; } @@ -1217,8 +1215,8 @@ static int cortexm_hostio_request(target *t) t->tc->interrupted = false; target_regs_read(t, arm_regs); - target_mem_read(t, params, arm_regs[1], sizeof(params)); uint32_t syscall = arm_regs[0]; + if (syscall != SYS_EXIT) target_mem_read(t, params, arm_regs[1], sizeof(params)); int32_t ret = 0; DEBUG_INFO("syscall 0"PRIx32"%"PRIx32" (%"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32")\n", @@ -1608,7 +1606,7 @@ static int cortexm_hostio_request(target *t) #endif 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); break; diff --git a/src/target/samd.c b/src/target/samd.c index 02879fbd..f6134088 100644 --- a/src/target/samd.c +++ b/src/target/samd.c @@ -22,6 +22,7 @@ * programming. * * Tested with + * * SAMD09D14A (rev B) * * SAMD20E17A (rev C) * * SAMD20J18A (rev B) * * SAMD21J18A (rev B) @@ -128,7 +129,7 @@ const struct command_s samd_cmd_list[] = { #define SAMD_STATUSB_PROT (1 << 16) /* Device Identification Register (DID) */ -#define SAMD_DID_MASK 0xFF3C0000 +#define SAMD_DID_MASK 0xFF380000 #define SAMD_DID_CONST_VALUE 0x10000000 #define SAMD_DID_DEVSEL_MASK 0xFF #define SAMD_DID_DEVSEL_POS 0 @@ -341,6 +342,8 @@ struct samd_descr { uint8_t series; char revision; char pin; + uint32_t ram_size; + uint32_t flash_size; uint8_t mem; char variant; char package[3]; @@ -351,6 +354,8 @@ struct samd_descr samd_parse_device_id(uint32_t did) uint8_t i = 0; const struct samd_part *parts = samd_d21_parts; memset(samd.package, 0, 3); + samd.ram_size = 0x8000; + samd.flash_size = 0x40000; uint8_t family = (did >> SAMD_DID_FAMILY_POS) & SAMD_DID_FAMILY_MASK; @@ -380,6 +385,7 @@ struct samd_descr samd_parse_device_id(uint32_t did) } break; case 3: samd.series = 11; break; + case 4: samd.series = 9; break; default: samd.series = 0; break; } /* Revision */ @@ -419,6 +425,23 @@ struct samd_descr samd_parse_device_id(uint32_t did) samd.mem = 14 - (devsel % 3); samd.variant = 'A'; 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; @@ -475,14 +498,14 @@ bool samd_probe(target *t) /* Part String */ if (protected) { 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.series, samd.pin, samd.mem, samd.variant, samd.package, samd.revision); } else { 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.series, samd.pin, samd.mem, samd.variant, @@ -513,8 +536,8 @@ bool samd_probe(target *t) t->attach = samd_protected_attach; } - target_add_ram(t, 0x20000000, 0x8000); - samd_add_flash(t, 0x00000000, 0x40000); + target_add_ram(t, 0x20000000, samd.ram_size); + samd_add_flash(t, 0x00000000, samd.flash_size); target_add_commands(t, samd_cmd_list, "SAMD"); /* If we're not in reset here */ diff --git a/src/target/stm32g0.c b/src/target/stm32g0.c index d5637901..43c58c30 100644 --- a/src/target/stm32g0.c +++ b/src/target/stm32g0.c @@ -52,6 +52,9 @@ #define FLASH_MEMORY_SIZE 0x1FFF75E0 #define FLASH_PAGE_SIZE 0x800 #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_G05_6 (64U * 1024U) // 64 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->erase = stm32g0_flash_erase; f->write = stm32g0_flash_write; - f->buf_size = FLASH_PAGE_SIZE; + f->buf_size = blocksize; f->erased = 0xFF; target_add_flash(t, f); } @@ -249,6 +252,9 @@ bool stm32g0_probe(target *t) priv_storage->irreversible_enabled = false; t->target_storage = (void*)priv_storage; + /* OTP Flash area */ + stm32g0_add_flash(t, FLASH_OTP_START, FLASH_OTP_SIZE, FLASH_OTP_BLOCKSIZE); + return true; } @@ -311,6 +317,7 @@ static void stm32g0_flash_lock(target *t) /* * 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, size_t len) @@ -328,11 +335,6 @@ static int stm32g0_flash_erase(struct target_flash *f, target_addr addr, if (len == (size_t)0U) 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 */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY_MASK) { 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 */ 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); do { @@ -392,12 +402,20 @@ exit_cleanup: * The SR is supposed to be ready and free of any error. * After a successful programming, the EMPTY bit is cleared to allow rebooting * 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, const void *src, size_t len) { target *t = f->t; 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); diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index cdd9fdf2..b0f7f81d 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -671,8 +671,12 @@ static const uint8_t g4_i2offset[11] = { 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( - 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"); stm32l4_flash_unlock(t); @@ -682,7 +686,7 @@ static bool stm32l4_option_write( if(target_check_error(t)) return true; 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); while (stm32l4_flash_read32(t, FLASH_SR) & FLASH_SR_BSY) 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"); return false; } - if (t->idcode == ID_STM32WLXX) { - tc_printf(t, "STM32WLxx options not implemented!\n"); - return false; - } if (t->idcode == ID_STM32WBXX) { tc_printf(t, "STM32WBxx options not implemented!\n"); return false; @@ -733,12 +733,17 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[]) 0xFFFFFFFF, 0xFFFFFFFF, 0xFF00FFFF, 0xFF00FFFF, 0xFF00FF00 }; + static const uint32_t wl_values[11] = { + 0x3FEFF0AA, 0xFFFFFFFF, 0xFFFFFF00, 0xFF80FFFF, 0xFF80FFFF, 0xFFFFFFFF, + 0xFFFFFF00 + }; + uint32_t val; uint32_t values[11] = { 0xFFEFF8AA, 0xFFFFFFFF, 0, 0x000000ff, 0x000000ff, 0xffffffff, 0, 0x000000ff, 0x000000ff }; int len; bool res = false; - + uint32_t fpec_base = L4_FPEC_BASE; const uint8_t *i2offset = l4_i2offset; if (t->idcode == ID_STM32L43) {/* L43x */ len = 5; @@ -753,24 +758,30 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[]) len = 6; for (int i = 0; i < len; 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 { len = 9; } 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")) { int i; for (i = 2; i < argc; i++) values[i - 2] = strtoul(argv[i], NULL, 0); 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); } if ((values[0] & 0xff) == 0xCC) { values[0]++; 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 { tc_printf(t, "usage: monitor option erase\n"); tc_printf(t, "usage: monitor option write ...\n"); @@ -780,8 +791,8 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[]) return false; } for (int i = 0; i < len; i ++) { - uint32_t addr = L4_FPEC_BASE + i2offset[i]; - val = target_mem_read32(t, L4_FPEC_BASE + i2offset[i]); + uint32_t addr = fpec_base + i2offset[i]; + val = target_mem_read32(t, fpec_base + i2offset[i]); tc_printf(t, "0x%08X: 0x%08X\n", addr, val); } return true;