Merge commit '7d2afcff06f1ccd9fe583d562ddd81e04a17e166' into sam-update

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

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

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

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

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

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# bootprog.py: STM32 SystemMemory Production Programmer -- version 1.1
# 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()

View File

@ -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,27 +57,17 @@ def parse(file,dump_images=False):
print("PARSE ERROR")
def build(file,targets,device=DEFAULT_DEVICE):
data = ''
if (python3):
data = b''
for t,target in enumerate(targets):
tdata = ''
if (python3):
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...'
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

View File

@ -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

View File

@ -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':

View File

@ -1,4 +1,4 @@
#!/usr/bin/python
#!/usr/bin/env python3
"""Pulls nRF51 IDs from openocd's nrf51.c in a form suitable for
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)

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# hexprog.py: Python application to flash a target with an Intel hex file
# Copyright (C) 2011 Black Sphere Technologies
@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
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 <http://gnu.org/licenses/gpl.html>")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
#
# stm32_mem.py: STM32 memory access using USB DFU class
# 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)

View File

@ -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 \

View File

@ -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

View File

@ -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 <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;
if (!found_debuggers && cl_opts->opt_list_only)
DEBUG_WARN("No usable debugger found\n");

View File

@ -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 {

View File

@ -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;
}
}
}
}

View File

@ -1010,7 +1010,7 @@ int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens)
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
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;
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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[];

View File

@ -3,7 +3,6 @@
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* 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
* 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
if (irlens) {
DEBUG_WARN("Given list of IR lengths, skipping probe\n");
DEBUG_INFO("Change state to Shift-IR\n");
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);
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;
}
if (!(ir_chain[0] & 1)) {
DEBUG_WARN("Unexpected IR chain!\n");
return 0;
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++)
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 (jd_handlers[i])
jd_handlers[i](&jtag_devs[i]);
if(dev_descr[j].handler)
dev_descr[j].handler(i, dev_descr[i].idcode);
break;
}
return jtag_dev_count;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
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;
/* 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)