Merge commit 'd594b42976e3b9640b64ef1cb2da3f74067930b8' into sam-update
# Conflicts: # README.md # src/platforms/common/cdcacm.c # src/target/adiv5_swdp.c
This commit is contained in:
commit
e174c5b503
2
HACKING
2
HACKING
@ -1 +1 @@
|
|||||||
See https://github.com/blacksphere/blackmagic/wiki/Hacking
|
See https://github.com/blackmagic-debug/blackmagic/wiki/Hacking
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
253
scripts/gdb.py
253
scripts/gdb.py
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;')
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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: */
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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))));
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user