Merge commit '7d2afcff06f1ccd9fe583d562ddd81e04a17e166' into sam-update
This commit is contained in:
commit
b4af0f5145
36
.github/workflows/build-and-upload.yml
vendored
Normal file
36
.github/workflows/build-and-upload.yml
vendored
Normal 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
29
.github/workflows/build-pr.yml
vendored
Normal 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
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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':
|
||||||
|
@ -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)
|
||||||
|
@ -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>")
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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 \
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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[];
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user