Merge commit '7d2afcff06f1ccd9fe583d562ddd81e04a17e166' into sam-update

This commit is contained in:
Jason Kotzin 2022-08-10 20:40:24 -07:00
commit b4af0f5145
24 changed files with 384 additions and 282 deletions

36
.github/workflows/build-and-upload.yml vendored Normal file
View File

@ -0,0 +1,36 @@
name: build and upload
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Use embedded toolchain
- uses: numworks/setup-arm-toolchain@2020-q4
# Runs a single command using the runners shell
- name: Build
run: make
- name: Archive firmware build artifacts as a zip
uses: actions/upload-artifact@v2.2.4
with:
name: blackmagic-firmware.zip
path: src/blackmagic*
if-no-files-found: error

29
.github/workflows/build-pr.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: build PR
# Controls when the workflow will run
on:
# Triggers the workflow on push or pull request events but only for the main branch
pull_request:
branches: [ master ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
# Use embedded toolchain
- uses: numworks/setup-arm-toolchain@2020-q4
# Runs a single command using the runners shell
- name: Build
run: make

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# #
# bootprog.py: STM32 SystemMemory Production Programmer -- version 1.1 # bootprog.py: STM32 SystemMemory Production Programmer -- version 1.1
# Copyright (C) 2011 Black Sphere Technologies # Copyright (C) 2011 Black Sphere Technologies
@ -34,95 +34,93 @@ class stm32_boot:
def _sync(self): def _sync(self):
# Send sync byte # Send sync byte
#print "sending sync byte" #print("sending sync byte")
self.serial.write("\x7F") self.serial.write(bytes((0x7F,)))
self._checkack() self._checkack()
def _sendcmd(self, cmd): def _sendcmd(self, cmd):
if type(cmd) == int: cmd = bytes((cmd, cmd ^ 0xff))
cmd = chr(cmd) #print("sendcmd:", repr(cmd))
cmd += chr(ord(cmd) ^ 0xff)
#print "sendcmd:", repr(cmd)
self.serial.write(cmd) self.serial.write(cmd)
def _send(self, data): def _send(self, data):
csum = 0 csum = 0
for c in data: csum ^= ord(c) for c in data: csum ^= c
data = data + chr(csum) data = data + bytes((csum,))
#print "sending:", repr(data) #print("sending:", repr(data))
self.serial.write(data) self.serial.write(data)
def _checkack(self): def _checkack(self):
ACK = "\x79" ACK = bytes((0x79,))
b = self.serial.read(1) b = self.serial.read(1)
if b != ACK: raise Exception("Invalid ack: %r" % b) if b != ACK: raise Exception("Invalid ack: %r" % b)
#print "got ack!" #print("got ack!")
def get(self): def get(self):
self._sendcmd("\x00") self._sendcmd(0x00)
self._checkack() self._checkack()
num = ord(self.serial.read(1)) num = self.serial.read(1)[0]
data = self.serial.read(num+1) data = self.serial.read(num+1)
self._checkack() self._checkack()
return data return data
def eraseall(self): def eraseall(self):
# Send erase cmd # Send erase cmd
self._sendcmd("\x43") self._sendcmd(0x43)
self._checkack() self._checkack()
# Global erase # Global erase
self._sendcmd("\xff") self._sendcmd(0xff)
self._checkack() self._checkack()
def read(self, addr, len): def read(self, addr, len):
# Send read cmd # Send read cmd
self._sendcmd("\x11") self._sendcmd(0x11)
self._checkack() self._checkack()
# Send address # Send address
self._send(struct.pack(">L", addr)) self._send(struct.pack(">L", addr))
self._checkack() self._checkack()
# Send length # Send length
self._sendcmd(chr(len-1)) self._sendcmd(len-1)
self._checkack() self._checkack()
return self.serial.read(len) return self.serial.read(len)
def write(self, addr, data): def write(self, addr, data):
# Send write cmd # Send write cmd
self._sendcmd("\x31") self._sendcmd(0x31)
self._checkack() self._checkack()
# Send address # Send address
self._send(struct.pack(">L", addr)) self._send(struct.pack(">L", addr))
self._checkack() self._checkack()
# Send data # Send data
self._send(chr(len(data)-1) + data) self._send(bytes((len(data)-1,)) + data)
self._checkack() self._checkack()
def write_protect(self, sectors): def write_protect(self, sectors):
# Send WP cmd # Send WP cmd
self._sendcmd("\x63") self._sendcmd(0x63)
self._checkack() self._checkack()
# Send sector list # Send sector list
self._send(chr(len(sectors)-1) + "".join(chr(i) for i in sectors)) self._send(bytes((len(sectors)-1,)) + bytes(sectors))
self._checkack() self._checkack()
# Resync after system reset # Resync after system reset
self._sync() self._sync()
def write_unprotect(self): def write_unprotect(self):
self._sendcmd("\x73") self._sendcmd(0x73)
self._checkack() self._checkack()
self._checkack() self._checkack()
self._sync() self._sync()
def read_protect(self): def read_protect(self):
self._sendcmd("\x82") self._sendcmd(0x82)
self._checkack() self._checkack()
self._checkack() self._checkack()
self._sync() self._sync()
def read_unprotect(self): def read_unprotect(self):
self._sendcmd("\x92") self._sendcmd(0x92)
self._checkack() self._checkack()
self._checkack() self._checkack()
self._sync() self._sync()
@ -132,7 +130,7 @@ if __name__ == "__main__":
from sys import stdout, argv, platform from sys import stdout, argv, platform
from getopt import getopt from getopt import getopt
if platform == "linux2": if platform == "linux":
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")
@ -162,7 +160,7 @@ if __name__ == "__main__":
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" % (cmds[0] >> 4, cmds[0] % 0xf))
print("Removing device protection...") print("Removing device protection...")
boot.read_unprotect() boot.read_unprotect()

View File

@ -1,19 +1,13 @@
#!/usr/bin/env python #!/usr/bin/env python3
# Written by Antonio Galea - 2010/11/18 # Written by Antonio Galea - 2010/11/18
# Distributed under Gnu LGPL 3.0 # Distributed under Gnu LGPL 3.0
# see http://www.gnu.org/licenses/lgpl-3.0.txt # see http://www.gnu.org/licenses/lgpl-3.0.txt
#
# Add support for Python 3 inspired by script found in Bitcraze repository
import sys,struct,zlib,os import sys,struct,zlib,os
from optparse import OptionParser from optparse import OptionParser
from intelhex import IntelHex from intelhex import IntelHex
python3 = False
if (sys.version_info > (3, 0)):
python3 = True
DEFAULT_DEVICE="0x0483:0xdf11" DEFAULT_DEVICE="0x0483:0xdf11"
def named(tuple,names): def named(tuple,names):
@ -22,7 +16,7 @@ def consume(fmt,data,names):
n = struct.calcsize(fmt) n = struct.calcsize(fmt)
return named(struct.unpack(fmt,data[:n]),names),data[n:] return named(struct.unpack(fmt,data[:n]),names),data[n:]
def cstring(string): def cstring(string):
return string.split('\0',1)[0] return string.split(b'\0',1)[0]
def compute_crc(data): def compute_crc(data):
return 0xFFFFFFFF & -zlib.crc32(data) -1 return 0xFFFFFFFF & -zlib.crc32(data) -1
@ -31,15 +25,15 @@ def parse(file,dump_images=False):
data = open(file,'rb').read() data = open(file,'rb').read()
crc = compute_crc(data[:-4]) crc = compute_crc(data[:-4])
prefix, data = consume('<5sBIB',data,'signature version size targets') prefix, data = consume('<5sBIB',data,'signature version size targets')
print('%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix) print('%(signature)r v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix)
for t in range(prefix['targets']): for t in range(prefix['targets']):
tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements')
tprefix['num'] = t tprefix['num'] = t
if tprefix['named']: if tprefix['named']:
tprefix['name'] = cstring(tprefix['name']) tprefix['name'] = cstring(tprefix['name'])
else: else:
tprefix['name'] = '' tprefix['name'] = b''
print('%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix) print('%(signature)r %(num)d, alt setting: %(altsetting)r, name: %(name)r, size: %(size)d, elements: %(elements)d' % tprefix)
tsize = tprefix['size'] tsize = tprefix['size']
target, data = data[:tsize], data[tsize:] target, data = data[:tsize], data[tsize:]
for e in range(tprefix['elements']): for e in range(tprefix['elements']):
@ -55,7 +49,7 @@ def parse(file,dump_images=False):
if len(target): if len(target):
print("target %d: PARSE ERROR" % t) print("target %d: PARSE ERROR" % t)
suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc')
print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix) print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)r, %(len)d, 0x%(crc)08x' % suffix)
if crc != suffix['crc']: if crc != suffix['crc']:
print("CRC ERROR: computed crc32 is 0x%08x" % crc) print("CRC ERROR: computed crc32 is 0x%08x" % crc)
data = data[16:] data = data[16:]
@ -63,30 +57,20 @@ def parse(file,dump_images=False):
print("PARSE ERROR") print("PARSE ERROR")
def build(file,targets,device=DEFAULT_DEVICE): def build(file,targets,device=DEFAULT_DEVICE):
data = '' data = b''
if (python3):
data = b''
for t,target in enumerate(targets): for t,target in enumerate(targets):
tdata = '' tdata = b''
if (python3):
tdata = b''
for image in target: for image in target:
tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data']
trgt = 'Target' trgt = b'Target'
st = 'ST...' st = b'ST...'
if (python3):
trgt = b'Target'
st = b'ST...'
tdata = struct.pack('<6sBI255s2I',trgt,0,1,st,len(tdata),len(target)) + tdata tdata = struct.pack('<6sBI255s2I',trgt,0,1,st,len(tdata),len(target)) + tdata
data += tdata data += tdata
dfu_se = 'DfuSe' dfu_se = b'DfuSe'
ufd = 'UFD' ufd = b'UFD'
if (python3): data = struct.pack('<5sBIB',dfu_se,1,len(data)+11,len(targets)) + data
dfu_se = b'DfuSe'
ufd = b'UFD'
data = struct.pack('<5sBIB',dfu_se,1,len(data)+11,len(targets)) + data
v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1))
data += struct.pack('<4H3sB',0,d,v,0x011a,ufd,16) data += struct.pack('<4H3sB',0,d,v,0x011a,ufd,16)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# #
# dfu.py: Access USB DFU class devices # dfu.py: Access USB DFU class devices
# Copyright (C) 2009 Black Sphere Technologies # Copyright (C) 2009 Black Sphere Technologies
@ -62,7 +62,7 @@ DFU_STATUS_ERROR_POR = 0x0d
DFU_STATUS_ERROR_UNKNOWN = 0x0e DFU_STATUS_ERROR_UNKNOWN = 0x0e
DFU_STATUS_ERROR_STALLEDPKT = 0x0f DFU_STATUS_ERROR_STALLEDPKT = 0x0f
class dfu_status(object): class dfu_status:
def __init__(self, buf): def __init__(self, buf):
self.bStatus = buf[0] self.bStatus = buf[0]
self.bwPollTimeout = buf[1] + (buf[2]<<8) + (buf[3]<<16) self.bwPollTimeout = buf[1] + (buf[2]<<8) + (buf[3]<<16)
@ -70,7 +70,7 @@ class dfu_status(object):
self.iString = buf[5] self.iString = buf[5]
class dfu_device(object): class dfu_device:
def __init__(self, dev, conf, iface): def __init__(self, dev, conf, iface):
self.dev = dev self.dev = dev
self.conf = conf self.conf = conf

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# #
# 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
@ -152,7 +152,7 @@ class Target:
"""Read length bytes from target at address addr""" """Read length bytes from target at address addr"""
ret = b'' ret = b''
while length: while length:
# print "Read" # print("Read")
packlen = min(length,self.PacketSize//2) packlen = min(length,self.PacketSize//2)
self.putpacket(b"m%08X,%08X" % (addr, packlen)) self.putpacket(b"m%08X,%08X" % (addr, packlen))
reply = self.getpacket() reply = self.getpacket()
@ -188,11 +188,11 @@ class Target:
self.putpacket(b"g") self.putpacket(b"g")
reply = self.getpacket() reply = self.getpacket()
if (reply == b'') or (reply[:1] == b'E'): if (reply == b'') or (reply[:1] == b'E'):
raise Exception('Error reading memory at 0x%08X' % addr) raise Exception('Error reading target core registers')
try: try:
data = unhexify(reply) data = unhexify(reply)
except Exception: except Exception:
raise Exception('Invalid response to memory read packet: %r' % reply) raise Exception('Invalid response to registers read packet: %r' % reply)
ret = array.array('I',data) ret = array.array('I',data)
return ret return ret
@ -292,7 +292,7 @@ class Target:
addr = self.offset + self.blocksize * i addr = self.offset + self.blocksize * i
if data is None: if data is None:
continue 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(b"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() != b'OK': if self.target.getpacket() != b'OK':
@ -301,7 +301,7 @@ class Target:
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(b"vFlashWrite:%08X:%s" % (addr, d)) self.target.putpacket(b"vFlashWrite:%08X:%s" % (addr, d))
addr += len(d) addr += len(d)
if self.target.getpacket() != b'OK': if self.target.getpacket() != b'OK':

View File

@ -1,4 +1,4 @@
#!/usr/bin/python #!/usr/bin/env python3
"""Pulls nRF51 IDs from openocd's nrf51.c in a form suitable for """Pulls nRF51 IDs from openocd's nrf51.c in a form suitable for
pasting into blackmagic's nrf51.c pasting into blackmagic's nrf51.c
@ -21,11 +21,11 @@ specdict = {}
specs = [] specs = []
spec = Spec() spec = Spec()
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"): for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
m = re.search('/\*(.*)\*/',line) m = re.search(r'/\*(.*)\*/',line)
if m: if m:
lastcomment=m.group(1) lastcomment=m.group(1)
m = re.search('NRF51_DEVICE_DEF\((0x[0-9A-F]*),\s*"(.*)",\s*"(.*)",\s*"(.*)",\s*([0-9]*)\s*\),', line) m = re.search(r'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)
spec.variant = m.group(3) spec.variant = m.group(3)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# 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
@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import gdb import gdb
import struct
import time import time
# Microcode sequence to erase option bytes # Microcode sequence to erase option bytes
@ -35,7 +34,7 @@ def flash_write_hex(target, hexfile, progress_cb=None):
raise Exception("Error in hex file") 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(x for x in bytes.fromhex(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
@ -65,8 +64,8 @@ if __name__ == "__main__":
from sys import argv, platform, stdout from sys import argv, platform, stdout
from getopt import getopt from getopt import getopt
if platform == "linux2": if platform == "linux":
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>")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# #
# stm32_mem.py: STM32 memory access using USB DFU class # stm32_mem.py: STM32 memory access using USB DFU class
# Copyright (C) 2011 Black Sphere Technologies # Copyright (C) 2011 Black Sphere Technologies
@ -21,10 +21,9 @@
from time import sleep from time import sleep
import struct import struct
import os import os
from sys import stdout, argv from sys import stdout
import argparse import argparse
import usb
import dfu import dfu
CMD_GETCOMMANDS = 0x00 CMD_GETCOMMANDS = 0x00
@ -86,7 +85,7 @@ def stm32_scan(args, test):
bmp_devs = [] bmp_devs = []
bmp = 0 bmp = 0
if not devs: if not devs:
if test == True: if test:
return return
print("No DFU devices found!") print("No DFU devices found!")
@ -107,14 +106,14 @@ def stm32_scan(args, test):
bmp_devs.append(dev) bmp_devs.append(dev)
if bmp == 0: if bmp == 0:
if test == True: if test:
return return
print("No compatible device found\n") print("No compatible device found\n")
exit(-1) exit(-1)
if bmp > 1 and not args.serial_target: if bmp > 1 and not args.serial_target:
if test == True: if test:
return return
print("Found multiple devices:\n") print("Found multiple devices:\n")
@ -129,7 +128,7 @@ def stm32_scan(args, test):
print("Serial:\t\t %s\n" % serial_no) print("Serial:\t\t %s\n" % serial_no)
print("Select device with serial number!") print("Select device with serial number!")
exit (-1) exit(-1)
for dev in bmp_devs: for dev in bmp_devs:
dfudev = dfu.dfu_device(*dev) dfudev = dfu.dfu_device(*dev)
@ -171,7 +170,7 @@ if __name__ == "__main__":
try: try:
state = dfudev.get_state() state = dfudev.get_state()
except: except:
if args.manifest : exit(0) if args.manifest: exit(0)
print("Failed to read device state! Assuming APP_IDLE") print("Failed to read device state! Assuming APP_IDLE")
state = dfu.STATE_APP_IDLE state = dfu.STATE_APP_IDLE
if state == dfu.STATE_APP_IDLE: if state == dfu.STATE_APP_IDLE:
@ -182,15 +181,15 @@ if __name__ == "__main__":
dfudev.release() dfudev.release()
print("Invoking DFU Device") print("Invoking DFU Device")
timeout = 0 timeout = 0
while True : while True:
sleep(1) sleep(1)
timeout = timeout + 0.5 timeout = timeout + 0.5
dfudev = stm32_scan(args, True) dfudev = stm32_scan(args, True)
if dfudev: break if dfudev: break
if timeout > 5 : if timeout > 5:
print("Error: DFU device did not appear") print("Error: DFU device did not appear")
exit(-1) exit(-1)
if args.manifest : if args.manifest:
stm32_manifest(dfudev) stm32_manifest(dfudev)
print("Invoking Application Device") print("Invoking Application Device")
exit(0) exit(0)
@ -203,16 +202,16 @@ if __name__ == "__main__":
bin = file.read() bin = file.read()
product = dfudev.handle.getString(dfudev.dev.iProduct, 64).decode('utf8') product = dfudev.handle.getString(dfudev.dev.iProduct, 64).decode('utf8')
if args.address : if args.address:
start = int(args.address, 0) start = int(args.address, 0)
else : else:
if "F4" in product or "STLINK-V3" in product: if "F4" in product or "STLINK-V3" in product:
start = 0x8004000 start = 0x8004000
else: else:
start = 0x8002000 start = 0x8002000
addr = start addr = start
while bin: while bin:
print ("Programming memory at 0x%08X" % addr, end="\r") print("Programming memory at 0x%08X" % addr, end="\r")
stdout.flush() stdout.flush()
try: try:
# STM DFU bootloader erases always. # STM DFU bootloader erases always.
@ -243,19 +242,19 @@ if __name__ == "__main__":
except: except:
# Abort silent if bootloader does not support upload # Abort silent if bootloader does not support upload
break break
print ("Verifying memory at 0x%08X" % addr, end="\r") print("Verifying memory at 0x%08X" % addr, end="\r")
stdout.flush() stdout.flush()
if len > 1024 : if len > 1024:
size = 1024 size = 1024
else : else:
size = len size = len
if bin[:size] != bytearray(data[:size]) : if bin[:size] != bytearray(data[:size]):
print ("\nMismatch 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
len -= 1024 len -= 1024
if len <= 0 : if len <= 0:
print("\nVerified!") print("\nVerified!")
stm32_manifest(dfudev) stm32_manifest(dfudev)

View File

@ -31,6 +31,7 @@ SRC = \
gdb_hostio.c \ gdb_hostio.c \
gdb_packet.c \ gdb_packet.c \
hex_utils.c \ hex_utils.c \
jtag_devs.c \
jtag_scan.c \ jtag_scan.c \
lmi.c \ lmi.c \
lpc_common.c \ lpc_common.c \

View File

@ -73,7 +73,7 @@ ifneq ($(HOSTED_BMP_ONLY), 1)
endif endif
VPATH += platforms/pc VPATH += platforms/pc
SRC += timing.c cl_utils.c utils.c jtag_devs.c SRC += timing.c cl_utils.c utils.c
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
ifneq ($(HOSTED_BMP_ONLY), 1) ifneq ($(HOSTED_BMP_ONLY), 1)
SRC += bmp_libusb.c stlinkv2.c SRC += bmp_libusb.c stlinkv2.c

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright(C) 2020 - 2021 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * Copyright(C) 2020 - 2022 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* 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
@ -146,7 +146,6 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
char serial[64]; char serial[64];
char manufacturer[128]; char manufacturer[128];
char product[128]; char product[128];
bmp_type_t type;
bool access_problems = false; bool access_problems = false;
char *active_cable = NULL; char *active_cable = NULL;
bool ftdi_unknown = false; bool ftdi_unknown = false;
@ -159,7 +158,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
active_cable = NULL; active_cable = NULL;
ftdi_unknown = false; ftdi_unknown = false;
for (int i = 0; devs[i]; i++) { for (int i = 0; devs[i]; i++) {
type = BMP_TYPE_NONE; bmp_type_t type = BMP_TYPE_NONE;
libusb_device *dev = devs[i]; libusb_device *dev = devs[i];
int res = libusb_get_device_descriptor(dev, &desc); int res = libusb_get_device_descriptor(dev, &desc);
if (res < 0) { if (res < 0) {
@ -299,7 +298,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
} }
if ((found_debuggers == 0) && ftdi_unknown) if ((found_debuggers == 0) && ftdi_unknown)
DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c <cable>\" !\n"); DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c <cable>\" !\n");
if ((found_debuggers == 1) && !cl_opts->opt_cable && (type == BMP_TYPE_LIBFTDI)) if ((found_debuggers == 1) && !cl_opts->opt_cable && (info->bmp_type == BMP_TYPE_LIBFTDI))
cl_opts->opt_cable = active_cable; cl_opts->opt_cable = active_cable;
if (!found_debuggers && cl_opts->opt_list_only) if (!found_debuggers && cl_opts->opt_list_only)
DEBUG_WARN("No usable debugger found\n"); DEBUG_WARN("No usable debugger found\n");

View File

@ -305,7 +305,10 @@ static uint32_t swdptap_seq_in(int ticks)
if (do_mpsse) { if (do_mpsse) {
uint8_t DO[4]; uint8_t DO[4];
libftdi_jtagtap_tdi_tdo_seq(DO, 0, NULL, ticks); libftdi_jtagtap_tdi_tdo_seq(DO, 0, NULL, ticks);
for (int i = 0; i < (ticks >> 3) + (ticks & 7)? 1: 0; i++) { int bytes = ticks >> 3;
if (ticks & 7)
bytes++;
for (int i = 0; i < bytes; i++) {
result |= DO[i] << (8 * i); result |= DO[i] << (8 * i);
} }
} else { } else {

View File

@ -126,26 +126,21 @@ static void jtagtap_tdi_tdo_seq(
chunk = 64; chunk = 64;
} }
ticks -= chunk; ticks -= chunk;
uint8_t di[8]; uint64_t di = 0;
memset(di, 0, 8);
int bytes = (chunk + 7) >> 3; int bytes = (chunk + 7) >> 3;
int i = 0;
if (DI) { if (DI) {
memcpy(&di, DI, bytes); for (; i < bytes; i++) {
int remainder = chunk & 7; di |= *DI << (i * 8);
DI += bytes; DI++;
DI += bytes;
if (remainder) {
uint8_t rem = *DI;
rem &= (1 << remainder) - 1;
*di = rem;
} }
}; }
/* PRIx64 differs with system. Use it explicit in the format string*/ /* PRIx64 differs with system. Use it explicit in the format string*/
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
"!J%c%02x%" PRIx64 "%c", "!J%c%02x%" PRIx64 "%c",
(!ticks && final_tms) ? (!ticks && final_tms) ?
REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS, REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS,
chunk, *(uint64_t*)di, REMOTE_EOM); chunk, di, REMOTE_EOM);
platform_buffer_write(construct,s); platform_buffer_write(construct,s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
@ -156,8 +151,10 @@ static void jtagtap_tdi_tdo_seq(
} }
if (DO) { if (DO) {
uint64_t res = remotehston(-1, (char *)&construct[1]); uint64_t res = remotehston(-1, (char *)&construct[1]);
memcpy(DO, &res, bytes); for (i = bytes; i > 0; i--) {
DO += bytes; *DO++ = res & 0xff;
res >>= 8;
}
} }
} }
} }

View File

@ -1010,7 +1010,7 @@ int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens)
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) == if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
dev_descr[j].idcode) { dev_descr[j].idcode) {
if(dev_descr[j].handler) if(dev_descr[j].handler)
dev_descr[j].handler(&jtag_devs[i]); dev_descr[j].handler(i, dev_descr[j].idcode);
break; break;
} }

View File

@ -27,7 +27,7 @@ all: blackmagic.bin blackmagic.hex
blackmagic.dfu: blackmagic.hex blackmagic.dfu: blackmagic.hex
@echo Creating $@ @echo Creating $@
@python ../scripts/dfu-convert.py -i $< $@ @python3 ../scripts/dfu-convert.py -i $< $@
host_clean: host_clean:
-$(Q)$(RM) blackmagic.bin blackmagic.hex blackmagic.dfu -$(Q)$(RM) blackmagic.bin blackmagic.hex blackmagic.dfu

View File

@ -11,7 +11,7 @@
| SRST | PB4 | CN5/8 | P4/9 (40) | | SRST | PB4 | CN5/8 | P4/9 (40) |
| UART1_TX | PB6 | CN7/4 | P4/7 (42) | | UART1_TX | PB6 | CN7/4 | P4/7 (42) |
| UART1_RX | PB7 | CN7/2 | P4/6 (43) | | UART1_RX | PB7 | CN7/2 | P4/6 (43) |
| SWO/RX2 | PA3 | NA(*1) | P3/7 (13) | | SWO/RX2 | PA3 | NA(*1) | P3/8 (13) |
*1: Wire JTDO/PB3 (U2/39) to USART2_RX/PA3 (U2/13) to expose SWO for Stlink *1: Wire JTDO/PB3 (U2/39) to USART2_RX/PA3 (U2/13) to expose SWO for Stlink
on STM8S-Disco on CN5/3 on STM8S-Disco on CN5/3

View File

@ -89,23 +89,19 @@
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8) #define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC) #define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
/* Known designers seen in SYSROM-PIDR and JTAG IDCode. /* Known designers seen in SYSROM-PIDR. Ignore Bit 0 from
* Ignore Bit 0 from the designer bits to get JEDEC Ids. * the designer bits to get JEDEC Ids with bit 7 ignored.*/
* Should get it's one file as not only related to Adiv5!
*/
#define AP_DESIGNER_FREESCALE 0x00e #define AP_DESIGNER_FREESCALE 0x00e
#define AP_DESIGNER_TEXAS 0x017 #define AP_DESIGNER_TEXAS 0x017
#define AP_DESIGNER_ATMEL 0x01f #define AP_DESIGNER_ATMEL 0x01f
#define AP_DESIGNER_STM 0x020 #define AP_DESIGNER_STM 0x020
#define AP_DESIGNER_CYPRESS 0x034 #define AP_DESIGNER_CYPRESS 0x034
#define AP_DESIGNER_INFINEON 0x041 #define AP_DESIGNER_INFINEON 0x041
#define DESIGNER_XILINX 0x049
#define AP_DESIGNER_NORDIC 0x244 #define AP_DESIGNER_NORDIC 0x244
#define AP_DESIGNER_ARM 0x43b #define AP_DESIGNER_ARM 0x43b
/*LPC845 with designer 501. Strange!? */ /*LPC845 with designer 501. Strange!? */
#define AP_DESIGNER_SPECULAR 0x501 #define AP_DESIGNER_SPECULAR 0x501
#define AP_DESIGNER_CS 0x555 #define AP_DESIGNER_CS 0x555
#define DESIGNER_XAMBALA 0x61e
#define AP_DESIGNER_ENERGY_MICRO 0x673 #define AP_DESIGNER_ENERGY_MICRO 0x673
#define AP_DESIGNER_GIGADEVICE 0x751 #define AP_DESIGNER_GIGADEVICE 0x751
#define AP_DESIGNER_RASPBERRY 0x927 #define AP_DESIGNER_RASPBERRY 0x927
@ -289,7 +285,7 @@ void adiv5_ap_ref(ADIv5_AP_t *ap);
void adiv5_ap_unref(ADIv5_AP_t *ap); void adiv5_ap_unref(ADIv5_AP_t *ap);
void platform_add_jtag_dev(const int dev_index, const jtag_dev_t *jtag_dev); void platform_add_jtag_dev(const int dev_index, const jtag_dev_t *jtag_dev);
void adiv5_jtag_dp_handler(jtag_dev_t *jd); void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode);
int platform_jtag_dp_init(ADIv5_DP_t *dp); int platform_jtag_dp_init(ADIv5_DP_t *dp);
int swdptap_init(ADIv5_DP_t *dp); int swdptap_init(ADIv5_DP_t *dp);

View File

@ -39,7 +39,7 @@
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp); static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp);
void adiv5_jtag_dp_handler(jtag_dev_t *jd) void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode)
{ {
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dp) { /* calloc failed: heap exhaustion */ if (!dp) { /* calloc failed: heap exhaustion */
@ -47,8 +47,8 @@ void adiv5_jtag_dp_handler(jtag_dev_t *jd)
return; return;
} }
dp->dp_jd_index = jd->jd_dev; dp->dp_jd_index = jd_index;
dp->idcode = jd->jd_idcode; dp->idcode = j_idcode;
if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) { if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) {
dp->dp_read = fw_adiv5_jtagdp_read; dp->dp_read = fw_adiv5_jtagdp_read;
dp->error = adiv5_jtagdp_error; dp->error = adiv5_jtagdp_error;

View File

@ -22,7 +22,7 @@ typedef const struct jtag_dev_descr_s {
const uint32_t idcode; const uint32_t idcode;
const uint32_t idmask; const uint32_t idmask;
const char * const descr; const char * const descr;
void (*const handler)(jtag_dev_t *jd); void (*const handler)(uint8_t jd_index, uint32_t j_idcode);
} jtag_dev_descr_t; } jtag_dev_descr_t;
extern jtag_dev_descr_t dev_descr[]; extern jtag_dev_descr_t dev_descr[];

View File

@ -3,7 +3,6 @@
* *
* Copyright (C) 2011 Black Sphere Technologies Ltd. * Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz> * Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2021 Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* 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
@ -26,14 +25,16 @@
#include "general.h" #include "general.h"
#include "jtagtap.h" #include "jtagtap.h"
#include "jtag_scan.h"
#include "target.h" #include "target.h"
#include "adiv5.h" #include "adiv5.h"
#include "jtag_devs.h"
jtag_dev_t jtag_devs[JTAG_MAX_DEVS+1]; struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1];
int jtag_dev_count; int jtag_dev_count;
/* bucket of ones for don't care TDI */ /* bucket of ones for don't care TDI */
static const uint8_t ones[] = {0xff, 0xFF, 0xFF, 0xFF}; static const uint8_t ones[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
#if PC_HOSTED == 0 #if PC_HOSTED == 0
void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev) void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev)
@ -46,32 +47,36 @@ void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev)
#endif #endif
/* Scan JTAG chain for devices, store IR length and IDCODE (if present). /* Scan JTAG chain for devices, store IR length and IDCODE (if present).
* Reset TAP state machine.
* Select Shift-IR state.
* Each device is assumed to shift out IR at 0x01. (this may not always be true)
* Shift in ones until we read two consecutive ones, then we have shifted out the
* IRs of all devices.
* *
* https://www.fpga4fun.com/JTAG3.html * After this process all the IRs are loaded with the BYPASS command.
* Count the number of devices in the JTAG chain * Select Shift-DR state.
* * Shift in ones and count zeros shifted out. Should be one for each device.
* shift enough ones in IR * Check this against device count obtained by IR scan above.
* shift enough zeros in DR
* Now shift out ones and stop if first '1' is seen. This gets the number
* of devices
*
* Assume max 32 devices with max IR len 16 = 512 bits = 16 loops * 32 bit
* *
* Reset the TAP state machine again. This should load all IRs with IDCODE. * Reset the TAP state machine again. This should load all IRs with IDCODE.
* Read 32 bit IDCODE for all devices. * For each device, shift out one bit. If this is zero IDCODE isn't present,
*/ * continue to next device. If this is one shift out the remaining 31 bits
* of the IDCODE register.
*/
int jtag_scan(const uint8_t *irlens) int jtag_scan(const uint8_t *irlens)
{ {
int i; int i;
void (*jd_handlers[JTAG_MAX_DEVS])(jtag_dev_t *jd); uint32_t j;
target_list_free(); target_list_free();
memset(jd_handlers, 0, sizeof(jd_handlers)); jtag_dev_count = 0;
memset(&jtag_devs, 0, sizeof(jtag_devs));
/* Run throught the SWD to JTAG sequence for the case where an /* Run throught the SWD to JTAG sequence for the case where an attached SWJ-DP is
* attached SWJ-DP is in SW-DP mode. * in SW-DP mode.
*/ */
DEBUG_INFO("Resetting TAP\n");
#if PC_HOSTED == 1 #if PC_HOSTED == 1
if (platform_jtagtap_init()) { if (platform_jtagtap_init()) {
DEBUG_WARN("JTAG not available\n"); DEBUG_WARN("JTAG not available\n");
@ -81,146 +86,139 @@ int jtag_scan(const uint8_t *irlens)
jtagtap_init(); jtagtap_init();
#endif #endif
jtag_proc.jtagtap_reset(); jtag_proc.jtagtap_reset();
#define LOOPS 16
jtagtap_shift_ir(); if (irlens) {
i = LOOPS; DEBUG_WARN("Given list of IR lengths, skipping probe\n");
uint8_t ir_chain[64], *din = ir_chain; DEBUG_INFO("Change state to Shift-IR\n");
while (i--) { jtagtap_shift_ir();
jtag_proc.jtagtap_tdi_tdo_seq(din, (i == 0) ? 1 : 0, ones, j = 0;
sizeof(ones) * 8); while((jtag_dev_count <= JTAG_MAX_DEVS) &&
din += sizeof(ones); (jtag_devs[jtag_dev_count].ir_len <= JTAG_MAX_IR_LEN)) {
} uint32_t irout;
if (!(ir_chain[0] & 1)) { if(*irlens == 0)
DEBUG_WARN("Unexpected IR chain!\n"); break;
return 0; jtag_proc.jtagtap_tdi_tdo_seq((uint8_t*)&irout, 0, ones, *irlens);
if (!(irout & 1)) {
DEBUG_WARN("check failed: IR[0] != 1\n");
return -1;
}
jtag_devs[jtag_dev_count].ir_len = *irlens;
jtag_devs[jtag_dev_count].ir_prescan = j;
jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count;
j += *irlens;
irlens++;
jtag_dev_count++;
}
} else {
DEBUG_INFO("Change state to Shift-IR\n");
jtagtap_shift_ir();
DEBUG_INFO("Scanning out IRs\n");
if(!jtag_proc.jtagtap_next(0, 1)) {
DEBUG_WARN("jtag_scan: Sanity check failed: IR[0] shifted out "
"as 0\n");
jtag_dev_count = -1;
return -1; /* must be 1 */
}
jtag_devs[0].ir_len = 1; j = 1;
while((jtag_dev_count <= JTAG_MAX_DEVS) &&
(jtag_devs[jtag_dev_count].ir_len <= JTAG_MAX_IR_LEN)) {
if(jtag_proc.jtagtap_next(0, 1)) {
if(jtag_devs[jtag_dev_count].ir_len == 1) break;
jtag_devs[++jtag_dev_count].ir_len = 1;
jtag_devs[jtag_dev_count].ir_prescan = j;
jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count;
} else jtag_devs[jtag_dev_count].ir_len++;
j++;
}
if(jtag_dev_count > JTAG_MAX_DEVS) {
DEBUG_WARN("jtag_scan: Maximum device count exceeded\n");
jtag_dev_count = -1;
return -1;
}
if(jtag_devs[jtag_dev_count].ir_len > JTAG_MAX_IR_LEN) {
DEBUG_WARN("jtag_scan: Maximum IR length exceeded\n");
jtag_dev_count = -1;
return -1;
}
} }
DEBUG_INFO("Return to Run-Test/Idle\n");
jtag_proc.jtagtap_next(1, 1);
jtagtap_return_idle(); jtagtap_return_idle();
/* All devices should be in BYPASS now */
/* Count device on chain */
DEBUG_INFO("Change state to Shift-DR\n");
jtagtap_shift_dr(); jtagtap_shift_dr();
i = LOOPS; for(i = 0; (jtag_proc.jtagtap_next(0, 1) == 0) && (i <= jtag_dev_count); i++)
uint8_t zeros[] = {0, 0, 0, 0};
while(i--) {
jtag_proc.jtagtap_tdi_seq(0, zeros, sizeof(zeros) * 8);
}
int num_devices = 0;
while (!jtag_proc.jtagtap_next(0,1) && (i++ < 6))
num_devices++;
jtag_proc.jtagtap_reset();
jtagtap_shift_dr();
jtag_dev_count = num_devices;
if (!num_devices)
return 0;
DEBUG_TARGET("Found %d devices\n", num_devices);
int irbit = 1;
int j = 0;
for (i = 0; i < num_devices; i++) {
uint8_t id[4];
jtag_proc.jtagtap_tdi_tdo_seq(id, 0, ones, 32);
if (!(id[0] & 1)) {
DEBUG_WARN("Invalid IDCode!\n");
return 0;
}
uint32_t idcode = id[3] << 24 | id[2] << 16 | id[1] << 8 | id[0];
unsigned int designer = ((id[1] & 0xf) << 8) | (id[0] >> 1);
unsigned int product = id[2] | ((id[3] & 0xf) << 8);
unsigned int expected_irlen = 0;
switch (designer) {
case AP_DESIGNER_ARM:
switch (product) {
case 0xba0:
jtag_devs[i].jd_descr = "ADIv5 JTAG-DP port";
jd_handlers[i] = adiv5_jtag_dp_handler;
expected_irlen = 4;
break;
default:
jtag_devs[i].jd_descr = "ARM";
}
break;
case AP_DESIGNER_STM:
expected_irlen = 5;
jtag_devs[i].jd_descr = "STM32 BSD";
break;
case AP_DESIGNER_ATMEL:
if ((product >= 0x940) & (product < 0x990)) {
jtag_devs[i].jd_descr = "ATMEL AVR8";
expected_irlen = 4;
break;
}
jtag_devs[i].jd_descr = "ATMEL";
break;
case DESIGNER_XILINX:
if (!irlens) {
/* Guessed irlen for XILINX devices is wrong.
* IR data contains status bits!
*/
DEBUG_WARN("Please provide irlens as chain contains XILINX devices!\n");
return 0;
}
jtag_devs[i].jd_descr = "XILINX";
break;
case DESIGNER_XAMBALA:
expected_irlen = 5;
jtag_devs[i].jd_descr = "RVDBG013";
break;
case AP_DESIGNER_GIGADEVICE:
expected_irlen = 5;
jtag_devs[i].jd_descr = "GIGADEVICE BSD";
break;
}
if (!jtag_devs[i].jd_descr) {
DEBUG_WARN("Unhandled designer %x\n", designer);
jtag_devs[i].jd_descr = "Unknow";
}
bool bit;
int guessed_irlen = 0;
int advance = irbit;
do {
/* Guess IR length from the IR scan after JTAG Reset
* First bit should be '1', following bits are '0', if not used
* for instruction capture, as for Xilinx parts.
*/
bit = (ir_chain[advance / 8] & (1 << (advance & 7)));
guessed_irlen++;
advance++;
} while (!bit && (advance < (JTAG_MAX_DEVS * 16)));
if (irlens) { /* Allow to overwrite from the command line!*/
if (*irlens != guessed_irlen) {
DEBUG_TARGET("Provides irlen %d vs guessed %d for device %d\n",
*irlens, guessed_irlen, i + 1);
}
expected_irlen = *irlens++;
}
if (!expected_irlen) {
expected_irlen = guessed_irlen++;
}
jtag_devs[i].ir_len = expected_irlen;
jtag_devs[i].ir_prescan = j;
jtag_devs[i].jd_dev = i;
jtag_devs[i].jd_idcode = idcode;
jtag_devs[i].dr_postscan = jtag_dev_count - i - 1; jtag_devs[i].dr_postscan = jtag_dev_count - i - 1;
jtag_devs[i].current_ir = -1;
j += expected_irlen; if(i != jtag_dev_count) {
irbit += expected_irlen; DEBUG_WARN("jtag_scan: Sanity check failed: "
DEBUG_INFO("%2d: IDCODE: 0x%08" PRIx32 ", IR len %d %s%s\n", i + 1, "BYPASS dev count doesn't match IR scan\n");
idcode,jtag_devs[i].ir_len, jtag_devs[i].jd_descr, jtag_dev_count = -1;
(jd_handlers[i]) ? "" : " (Unhandled) "); return -1;
} }
jtag_proc.jtagtap_reset();
DEBUG_INFO("Return to Run-Test/Idle\n");
jtag_proc.jtagtap_next(1, 1);
jtagtap_return_idle();
if(!jtag_dev_count) {
return 0;
}
/* Fill in the ir_postscan fields */ /* Fill in the ir_postscan fields */
for(i = jtag_dev_count - 1; i; i--) { for(i = jtag_dev_count - 1; i; i--)
jtag_devs[i-1].ir_postscan = jtag_devs[i].ir_postscan + jtag_devs[i-1].ir_postscan = jtag_devs[i].ir_postscan +
jtag_devs[i].ir_len; jtag_devs[i].ir_len;
/* Reset jtagtap: should take all devs to IDCODE */
jtag_proc.jtagtap_reset();
jtagtap_shift_dr();
for(i = 0; i < jtag_dev_count; i++) {
if(!jtag_proc.jtagtap_next(0, 1)) continue;
jtag_devs[i].jd_idcode = 1;
for(j = 2; j; j <<= 1)
if(jtag_proc.jtagtap_next(0, 1)) jtag_devs[i].jd_idcode |= j;
} }
DEBUG_INFO("Return to Run-Test/Idle\n");
jtag_proc.jtagtap_next(1, 1);
jtagtap_return_idle();
#if PC_HOSTED == 1 #if PC_HOSTED == 1
/*Transfer needed device information to firmware jtag_devs*/ /*Transfer needed device information to firmware jtag_devs*/
for(i = 0; i < jtag_dev_count; i++) { for(i = 0; i < jtag_dev_count; i++)
platform_add_jtag_dev(i, &jtag_devs[i]); platform_add_jtag_dev(i, &jtag_devs[i]);
for(i = 0; i < jtag_dev_count; i++) {
DEBUG_INFO("Idcode 0x%08" PRIx32, jtag_devs[i].jd_idcode);
for(j = 0; dev_descr[j].idcode; j++) {
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
dev_descr[j].idcode) {
DEBUG_INFO(": %s",
(dev_descr[j].descr) ? dev_descr[j].descr : "unknown");
break;
}
}
DEBUG_INFO("\n");
} }
#endif #endif
/* Check for known devices and handle accordingly */ /* Check for known devices and handle accordingly */
for(i = 0; i < jtag_dev_count; i++) for(i = 0; i < jtag_dev_count; i++)
/* Call handler to initialise/probe device further */ for(j = 0; dev_descr[j].idcode; j++)
if (jd_handlers[i]) if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
jd_handlers[i](&jtag_devs[i]); dev_descr[j].idcode) {
jtag_devs[i].current_ir = -1;
/* Save description in table */
jtag_devs[i].jd_descr = dev_descr[j].descr;
/* Call handler to initialise/probe device further */
if(dev_descr[j].handler)
dev_descr[j].handler(i, dev_descr[i].idcode);
break;
}
return jtag_dev_count; return jtag_dev_count;
} }

View File

@ -40,7 +40,7 @@ typedef struct jtag_dev_s {
uint32_t current_ir; uint32_t current_ir;
} jtag_dev_t; } jtag_dev_t;
extern jtag_dev_t jtag_devs[JTAG_MAX_DEVS+1]; extern struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1];
extern int jtag_dev_count; extern int jtag_dev_count;
void jtag_dev_write_ir(jtag_proc_t *jp, uint8_t jd_index, uint32_t ir); void jtag_dev_write_ir(jtag_proc_t *jp, uint8_t jd_index, uint32_t ir);

View File

@ -373,7 +373,7 @@ do_common_s32k14x:
} }
static bool static bool
kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint8_t data[8]) kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint32_t *data, int n_items)
{ {
uint8_t fstat; uint8_t fstat;
@ -390,8 +390,9 @@ kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint8_t data[8])
addr |= (uint32_t)cmd << 24; addr |= (uint32_t)cmd << 24;
target_mem_write32(t, FTFA_FCCOB_0, addr); target_mem_write32(t, FTFA_FCCOB_0, addr);
if (data) { if (data) {
target_mem_write32(t, FTFA_FCCOB_1, *(uint32_t*)&data[0]); target_mem_write32(t, FTFA_FCCOB_1, data[0]);
target_mem_write32(t, FTFA_FCCOB_2, *(uint32_t*)&data[4]); if (n_items > 1)
target_mem_write32(t, FTFA_FCCOB_2, data[1]);
} }
/* Enable execution by clearing CCIF */ /* Enable execution by clearing CCIF */
@ -411,7 +412,7 @@ kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint8_t data[8])
static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t len) static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t len)
{ {
while (len) { while (len) {
if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL)) { if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL, 0)) {
/* Different targets have different flash erase sizes */ /* Different targets have different flash erase sizes */
if (len > f->blocksize) if (len > f->blocksize)
len -= f->blocksize; len -= f->blocksize;
@ -450,7 +451,7 @@ static int kl_gen_flash_write(struct target_flash *f,
} }
while (len) { while (len) {
if (kl_gen_command(f->t, write_cmd, dest, src)) { if (kl_gen_command(f->t, write_cmd, dest, src, 1)) {
if (len > kf->write_len) if (len > kf->write_len)
len -= kf->write_len; len -= kf->write_len;
else else
@ -484,12 +485,13 @@ static int kl_gen_flash_done(struct target_flash *f)
vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS); vals[1] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS);
vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; vals[1] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED;
kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE, kl_gen_command(f->t, FTFE_CMD_PROGRAM_PHRASE,
FLASH_SECURITY_BYTE_ADDRESS - 4, (uint8_t*)vals); FLASH_SECURITY_BYTE_ADDRESS - 4, vals, 2);
} else { } else {
uint32_t vals[2] = {target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS), 0}; uint32_t vals[1];
vals[0] = target_mem_read32(f->t, FLASH_SECURITY_BYTE_ADDRESS);
vals[0] = (vals[0] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED; vals[0] = (vals[0] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED;
kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD,
FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&vals); FLASH_SECURITY_BYTE_ADDRESS, vals, 1);
} }
return 0; return 0;

View File

@ -715,11 +715,51 @@ static bool samd_set_flashlock(target *t, uint16_t value, const char **argv)
return true; return true;
} }
static bool parse_unsigned(const char *s, uint32_t *val) {
int l, st;
unsigned long num;
l=strlen(s);
if (l>2 && s[0]=='0' && (s[1]=='x' || s[1]=='X')) {
st=sscanf(s+2, "%lx", &num);
} else {
st=sscanf(s, "%lu", &num);
}
if (st<1) {
return false;
}
*val=(uint32_t)num;
return true;
}
static bool samd_cmd_lock_flash(target *t, int argc, const char **argv) static bool samd_cmd_lock_flash(target *t, int argc, const char **argv)
{ {
unsigned long val;
(void)argc; (void)argc;
(void)argv; (void)argv;
return samd_set_flashlock(t, 0x0000, NULL);
if (argc>2) {
tc_printf(t, "usage: monitor lock_flash [number]\n");
return false;
} else if (argc==1) {
return samd_set_flashlock(t, 0x0000, NULL);
} else {
if (!parse_unsigned(argv[1], &val)) {
tc_printf(t, "number must be either decimal or 0x prefixed hexadecimal\n");
return false;
}
if (val>0xffff) {
tc_printf(t, "number must be between 0 and 0xFFFF\n");
return false;
}
return samd_set_flashlock(t, (uint16_t)val, NULL);
}
} }
static bool samd_cmd_unlock_flash(target *t, int argc, const char **argv) static bool samd_cmd_unlock_flash(target *t, int argc, const char **argv)
@ -764,9 +804,30 @@ static bool samd_set_bootprot(target *t, uint16_t value, const char **argv)
static bool samd_cmd_lock_bootprot(target *t, int argc, const char **argv) static bool samd_cmd_lock_bootprot(target *t, int argc, const char **argv)
{ {
unsigned long val;
(void)argc; (void)argc;
(void)argv; (void)argv;
return samd_set_bootprot(t, 0, NULL); /* locks first 0x7 .. 0, 0x6 .. 512, 0x5 .. 1024, ..., 0x0 .. 32768 bytes of flash*/
if (argc>2) {
tc_printf(t, "usage: monitor lock_bootprot [number]\n");
return false;
} else if (argc==1) {
return samd_set_bootprot(t, 0, NULL);
} else {
if (!parse_unsigned(argv[1], &val)) {
tc_printf(t, "number must be either decimal or 0x prefixed hexadecimal\n");
return false;
}
if (val>7) {
tc_printf(t, "number must be between 0 and 7\n");
return false;
}
return samd_set_bootprot(t, (uint16_t)val, NULL);
}
} }
static bool samd_cmd_unlock_bootprot(target *t, int argc, const char **argv) static bool samd_cmd_unlock_bootprot(target *t, int argc, const char **argv)