diff --git a/.github/workflows/build-and-upload.yml b/.github/workflows/build-and-upload.yml
new file mode 100644
index 00000000..0bebd43f
--- /dev/null
+++ b/.github/workflows/build-and-upload.yml
@@ -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
diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml
new file mode 100644
index 00000000..a64ec3f2
--- /dev/null
+++ b/.github/workflows/build-pr.yml
@@ -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
diff --git a/scripts/bootprog.py b/scripts/bootprog.py
index 5baf82b0..968fcd68 100755
--- a/scripts/bootprog.py
+++ b/scripts/bootprog.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# bootprog.py: STM32 SystemMemory Production Programmer -- version 1.1
# Copyright (C) 2011 Black Sphere Technologies
@@ -34,95 +34,93 @@ class stm32_boot:
def _sync(self):
# Send sync byte
- #print "sending sync byte"
- self.serial.write("\x7F")
+ #print("sending sync byte")
+ self.serial.write(bytes((0x7F,)))
self._checkack()
def _sendcmd(self, cmd):
- if type(cmd) == int:
- cmd = chr(cmd)
- cmd += chr(ord(cmd) ^ 0xff)
- #print "sendcmd:", repr(cmd)
+ cmd = bytes((cmd, cmd ^ 0xff))
+ #print("sendcmd:", repr(cmd))
self.serial.write(cmd)
def _send(self, data):
csum = 0
- for c in data: csum ^= ord(c)
- data = data + chr(csum)
- #print "sending:", repr(data)
+ for c in data: csum ^= c
+ data = data + bytes((csum,))
+ #print("sending:", repr(data))
self.serial.write(data)
def _checkack(self):
- ACK = "\x79"
+ ACK = bytes((0x79,))
b = self.serial.read(1)
if b != ACK: raise Exception("Invalid ack: %r" % b)
- #print "got ack!"
+ #print("got ack!")
def get(self):
- self._sendcmd("\x00")
+ self._sendcmd(0x00)
self._checkack()
- num = ord(self.serial.read(1))
+ num = self.serial.read(1)[0]
data = self.serial.read(num+1)
self._checkack()
return data
def eraseall(self):
# Send erase cmd
- self._sendcmd("\x43")
+ self._sendcmd(0x43)
self._checkack()
# Global erase
- self._sendcmd("\xff")
+ self._sendcmd(0xff)
self._checkack()
def read(self, addr, len):
# Send read cmd
- self._sendcmd("\x11")
+ self._sendcmd(0x11)
self._checkack()
# Send address
self._send(struct.pack(">L", addr))
self._checkack()
# Send length
- self._sendcmd(chr(len-1))
+ self._sendcmd(len-1)
self._checkack()
return self.serial.read(len)
def write(self, addr, data):
# Send write cmd
- self._sendcmd("\x31")
+ self._sendcmd(0x31)
self._checkack()
# Send address
self._send(struct.pack(">L", addr))
self._checkack()
# Send data
- self._send(chr(len(data)-1) + data)
+ self._send(bytes((len(data)-1,)) + data)
self._checkack()
def write_protect(self, sectors):
# Send WP cmd
- self._sendcmd("\x63")
+ self._sendcmd(0x63)
self._checkack()
# 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()
# Resync after system reset
self._sync()
def write_unprotect(self):
- self._sendcmd("\x73")
+ self._sendcmd(0x73)
self._checkack()
self._checkack()
self._sync()
def read_protect(self):
- self._sendcmd("\x82")
+ self._sendcmd(0x82)
self._checkack()
self._checkack()
self._sync()
def read_unprotect(self):
- self._sendcmd("\x92")
+ self._sendcmd(0x92)
self._checkack()
self._checkack()
self._sync()
@@ -132,7 +130,7 @@ if __name__ == "__main__":
from sys import stdout, argv, platform
from getopt import getopt
- if platform == "linux2":
+ if platform == "linux":
print("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
print("STM32 SystemMemory Production Programmer -- version 1.1")
print("Copyright (C) 2011 Black Sphere Technologies")
@@ -162,7 +160,7 @@ if __name__ == "__main__":
boot = stm32_boot(dev, baud)
cmds = boot.get()
- print("Target bootloader version: %d.%d\n" % (ord(cmds[0]) >> 4, ord(cmds[0]) % 0xf))
+ print("Target bootloader version: %d.%d\n" % (cmds[0] >> 4, cmds[0] % 0xf))
print("Removing device protection...")
boot.read_unprotect()
diff --git a/scripts/dfu-convert.py b/scripts/dfu-convert.py
index 63240724..abc0cdda 100755
--- a/scripts/dfu-convert.py
+++ b/scripts/dfu-convert.py
@@ -1,19 +1,13 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# Written by Antonio Galea - 2010/11/18
# Distributed under Gnu LGPL 3.0
# 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
from optparse import OptionParser
from intelhex import IntelHex
-python3 = False
-if (sys.version_info > (3, 0)):
- python3 = True
-
DEFAULT_DEVICE="0x0483:0xdf11"
def named(tuple,names):
@@ -22,7 +16,7 @@ def consume(fmt,data,names):
n = struct.calcsize(fmt)
return named(struct.unpack(fmt,data[:n]),names),data[n:]
def cstring(string):
- return string.split('\0',1)[0]
+ return string.split(b'\0',1)[0]
def compute_crc(data):
return 0xFFFFFFFF & -zlib.crc32(data) -1
@@ -31,15 +25,15 @@ def parse(file,dump_images=False):
data = open(file,'rb').read()
crc = compute_crc(data[:-4])
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']):
tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements')
tprefix['num'] = t
if tprefix['named']:
tprefix['name'] = cstring(tprefix['name'])
else:
- tprefix['name'] = ''
- print('%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix)
+ tprefix['name'] = b''
+ print('%(signature)r %(num)d, alt setting: %(altsetting)r, name: %(name)r, size: %(size)d, elements: %(elements)d' % tprefix)
tsize = tprefix['size']
target, data = data[:tsize], data[tsize:]
for e in range(tprefix['elements']):
@@ -55,7 +49,7 @@ def parse(file,dump_images=False):
if len(target):
print("target %d: PARSE ERROR" % t)
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']:
print("CRC ERROR: computed crc32 is 0x%08x" % crc)
data = data[16:]
@@ -63,30 +57,20 @@ def parse(file,dump_images=False):
print("PARSE ERROR")
def build(file,targets,device=DEFAULT_DEVICE):
- data = ''
- if (python3):
- data = b''
+ data = b''
for t,target in enumerate(targets):
- tdata = ''
- if (python3):
- tdata = b''
+ tdata = b''
for image in target:
tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data']
- trgt = 'Target'
- st = 'ST...'
- if (python3):
- trgt = b'Target'
- st = b'ST...'
+ trgt = b'Target'
+ st = b'ST...'
tdata = struct.pack('<6sBI255s2I',trgt,0,1,st,len(tdata),len(target)) + tdata
data += tdata
- dfu_se = 'DfuSe'
- ufd = 'UFD'
- if (python3):
- dfu_se = b'DfuSe'
- ufd = b'UFD'
- 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))
data += struct.pack('<4H3sB',0,d,v,0x011a,ufd,16)
diff --git a/scripts/dfu.py b/scripts/dfu.py
index 170f2d2a..3a6fa752 100644
--- a/scripts/dfu.py
+++ b/scripts/dfu.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# dfu.py: Access USB DFU class devices
# Copyright (C) 2009 Black Sphere Technologies
@@ -62,7 +62,7 @@ DFU_STATUS_ERROR_POR = 0x0d
DFU_STATUS_ERROR_UNKNOWN = 0x0e
DFU_STATUS_ERROR_STALLEDPKT = 0x0f
-class dfu_status(object):
+class dfu_status:
def __init__(self, buf):
self.bStatus = buf[0]
self.bwPollTimeout = buf[1] + (buf[2]<<8) + (buf[3]<<16)
@@ -70,7 +70,7 @@ class dfu_status(object):
self.iString = buf[5]
-class dfu_device(object):
+class dfu_device:
def __init__(self, dev, conf, iface):
self.dev = dev
self.conf = conf
diff --git a/scripts/gdb.py b/scripts/gdb.py
index 6c6e02d0..30fa20f4 100644
--- a/scripts/gdb.py
+++ b/scripts/gdb.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# gdb.py: Python module for low level GDB protocol implementation
# Copyright (C) 2009 Black Sphere Technologies
@@ -152,7 +152,7 @@ class Target:
"""Read length bytes from target at address addr"""
ret = b''
while length:
- # print "Read"
+ # print("Read")
packlen = min(length,self.PacketSize//2)
self.putpacket(b"m%08X,%08X" % (addr, packlen))
reply = self.getpacket()
@@ -188,11 +188,11 @@ class Target:
self.putpacket(b"g")
reply = self.getpacket()
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:
data = unhexify(reply)
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)
return ret
@@ -292,7 +292,7 @@ class Target:
addr = self.offset + self.blocksize * i
if data is None:
continue
- #print "Erasing flash at 0x%X" % (self.offset + self.blocksize*i)
+ #print("Erasing flash at 0x%X" % (self.offset + self.blocksize*i))
self.target.putpacket(b"vFlashErase:%08X,%08X" %
(self.offset + self.blocksize*i, self.blocksize))
if self.target.getpacket() != b'OK':
@@ -301,7 +301,7 @@ class Target:
while data:
d = data[0:980]
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))
addr += len(d)
if self.target.getpacket() != b'OK':
diff --git a/scripts/get_openocd_nrf51_ids.py b/scripts/get_openocd_nrf51_ids.py
index 33bdd60e..a141f4fe 100755
--- a/scripts/get_openocd_nrf51_ids.py
+++ b/scripts/get_openocd_nrf51_ids.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
"""Pulls nRF51 IDs from openocd's nrf51.c in a form suitable for
pasting into blackmagic's nrf51.c
@@ -21,11 +21,11 @@ specdict = {}
specs = []
spec = Spec()
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
- m = re.search('/\*(.*)\*/',line)
+ m = re.search(r'/\*(.*)\*/',line)
if m:
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:
spec.hwid = int(m.group(1), base=0)
spec.variant = m.group(3)
diff --git a/scripts/hexprog.py b/scripts/hexprog.py
index 43f9693e..c9356d1c 100755
--- a/scripts/hexprog.py
+++ b/scripts/hexprog.py
@@ -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
# Copyright (C) 2011 Black Sphere Technologies
@@ -18,7 +18,6 @@
# along with this program. If not, see .
import gdb
-import struct
import time
# 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")
reclen = int(line[1:3], 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:
raise Exception("Checksum error in hex file")
if rectype == 0: # Data record
@@ -65,8 +64,8 @@ if __name__ == "__main__":
from sys import argv, platform, stdout
from getopt import getopt
- if platform == "linux2":
- print ("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
+ if platform == "linux":
+ print("\x1b\x5b\x48\x1b\x5b\x32\x4a") # clear terminal screen
print("Black Magic Probe -- Target Production Programming Tool -- version 1.0")
print("Copyright (C) 2011 Black Sphere Technologies")
print("License GPLv3+: GNU GPL version 3 or later ")
diff --git a/scripts/stm32_mem.py b/scripts/stm32_mem.py
index 9f47df31..a33c12ff 100755
--- a/scripts/stm32_mem.py
+++ b/scripts/stm32_mem.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
#
# stm32_mem.py: STM32 memory access using USB DFU class
# Copyright (C) 2011 Black Sphere Technologies
@@ -21,10 +21,9 @@
from time import sleep
import struct
import os
-from sys import stdout, argv
+from sys import stdout
import argparse
-import usb
import dfu
CMD_GETCOMMANDS = 0x00
@@ -86,7 +85,7 @@ def stm32_scan(args, test):
bmp_devs = []
bmp = 0
if not devs:
- if test == True:
+ if test:
return
print("No DFU devices found!")
@@ -107,14 +106,14 @@ def stm32_scan(args, test):
bmp_devs.append(dev)
if bmp == 0:
- if test == True:
+ if test:
return
print("No compatible device found\n")
exit(-1)
if bmp > 1 and not args.serial_target:
- if test == True:
+ if test:
return
print("Found multiple devices:\n")
@@ -129,7 +128,7 @@ def stm32_scan(args, test):
print("Serial:\t\t %s\n" % serial_no)
print("Select device with serial number!")
- exit (-1)
+ exit(-1)
for dev in bmp_devs:
dfudev = dfu.dfu_device(*dev)
@@ -171,7 +170,7 @@ if __name__ == "__main__":
try:
state = dfudev.get_state()
except:
- if args.manifest : exit(0)
+ if args.manifest: exit(0)
print("Failed to read device state! Assuming APP_IDLE")
state = dfu.STATE_APP_IDLE
if state == dfu.STATE_APP_IDLE:
@@ -182,15 +181,15 @@ if __name__ == "__main__":
dfudev.release()
print("Invoking DFU Device")
timeout = 0
- while True :
+ while True:
sleep(1)
timeout = timeout + 0.5
dfudev = stm32_scan(args, True)
if dfudev: break
- if timeout > 5 :
+ if timeout > 5:
print("Error: DFU device did not appear")
exit(-1)
- if args.manifest :
+ if args.manifest:
stm32_manifest(dfudev)
print("Invoking Application Device")
exit(0)
@@ -203,16 +202,16 @@ if __name__ == "__main__":
bin = file.read()
product = dfudev.handle.getString(dfudev.dev.iProduct, 64).decode('utf8')
- if args.address :
+ if args.address:
start = int(args.address, 0)
- else :
+ else:
if "F4" in product or "STLINK-V3" in product:
start = 0x8004000
else:
start = 0x8002000
addr = start
while bin:
- print ("Programming memory at 0x%08X" % addr, end="\r")
+ print("Programming memory at 0x%08X" % addr, end="\r")
stdout.flush()
try:
# STM DFU bootloader erases always.
@@ -243,19 +242,19 @@ if __name__ == "__main__":
except:
# Abort silent if bootloader does not support upload
break
- print ("Verifying memory at 0x%08X" % addr, end="\r")
+ print("Verifying memory at 0x%08X" % addr, end="\r")
stdout.flush()
- if len > 1024 :
+ if len > 1024:
size = 1024
- else :
+ else:
size = len
- if bin[:size] != bytearray(data[:size]) :
- print ("\nMismatch in block at 0x%08X" % addr)
- break;
+ if bin[:size] != bytearray(data[:size]):
+ print("\nMismatch in block at 0x%08X" % addr)
+ break
bin = bin[1024:]
addr += 1024
len -= 1024
- if len <= 0 :
+ if len <= 0:
print("\nVerified!")
stm32_manifest(dfudev)
diff --git a/src/Makefile b/src/Makefile
index b3f6f7ac..b6930f27 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -31,6 +31,7 @@ SRC = \
gdb_hostio.c \
gdb_packet.c \
hex_utils.c \
+ jtag_devs.c \
jtag_scan.c \
lmi.c \
lpc_common.c \
diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc
index f3e3248b..6ba2d781 100644
--- a/src/platforms/hosted/Makefile.inc
+++ b/src/platforms/hosted/Makefile.inc
@@ -73,7 +73,7 @@ ifneq ($(HOSTED_BMP_ONLY), 1)
endif
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
ifneq ($(HOSTED_BMP_ONLY), 1)
SRC += bmp_libusb.c stlinkv2.c
diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c
index 21ed9542..79d4a85b 100644
--- a/src/platforms/hosted/bmp_libusb.c
+++ b/src/platforms/hosted/bmp_libusb.c
@@ -1,7 +1,7 @@
/*
* 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
* 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 manufacturer[128];
char product[128];
- bmp_type_t type;
bool access_problems = false;
char *active_cable = NULL;
bool ftdi_unknown = false;
@@ -159,7 +158,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
active_cable = NULL;
ftdi_unknown = false;
for (int i = 0; devs[i]; i++) {
- type = BMP_TYPE_NONE;
+ bmp_type_t type = BMP_TYPE_NONE;
libusb_device *dev = devs[i];
int res = libusb_get_device_descriptor(dev, &desc);
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)
DEBUG_WARN("Generic FTDI MPSSE VID/PID found. Please specify exact type with \"-c \" !\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;
if (!found_debuggers && cl_opts->opt_list_only)
DEBUG_WARN("No usable debugger found\n");
diff --git a/src/platforms/hosted/libftdi_swdptap.c b/src/platforms/hosted/libftdi_swdptap.c
index 4878437f..3bf69898 100644
--- a/src/platforms/hosted/libftdi_swdptap.c
+++ b/src/platforms/hosted/libftdi_swdptap.c
@@ -305,7 +305,10 @@ static uint32_t swdptap_seq_in(int ticks)
if (do_mpsse) {
uint8_t DO[4];
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);
}
} else {
diff --git a/src/platforms/hosted/remote_jtagtap.c b/src/platforms/hosted/remote_jtagtap.c
index a5aa3b6c..8a0d91ae 100644
--- a/src/platforms/hosted/remote_jtagtap.c
+++ b/src/platforms/hosted/remote_jtagtap.c
@@ -126,26 +126,21 @@ static void jtagtap_tdi_tdo_seq(
chunk = 64;
}
ticks -= chunk;
- uint8_t di[8];
- memset(di, 0, 8);
+ uint64_t di = 0;
int bytes = (chunk + 7) >> 3;
+ int i = 0;
if (DI) {
- memcpy(&di, DI, bytes);
- int remainder = chunk & 7;
- DI += bytes;
- DI += bytes;
- if (remainder) {
- uint8_t rem = *DI;
- rem &= (1 << remainder) - 1;
- *di = rem;
+ for (; i < bytes; i++) {
+ di |= *DI << (i * 8);
+ DI++;
}
- };
+ }
/* PRIx64 differs with system. Use it explicit in the format string*/
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
"!J%c%02x%" PRIx64 "%c",
(!ticks && final_tms) ?
REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS,
- chunk, *(uint64_t*)di, REMOTE_EOM);
+ chunk, di, REMOTE_EOM);
platform_buffer_write(construct,s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
@@ -156,8 +151,10 @@ static void jtagtap_tdi_tdo_seq(
}
if (DO) {
uint64_t res = remotehston(-1, (char *)&construct[1]);
- memcpy(DO, &res, bytes);
- DO += bytes;
+ for (i = bytes; i > 0; i--) {
+ *DO++ = res & 0xff;
+ res >>= 8;
+ }
}
}
}
diff --git a/src/platforms/hosted/stlinkv2.c b/src/platforms/hosted/stlinkv2.c
index 42e81dd9..1ecae9f5 100644
--- a/src/platforms/hosted/stlinkv2.c
+++ b/src/platforms/hosted/stlinkv2.c
@@ -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) ==
dev_descr[j].idcode) {
if(dev_descr[j].handler)
- dev_descr[j].handler(&jtag_devs[i]);
+ dev_descr[j].handler(i, dev_descr[j].idcode);
break;
}
diff --git a/src/platforms/hydrabus/Makefile.inc b/src/platforms/hydrabus/Makefile.inc
index e2f8f395..9d62f2df 100644
--- a/src/platforms/hydrabus/Makefile.inc
+++ b/src/platforms/hydrabus/Makefile.inc
@@ -27,7 +27,7 @@ all: blackmagic.bin blackmagic.hex
blackmagic.dfu: blackmagic.hex
@echo Creating $@
- @python ../scripts/dfu-convert.py -i $< $@
+ @python3 ../scripts/dfu-convert.py -i $< $@
host_clean:
-$(Q)$(RM) blackmagic.bin blackmagic.hex blackmagic.dfu
diff --git a/src/platforms/swlink/README.md b/src/platforms/swlink/README.md
index edfbb9e6..1a9cceb3 100644
--- a/src/platforms/swlink/README.md
+++ b/src/platforms/swlink/README.md
@@ -11,7 +11,7 @@
| SRST | PB4 | CN5/8 | P4/9 (40) |
| UART1_TX | PB6 | CN7/4 | P4/7 (42) |
| 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
on STM8S-Disco on CN5/3
diff --git a/src/target/adiv5.h b/src/target/adiv5.h
index 95c62f62..bcaa1921 100644
--- a/src/target/adiv5.h
+++ b/src/target/adiv5.h
@@ -89,23 +89,19 @@
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
-/* Known designers seen in SYSROM-PIDR and JTAG IDCode.
- * Ignore Bit 0 from the designer bits to get JEDEC Ids.
- * Should get it's one file as not only related to Adiv5!
- */
+/* Known designers seen in SYSROM-PIDR. Ignore Bit 0 from
+ * the designer bits to get JEDEC Ids with bit 7 ignored.*/
#define AP_DESIGNER_FREESCALE 0x00e
#define AP_DESIGNER_TEXAS 0x017
#define AP_DESIGNER_ATMEL 0x01f
#define AP_DESIGNER_STM 0x020
#define AP_DESIGNER_CYPRESS 0x034
#define AP_DESIGNER_INFINEON 0x041
-#define DESIGNER_XILINX 0x049
#define AP_DESIGNER_NORDIC 0x244
#define AP_DESIGNER_ARM 0x43b
/*LPC845 with designer 501. Strange!? */
#define AP_DESIGNER_SPECULAR 0x501
#define AP_DESIGNER_CS 0x555
-#define DESIGNER_XAMBALA 0x61e
#define AP_DESIGNER_ENERGY_MICRO 0x673
#define AP_DESIGNER_GIGADEVICE 0x751
#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 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 swdptap_init(ADIv5_DP_t *dp);
diff --git a/src/target/adiv5_jtagdp.c b/src/target/adiv5_jtagdp.c
index 52737461..2c87dc7c 100644
--- a/src/target/adiv5_jtagdp.c
+++ b/src/target/adiv5_jtagdp.c
@@ -39,7 +39,7 @@
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));
if (!dp) { /* calloc failed: heap exhaustion */
@@ -47,8 +47,8 @@ void adiv5_jtag_dp_handler(jtag_dev_t *jd)
return;
}
- dp->dp_jd_index = jd->jd_dev;
- dp->idcode = jd->jd_idcode;
+ dp->dp_jd_index = jd_index;
+ dp->idcode = j_idcode;
if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) {
dp->dp_read = fw_adiv5_jtagdp_read;
dp->error = adiv5_jtagdp_error;
diff --git a/src/target/jtag_devs.h b/src/target/jtag_devs.h
index 8f877985..8c2c0b5a 100644
--- a/src/target/jtag_devs.h
+++ b/src/target/jtag_devs.h
@@ -22,7 +22,7 @@ typedef const struct jtag_dev_descr_s {
const uint32_t idcode;
const uint32_t idmask;
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;
extern jtag_dev_descr_t dev_descr[];
diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c
index eb1efc80..761f5ff0 100644
--- a/src/target/jtag_scan.c
+++ b/src/target/jtag_scan.c
@@ -3,7 +3,6 @@
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin
- * Copyright (C) 2021 Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
*
* 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
@@ -26,14 +25,16 @@
#include "general.h"
#include "jtagtap.h"
+#include "jtag_scan.h"
#include "target.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;
/* 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
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
/* 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
- * Count the number of devices in the JTAG chain
- *
- * shift enough ones in IR
- * 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
+ * After this process all the IRs are loaded with the BYPASS command.
+ * Select Shift-DR state.
+ * Shift in ones and count zeros shifted out. Should be one for each device.
+ * Check this against device count obtained by IR scan above.
*
* 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 i;
- void (*jd_handlers[JTAG_MAX_DEVS])(jtag_dev_t *jd);
+ uint32_t j;
+
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
- * attached SWJ-DP is in SW-DP mode.
+ /* Run throught the SWD to JTAG sequence for the case where an attached SWJ-DP is
+ * in SW-DP mode.
*/
+ DEBUG_INFO("Resetting TAP\n");
#if PC_HOSTED == 1
if (platform_jtagtap_init()) {
DEBUG_WARN("JTAG not available\n");
@@ -81,146 +86,139 @@ int jtag_scan(const uint8_t *irlens)
jtagtap_init();
#endif
jtag_proc.jtagtap_reset();
-#define LOOPS 16
- jtagtap_shift_ir();
- i = LOOPS;
- uint8_t ir_chain[64], *din = ir_chain;
- while (i--) {
- jtag_proc.jtagtap_tdi_tdo_seq(din, (i == 0) ? 1 : 0, ones,
- sizeof(ones) * 8);
- din += sizeof(ones);
- }
- if (!(ir_chain[0] & 1)) {
- DEBUG_WARN("Unexpected IR chain!\n");
- return 0;
+
+ if (irlens) {
+ DEBUG_WARN("Given list of IR lengths, skipping probe\n");
+ DEBUG_INFO("Change state to Shift-IR\n");
+ jtagtap_shift_ir();
+ j = 0;
+ while((jtag_dev_count <= JTAG_MAX_DEVS) &&
+ (jtag_devs[jtag_dev_count].ir_len <= JTAG_MAX_IR_LEN)) {
+ uint32_t irout;
+ if(*irlens == 0)
+ break;
+ 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();
+
+ /* All devices should be in BYPASS now */
+
+ /* Count device on chain */
+ DEBUG_INFO("Change state to Shift-DR\n");
jtagtap_shift_dr();
- i = LOOPS;
- 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;
+ for(i = 0; (jtag_proc.jtagtap_next(0, 1) == 0) && (i <= jtag_dev_count); i++)
jtag_devs[i].dr_postscan = jtag_dev_count - i - 1;
- jtag_devs[i].current_ir = -1;
- j += expected_irlen;
- irbit += expected_irlen;
- DEBUG_INFO("%2d: IDCODE: 0x%08" PRIx32 ", IR len %d %s%s\n", i + 1,
- idcode,jtag_devs[i].ir_len, jtag_devs[i].jd_descr,
- (jd_handlers[i]) ? "" : " (Unhandled) ");
+
+ if(i != jtag_dev_count) {
+ DEBUG_WARN("jtag_scan: Sanity check failed: "
+ "BYPASS dev count doesn't match IR scan\n");
+ jtag_dev_count = -1;
+ 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 */
- 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].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
/*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]);
+ 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
+
/* Check for known devices and handle accordingly */
for(i = 0; i < jtag_dev_count; i++)
- /* Call handler to initialise/probe device further */
- if (jd_handlers[i])
- jd_handlers[i](&jtag_devs[i]);
+ for(j = 0; dev_descr[j].idcode; j++)
+ if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
+ 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;
}
diff --git a/src/target/jtag_scan.h b/src/target/jtag_scan.h
index bc76e0bc..cc6d361a 100644
--- a/src/target/jtag_scan.h
+++ b/src/target/jtag_scan.h
@@ -40,7 +40,7 @@ typedef struct jtag_dev_s {
uint32_t current_ir;
} 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;
void jtag_dev_write_ir(jtag_proc_t *jp, uint8_t jd_index, uint32_t ir);
diff --git a/src/target/kinetis.c b/src/target/kinetis.c
index 7ac9ffa5..5e44bfe8 100644
--- a/src/target/kinetis.c
+++ b/src/target/kinetis.c
@@ -373,7 +373,7 @@ do_common_s32k14x:
}
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;
@@ -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;
target_mem_write32(t, FTFA_FCCOB_0, addr);
if (data) {
- target_mem_write32(t, FTFA_FCCOB_1, *(uint32_t*)&data[0]);
- target_mem_write32(t, FTFA_FCCOB_2, *(uint32_t*)&data[4]);
+ target_mem_write32(t, FTFA_FCCOB_1, data[0]);
+ if (n_items > 1)
+ target_mem_write32(t, FTFA_FCCOB_2, data[1]);
}
/* 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)
{
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 */
if (len > f->blocksize)
len -= f->blocksize;
@@ -450,7 +451,7 @@ static int kl_gen_flash_write(struct target_flash *f,
}
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)
len -= kf->write_len;
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] = (vals[1] & 0xffffff00) | FLASH_SECURITY_BYTE_UNSECURED;
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 {
- 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;
kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD,
- FLASH_SECURITY_BYTE_ADDRESS, (uint8_t*)&vals);
+ FLASH_SECURITY_BYTE_ADDRESS, vals, 1);
}
return 0;
diff --git a/src/target/samd.c b/src/target/samd.c
index f6134088..6f3c574b 100644
--- a/src/target/samd.c
+++ b/src/target/samd.c
@@ -715,11 +715,51 @@ static bool samd_set_flashlock(target *t, uint16_t value, const char **argv)
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)
{
+ unsigned long val;
+
(void)argc;
(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)
@@ -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)
{
+ unsigned long val;
+
(void)argc;
(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)