From b1ed55a18fd1fb9abb5e60606bc0140d16c7bc03 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 22 Jan 2022 14:46:47 +0100 Subject: [PATCH 01/17] hosted/firmware/jtag: Fix unhandled exception introduced with da15cc3cb75cc2a9f. Write in endianess independant way. --- src/platforms/hosted/bmp_libusb.c | 2 +- src/platforms/hosted/remote_jtagtap.c | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 21ed9542..aff66f9d 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 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; + } } } } From e3804183f789220ffbb71d3c9012ef7172ad8114 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 23 Jan 2022 12:26:57 +0100 Subject: [PATCH 02/17] bmp_libusb: Fix crash with FTDI devices as outdated variable was used. Triggered by 7b1eb6e6e3. --- src/platforms/hosted/bmp_libusb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index aff66f9d..c6bcf2f4 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -299,7 +299,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"); From 266fe174619cb0af9e74b02e7dc99fac302c9513 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 23 Jan 2022 12:28:38 +0100 Subject: [PATCH 03/17] bmp_libusb: Restrict scope of variable --- src/platforms/hosted/bmp_libusb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index c6bcf2f4..79d4a85b 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -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) { From 6a9b2b82244057e2146929acf7ba296bce4eeab4 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 23 Jan 2022 16:55:38 +0100 Subject: [PATCH 04/17] hosted/ftdi: Fix bad length calculation in MPSSE case of swdptap_seq_in() --- src/platforms/hosted/libftdi_swdptap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 { From ed156076a2f6e97642f06729cb480f0b7c5dc540 Mon Sep 17 00:00:00 2001 From: Paul Mulders Date: Sun, 30 Jan 2022 11:41:01 +0100 Subject: [PATCH 05/17] swlink README: correct SWO/RX2 header location for blue pill --- src/platforms/swlink/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From ca9d8cd0ae43cd15a349698eeda32e7ba163ae5e Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 24 Jan 2022 23:23:10 +0100 Subject: [PATCH 06/17] scripts: fix dfu-convert.py for Python 3 and drop Python 2 support --- scripts/dfu-convert.py | 42 +++++++++-------------------- src/platforms/hydrabus/Makefile.inc | 2 +- 2 files changed, 14 insertions(+), 30 deletions(-) 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/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 From d9cce4d5e8b71e308d631ff494ff3eb11dda6221 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Wed, 26 Jan 2022 00:53:25 +0100 Subject: [PATCH 07/17] scripts: convert bootprog.py to Python 3 Tested with a stm32f100 bootloader. --- scripts/bootprog.py | 52 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 27 deletions(-) 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() From eafc634eba3f5d4238f911b152675e7842998914 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Tue, 8 Feb 2022 00:01:38 +0100 Subject: [PATCH 08/17] scripts: more conversion to Python 3, change the shebang line --- scripts/dfu.py | 6 +++--- scripts/gdb.py | 8 ++++---- scripts/get_openocd_nrf51_ids.py | 6 +++--- scripts/hexprog.py | 6 +++--- scripts/stm32_mem.py | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) 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..7ef525ff 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() @@ -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..0c26e9ca 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 @@ -65,8 +65,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..40d8bd90 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 From f8f2ab201671a6272c600b94b8155116aae898dc Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Sun, 13 Feb 2022 17:04:35 +0100 Subject: [PATCH 09/17] scripts: stm32_mem.py: change some formatting, remove unused imports --- scripts/stm32_mem.py | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/scripts/stm32_mem.py b/scripts/stm32_mem.py index 40d8bd90..a33c12ff 100755 --- a/scripts/stm32_mem.py +++ b/scripts/stm32_mem.py @@ -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) From de834264ab9c199a141c4cc985261aeb30915354 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Sun, 13 Feb 2022 17:15:57 +0100 Subject: [PATCH 10/17] scripts: hexprog.py: minor fixes Unused import and useless semicolon. --- scripts/hexprog.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/hexprog.py b/scripts/hexprog.py index 0c26e9ca..c9356d1c 100755 --- a/scripts/hexprog.py +++ b/scripts/hexprog.py @@ -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 From 2dd3c7bae290aefe40240ef9ae7485e33f25d4d3 Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Sun, 13 Feb 2022 17:17:05 +0100 Subject: [PATCH 11/17] scripts: gdb.py: fix error messages --- scripts/gdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/gdb.py b/scripts/gdb.py index 7ef525ff..30fa20f4 100644 --- a/scripts/gdb.py +++ b/scripts/gdb.py @@ -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 From 91a63fe0e66d120a61d69618c002b667587598f5 Mon Sep 17 00:00:00 2001 From: Qyriad Date: Mon, 26 Jul 2021 12:33:19 -0600 Subject: [PATCH 12/17] Upload builds on push, and test that PRs build, with GH Actions --- .github/workflows/build-and-upload.yml | 36 ++++++++++++++++++++++++++ .github/workflows/build-pr.yml | 29 +++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 .github/workflows/build-and-upload.yml create mode 100644 .github/workflows/build-pr.yml 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 From c1a12edbe9a801051a6bfdfde7264be623bd389f Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 6 May 2021 15:17:50 +0200 Subject: [PATCH 13/17] kinetis: Clarify arguments to kl_gen_command gcc11 chokes on the old setup --- src/target/kinetis.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) 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; From 4045406ed81c7c2f63aa43562e5dd70aaf6df327 Mon Sep 17 00:00:00 2001 From: arpadbuermen <99882173+arpadbuermen@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:54:19 +0100 Subject: [PATCH 14/17] Added support for fine-grained bootloader and flash locking in samd.c lock_flash and lock_bootprot currently support only locking the whole flash and locking the maximal leading flash chunk (32k). An optional numerical parameter is added. It can be specified in decimal or 0x prefixed hexadecimal. For samd21 'lock_bootprot 0' locks the first 32k of flash while 'lock_bootprot 6' locks the first 512 bytes. 'lock_bootprot 0' is equivalent to 'unlock_bootprot'. Similarly, 'lock_flash ' locks the flash segments corresponding to zeros in the binary representation of the given number. 'lock_flash 0xffff' is equivalent to 'unlock_flash'. If the optional parameter is not given both commands work as previously. --- src/target/samd.c | 65 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) 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) From 02d9a1d3cfa99e823278f3fb7cab0fd38e3022da Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 21 Jan 2022 20:47:58 -0500 Subject: [PATCH 15/17] Revert "jtag_scan: Rework chain detection" This reverts commit 2d4a50313596081a64bd1397017985641fd8cad0. --- src/Makefile | 1 + src/platforms/hosted/Makefile.inc | 2 +- src/target/adiv5.h | 8 +- src/target/jtag_scan.c | 282 +++++++++++++++--------------- 4 files changed, 144 insertions(+), 149 deletions(-) diff --git a/src/Makefile b/src/Makefile index 188ecfa4..de053656 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/target/adiv5.h b/src/target/adiv5.h index 95c62f62..bd0985e4 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 diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c index eb1efc80..04a8cca4 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]; 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, jtag_devs[i].jd_idcode); + break; + } + return jtag_dev_count; } From 024152b03e9331aba3e9562ad634a774eece0f10 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 21 Jan 2022 20:52:28 -0500 Subject: [PATCH 16/17] Revert "jtag_scan: Deliver full idcode to the handler." This reverts commit 1845d71f00dda59849254bbddb3c4c00f556d35c. --- src/target/jtag_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c index 04a8cca4..f35aa67c 100644 --- a/src/target/jtag_scan.c +++ b/src/target/jtag_scan.c @@ -215,7 +215,7 @@ int jtag_scan(const uint8_t *irlens) 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, jtag_devs[i].jd_idcode); + dev_descr[j].handler(i, dev_descr[i].idcode); break; } From 7d2afcff06f1ccd9fe583d562ddd81e04a17e166 Mon Sep 17 00:00:00 2001 From: dragonmux Date: Fri, 21 Jan 2022 21:05:13 -0500 Subject: [PATCH 17/17] Revert "jtag: Make jtag_devs argument to jtag_handler." This reverts commit 6308506276d09cde14be2985c0c5a59adc0addc6. --- src/platforms/hosted/stlinkv2.c | 2 +- src/target/adiv5.h | 2 +- src/target/adiv5_jtagdp.c | 6 +++--- src/target/jtag_devs.h | 2 +- src/target/jtag_scan.c | 2 +- src/target/jtag_scan.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) 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/target/adiv5.h b/src/target/adiv5.h index bd0985e4..bcaa1921 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -285,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 f35aa67c..761f5ff0 100644 --- a/src/target/jtag_scan.c +++ b/src/target/jtag_scan.c @@ -30,7 +30,7 @@ #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 */ 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);