Merge commit 'ef816e318391c64014554140be65a5cafc6c8be2' into sam-update

# Conflicts:
#	.gitignore
This commit is contained in:
Jason Kotzin 2022-08-10 17:34:55 -07:00
commit eda19bc28d
44 changed files with 1667 additions and 1610 deletions

1
.gitignore vendored
View File

@ -17,5 +17,6 @@ tags
blackmagic_upgrade
*.exe
.DS_Store
*.elf
.vscode
cscope.out

View File

@ -62,12 +62,16 @@ SRC = \
include $(PLATFORM_DIR)/Makefile.inc
OPT_FLAGS ?= -O2
OPT_FLAGS ?= -Og
CFLAGS += $(OPT_FLAGS)
LDFLAGS += $(OPT_FLAGS)
ifndef TARGET
TARGET=blackmagic
ifdef PC_HOSTED
TARGET = blackmagic
else
TARGET = blackmagic.elf
endif
endif
ifdef NO_OWN_LL
@ -96,19 +100,21 @@ $(TARGET): include/version.h $(OBJ)
@echo " AS $<"
$(Q)$(CC) $(CFLAGS) -c $< -o $@
%.bin: %
ifndef PC_HOSTED
%.bin: %.elf
@echo " OBJCOPY $@"
$(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@
%.hex: %
%.hex: %.elf
@echo " OBJCOPY $@"
$(Q)$(OBJCOPY) -O ihex $^ $@
endif
.PHONY: clean host_clean all_platforms FORCE
clean: host_clean
$(Q)echo " CLEAN"
-$(Q)$(RM) *.o *.d *~ blackmagic $(HOSTFILES)
-$(Q)$(RM) *.o *.d *.elf *~ $(TARGET) $(HOSTFILES)
-$(Q)$(RM) platforms/*/*.o platforms/*/*.d mapfile include/version.h
all_platforms:

View File

@ -154,7 +154,7 @@ bool cmd_version(target *t, int argc, char **argv)
(void)argc;
(void)argv;
#if PC_HOSTED == 1
gdb_outf("Black Magic Probe, PC-Hosted for " PLATFORM_IDENT
gdb_outf("Black Magic Probe, PC-Hosted for " PLATFORM_IDENT()
", Version " FIRMWARE_VERSION "\n");
#else
gdb_outf("Black Magic Probe (Firmware " FIRMWARE_VERSION ") (Hardware Version %d)\n", platform_hwversion());

View File

@ -0,0 +1,21 @@
SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG
CFLAGS +=-I ./target -I./platforms/pc
LDFLAGS += -lusb-1.0
CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1)
ifneq (, $(findstring mingw, $(SYS)))
SRC += serial_win.c
LDFLAGS += -lws2_32
else ifneq (, $(findstring cygwin, $(SYS)))
SRC += serial_win.c
LDFLAGS += -lws2_32
else
SRC += serial_unix.c
endif
VPATH += platforms/pc
SRC += timing.c cl_utils.c utils.c libusb_utils.c
SRC += stlinkv2.c
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c
PC_HOSTED = 1

View File

@ -0,0 +1,147 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Additions by Dave Marples <dave@marples.net>
* Additions by 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "platform.h"
#include "remote.h"
#include "target.h"
#include "bmp_remote.h"
#include <assert.h>
#include <sys/time.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include "adiv5.h"
int remote_init(void)
{
char construct[REMOTE_MAX_MSG_SIZE];
int c = snprintf(construct, REMOTE_MAX_MSG_SIZE, "%s", REMOTE_START_STR);
platform_buffer_write((uint8_t *)construct, c);
c = platform_buffer_read((uint8_t *)construct, REMOTE_MAX_MSG_SIZE);
if ((!c) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr,"Remote Start failed, error %s\n",
c ? (char *)&(construct[1]) : "unknown");
return -1;
}
printf("Remote is %s\n", &construct[1]);
return 0;
}
bool remote_target_get_power(void)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "%s",
REMOTE_PWR_GET_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr," platform_target_get_power failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit (-1);
}
return (construct[1] == '1');
}
void remote_target_set_power(bool power)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_PWR_SET_STR,
power ? '1' : '0');
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_target_set_power failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
}
void remote_srst_set_val(bool assert)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_SRST_SET_STR,
assert ? '1' : '0');
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_srst_set_val failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
}
bool remote_srst_get_val(void)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,"%s",
REMOTE_SRST_GET_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_srst_set_val failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
return (construct[1] == '1');
}
const char *remote_target_voltage(void)
{
static uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE," %s",
REMOTE_VOLTAGE_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_target_voltage failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(- 1);
}
return (char *)&construct[1];
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 Uwe Bonnes
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__BMP_REMOTE_H_)
#define __BMP_REMOTE_H_
#include "swdptap.h"
#include "jtagtap.h"
#define REMOTE_MAX_MSG_SIZE (256)
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
int remote_init(void);
int remote_swdptap_init(swd_proc_t *swd_proc);
int remote_jtagtap_init(jtag_proc_t *jtag_proc);
bool remote_target_get_power(void);
const char *remote_target_voltage(void);
void remote_target_set_power(bool power);
void remote_srst_set_val(bool assert);
bool remote_srst_get_val(void);
const char *platform_target_voltage(void);
#define __BMP_REMOTE_H_
#endif

View File

@ -27,9 +27,9 @@
#include <unistd.h>
#include <sys/time.h>
struct ftdi_context *ftdic;
#include "ftdi_bmp.h"
#include "cl_utils.h"
struct ftdi_context *ftdic;
#define BUF_SIZE 4096
static uint8_t outbuf[BUF_SIZE];
@ -181,39 +181,18 @@ cable_desc_t cable_desc[] = {
},
};
int platform_adiv5_swdp_scan(void)
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
{
return adiv5_swdp_scan();
}
int platform_jtag_scan(const uint8_t *lrlens)
{
return jtag_scan(lrlens);
}
int platform_jtag_dp_init()
{
return 0;
}
void platform_init(int argc, char **argv)
{
BMP_CL_OPTIONS_t cl_opts = {0};
cl_opts.opt_idstring = "Blackmagic Debug Probe for FTDI/MPSSE";
cl_opts.opt_cable = "ftdi";
cl_init(&cl_opts, argc, argv);
int err;
unsigned index = 0;
int ret = -1;
for(index = 0; index < sizeof(cable_desc)/sizeof(cable_desc[0]);
index++)
if (strcmp(cable_desc[index].name, cl_opts.opt_cable) == 0)
if (strcmp(cable_desc[index].name, cl_opts->opt_cable) == 0)
break;
if (index == sizeof(cable_desc)/sizeof(cable_desc[0])){
fprintf(stderr, "No cable matching %s found\n", cl_opts.opt_cable);
exit(-1);
fprintf(stderr, "No cable matching %s found\n", cl_opts->opt_cable);
return -1;
}
active_cable = &cable_desc[index];
@ -233,6 +212,7 @@ void platform_init(int argc, char **argv)
ftdi_get_error_string(ftdic));
abort();
}
info->ftdic = ftdic;
if((err = ftdi_set_interface(ftdic, active_cable->interface)) != 0) {
fprintf(stderr, "ftdi_set_interface: %d: %s\n",
err, ftdi_get_error_string(ftdic));
@ -240,7 +220,7 @@ void platform_init(int argc, char **argv)
}
if((err = ftdi_usb_open_desc(
ftdic, active_cable->vendor, active_cable->product,
active_cable->description, cl_opts.opt_serial)) != 0) {
active_cable->description, cl_opts->opt_serial)) != 0) {
fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
err, ftdi_get_error_string(ftdic));
goto error_1;
@ -261,52 +241,47 @@ void platform_init(int argc, char **argv)
err, ftdi_get_error_string(ftdic));
goto error_2;
}
if (cl_opts.opt_mode != BMP_MODE_DEBUG) {
ret = cl_execute(&cl_opts);
} else {
assert(gdb_if_init() == 0);
return;
}
return 0;
error_2:
ftdi_usb_close(ftdic);
error_1:
ftdi_free(ftdic);
exit(ret);
return -1;
}
void platform_srst_set_val(bool assert)
void libftdi_srst_set_val(bool assert)
{
(void)assert;
platform_buffer_flush();
libftdi_buffer_flush();
}
bool platform_srst_get_val(void) { return false; }
bool libftdi_srst_get_val(void) { return false; }
void platform_buffer_flush(void)
void libftdi_buffer_flush(void)
{
assert(ftdi_write_data(ftdic, outbuf, bufptr) == bufptr);
// printf("FT2232 platform_buffer flush: %d bytes\n", bufptr);
// printf("FT2232 libftdi_buffer flush: %d bytes\n", bufptr);
bufptr = 0;
}
int platform_buffer_write(const uint8_t *data, int size)
int libftdi_buffer_write(const uint8_t *data, int size)
{
if((bufptr + size) / BUF_SIZE > 0) platform_buffer_flush();
if((bufptr + size) / BUF_SIZE > 0) libftdi_buffer_flush();
memcpy(outbuf + bufptr, data, size);
bufptr += size;
return size;
}
int platform_buffer_read(uint8_t *data, int size)
int libftdi_buffer_read(uint8_t *data, int size)
{
int index = 0;
outbuf[bufptr++] = SEND_IMMEDIATE;
platform_buffer_flush();
libftdi_buffer_flush();
while((index += ftdi_read_data(ftdic, data + index, size-index)) != size);
return size;
}
const char *platform_target_voltage(void)
const char *libftdi_target_voltage(void)
{
return "not supported";
}

View File

@ -18,36 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PLATFORM_H
#define __PLATFORM_H
#ifndef __FTDI_BMP_H
#define __FTDI_BMP_H
#include <libftdi1/ftdi.h>
#include "timing.h"
#ifndef _WIN32
# include <alloca.h>
#else
# ifndef alloca
# define alloca __builtin_alloca
# endif
#endif
#define FT2232_VID 0x0403
#define FT2232_PID 0x6010
#define PLATFORM_HAS_DEBUG
#define PLATFORM_IDENT "FTDI/MPSSE"
#define SET_RUN_STATE(state)
#define SET_IDLE_STATE(state)
#define SET_ERROR_STATE(state)
extern struct ftdi_context *ftdic;
void platform_buffer_flush(void);
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
#include "cl_utils.h"
#include "swdptap.h"
#include "jtagtap.h"
typedef struct cable_desc_s {
int vendor;
@ -67,15 +43,19 @@ typedef struct cable_desc_s {
}cable_desc_t;
extern cable_desc_t *active_cable;
extern struct ftdi_context *ftdic;
static inline int platform_hwversion(void)
{
return 0;
}
int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info);
int libftdi_swdptap_init(swd_proc_t *swd_proc);
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc);
void libftdi_buffer_flush(void);
int libftdi_buffer_write(const uint8_t *data, int size);
int libftdi_buffer_read(uint8_t *data, int size);
const char *libftdi_target_voltage(void);
#define MPSSE_TDI 2
#define MPSSE_TDO 4
#define MPSSE_TMS 8
#endif

View File

@ -31,9 +31,10 @@
#include <assert.h>
#include "general.h"
#include "jtagtap.h"
#include "ftdi_bmp.h"
jtag_proc_t jtag_proc;
extern cable_desc_t *active_cable;
extern struct ftdi_context *ftdic;
static void jtagtap_reset(void);
static void jtagtap_tms_seq(uint32_t MS, int ticks);
@ -43,7 +44,7 @@ static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks);
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
int platform_jtagtap_init(void)
int libftdi_jtagtap_init(jtag_proc_t *jtag_proc)
{
assert(ftdic != NULL);
int err = ftdi_usb_purge_buffers(ftdic);
@ -57,14 +58,14 @@ int platform_jtagtap_init(void)
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
return -1;
}
/* Enable MPSSE controller. Pin directions are set later.*/
err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
return -1;
}
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x00, 0x00, SET_BITS_LOW, 0,0,
SET_BITS_HIGH, 0,0};
@ -72,37 +73,32 @@ int platform_jtagtap_init(void)
ftdi_init[5]= active_cable->dbus_ddr;
ftdi_init[7]= active_cable->cbus_data;
ftdi_init[8]= active_cable->cbus_ddr;
platform_buffer_write(ftdi_init, 9);
platform_buffer_flush();
libftdi_buffer_write(ftdi_init, 9);
libftdi_buffer_flush();
jtag_proc.jtagtap_reset = jtagtap_reset;
jtag_proc.jtagtap_next =jtagtap_next;
jtag_proc.jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc.jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
jtag_proc.jtagtap_tdi_seq = jtagtap_tdi_seq;
/* Go to JTAG mode for SWJ-DP */
for (int i = 0; i <= 50; i++)
jtagtap_next(1, 0); /* Reset SW-DP */
jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */
jtagtap_soft_reset();
jtag_proc->jtagtap_reset = jtagtap_reset;
jtag_proc->jtagtap_next =jtagtap_next;
jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc->jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
jtag_proc->jtagtap_tdi_seq = jtagtap_tdi_seq;
return 0;
}
void jtagtap_reset(void)
static void jtagtap_reset(void)
{
jtagtap_soft_reset();
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE| MPSSE_READ_NEG, 0, 0};
uint8_t tmp[3] = {
MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE| MPSSE_READ_NEG, 0, 0};
while(ticks >= 0) {
tmp[1] = ticks<7?ticks-1:6;
tmp[2] = 0x80 | (MS & 0x7F);
platform_buffer_write(tmp, 3);
libftdi_buffer_write(tmp, 3);
MS >>= 7; ticks -= 7;
}
}
@ -120,15 +116,16 @@ static void jtagtap_tdi_tdo_seq(
rticks = ticks & 7;
ticks >>= 3;
uint8_t data[3];
uint8_t cmd = ((DO)? MPSSE_DO_READ : 0) | ((DI)? (MPSSE_DO_WRITE | MPSSE_WRITE_NEG) : 0) | MPSSE_LSB;
uint8_t cmd = ((DO)? MPSSE_DO_READ : 0) |
((DI)? (MPSSE_DO_WRITE | MPSSE_WRITE_NEG) : 0) | MPSSE_LSB;
rsize = ticks;
if(ticks) {
data[0] = cmd;
data[1] = ticks - 1;
data[2] = 0;
platform_buffer_write(data, 3);
libftdi_buffer_write(data, 3);
if (DI)
platform_buffer_write(DI, ticks);
libftdi_buffer_write(DI, ticks);
}
if(rticks) {
int index = 0;
@ -137,21 +134,22 @@ static void jtagtap_tdi_tdo_seq(
data[index++] = rticks - 1;
if (DI)
data[index++] = DI[ticks];
platform_buffer_write(data, index);
libftdi_buffer_write(data, index);
}
if(final_tms) {
int index = 0;
rsize++;
data[index++] = MPSSE_WRITE_TMS | ((DO)? MPSSE_DO_READ : 0) | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
data[index++] = MPSSE_WRITE_TMS | ((DO)? MPSSE_DO_READ : 0) |
MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG;
data[index++] = 0;
if (DI)
data[index++] = (DI[ticks]) >> rticks?0x81 : 0x01;
platform_buffer_write(data, index);
libftdi_buffer_write(data, index);
}
if (DO) {
int index = 0;
uint8_t *tmp = alloca(ticks);
platform_buffer_read(tmp, rsize);
libftdi_buffer_read(tmp, rsize);
if(final_tms) rsize--;
while(rsize--) {
@ -181,10 +179,11 @@ static void jtagtap_tdi_seq(
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t ret;
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_DO_READ | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG, 0, 0};
uint8_t tmp[3] = {MPSSE_WRITE_TMS | MPSSE_DO_READ | MPSSE_LSB |
MPSSE_BITMODE | MPSSE_WRITE_NEG, 0, 0};
tmp[2] = (dTDI?0x80:0) | (dTMS?0x01:0);
platform_buffer_write(tmp, 3);
platform_buffer_read(&ret, 1);
libftdi_buffer_write(tmp, 3);
libftdi_buffer_read(&ret, 1);
ret &= 0x80;
@ -192,4 +191,3 @@ static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
return ret;
}

View File

@ -26,7 +26,7 @@
#include <assert.h>
#include "general.h"
#include "swdptap.h"
#include "ftdi_bmp.h"
static uint8_t olddir = 0;
@ -40,9 +40,7 @@ static uint32_t swdptap_seq_in(int ticks);
static void swdptap_seq_out(uint32_t MS, int ticks);
static void swdptap_seq_out_parity(uint32_t MS, int ticks);
swd_proc_t swd_proc;
int platform_swdptap_init(void)
int libftdi_swdptap_init(swd_proc_t *swd_proc)
{
if (!active_cable->bitbang_tms_in_pin) {
DEBUG("SWD not possible or missing item in cable description.\n");
@ -52,21 +50,21 @@ int platform_swdptap_init(void)
if (err != 0) {
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n",
err, ftdi_get_error_string(ftdic));
abort();
return -1;
}
/* Reset MPSSE controller. */
err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
return -1;
}
/* Enable MPSSE controller. Pin directions are set later.*/
err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE);
if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic));
return -1;;
return -1;
}
uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0,
SET_BITS_HIGH, 0,0};
@ -74,13 +72,13 @@ int platform_swdptap_init(void)
ftdi_init[5]= active_cable->dbus_ddr & ~MPSSE_TD_MASK;
ftdi_init[7]= active_cable->cbus_data;
ftdi_init[8]= active_cable->cbus_ddr;
platform_buffer_write(ftdi_init, 9);
platform_buffer_flush();
libftdi_buffer_write(ftdi_init, 9);
libftdi_buffer_flush();
swd_proc.swdptap_seq_in = swdptap_seq_in;
swd_proc.swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc.swdptap_seq_out = swdptap_seq_out;
swd_proc.swdptap_seq_out_parity = swdptap_seq_out_parity;
swd_proc->swdptap_seq_in = swdptap_seq_in;
swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc->swdptap_seq_out = swdptap_seq_out;
swd_proc->swdptap_seq_out_parity = swdptap_seq_out_parity;
return 0;
}
@ -111,7 +109,7 @@ static void swdptap_turnaround(uint8_t dir)
cmd[index++] = active_cable->dbus_data | MPSSE_MASK;
cmd[index++] = active_cable->dbus_ddr & ~MPSSE_TD_MASK;
}
platform_buffer_write(cmd, index);
libftdi_buffer_write(cmd, index);
}
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
@ -126,11 +124,11 @@ static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
cmd[3] = 0;
swdptap_turnaround(1);
while (index--) {
platform_buffer_write(cmd, 4);
libftdi_buffer_write(cmd, 4);
}
uint8_t data[33];
unsigned int ret = 0;
platform_buffer_read(data, ticks + 1);
libftdi_buffer_read(data, ticks + 1);
if (data[ticks] & active_cable->bitbang_tms_in_pin)
parity ^= 1;
while (ticks--) {
@ -155,11 +153,11 @@ static uint32_t swdptap_seq_in(int ticks)
swdptap_turnaround(1);
while (index--) {
platform_buffer_write(cmd, 4);
libftdi_buffer_write(cmd, 4);
}
uint8_t data[32];
uint32_t ret = 0;
platform_buffer_read(data, ticks);
libftdi_buffer_read(data, ticks);
while (ticks--) {
if (data[ticks] & active_cable->bitbang_tms_in_pin)
ret |= (1 << ticks);
@ -185,7 +183,7 @@ static void swdptap_seq_out(uint32_t MS, int ticks)
ticks = 0;
}
}
platform_buffer_write(cmd, index);
libftdi_buffer_write(cmd, index);
}
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
@ -216,5 +214,5 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks)
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 0;
cmd[index++] = parity;
platform_buffer_write(cmd, index);
libftdi_buffer_write(cmd, index);
}

View File

@ -0,0 +1,418 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020
* Written by 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Handle different BMP pc-hosted platforms/
*/
#include "general.h"
#include "swdptap.h"
#include "jtagtap.h"
#include "target.h"
#include "target_internal.h"
#include "adiv5.h"
#include "timing.h"
#include "cl_utils.h"
#include "gdb_if.h"
#include <signal.h>
#include "bmp_remote.h"
#include "stlinkv2.h"
#include "ftdi_bmp.h"
#define VENDOR_ID_BMP 0x1d50
#define PRODUCT_ID_BMP 0x6018
#define VENDOR_ID_STLINK 0x0483
#define PRODUCT_ID_STLINK_MASK 0xffe0
#define PRODUCT_ID_STLINK_GROUP 0x3740
#define PRODUCT_ID_STLINKV1 0x3744
#define PRODUCT_ID_STLINKV2 0x3748
#define PRODUCT_ID_STLINKV21 0x374b
#define PRODUCT_ID_STLINKV21_MSD 0x3752
#define PRODUCT_ID_STLINKV3 0x374f
#define PRODUCT_ID_STLINKV3E 0x374e
bmp_info_t info;
swd_proc_t swd_proc;
jtag_proc_t jtag_proc;
static void exit_function(void)
{
if(info.usb_link) {
libusb_free_transfer(info.usb_link->req_trans);
libusb_free_transfer(info.usb_link->rep_trans);
if (info.usb_link->ul_libusb_device_handle) {
libusb_release_interface (
info.usb_link->ul_libusb_device_handle, 0);
libusb_close(info.usb_link->ul_libusb_device_handle);
}
}
switch (info.bmp_type) {
default:
break;
}
fflush(stdout);
}
/* SIGTERM handler. */
static void sigterm_handler(int sig)
{
(void)sig;
exit(0);
}
static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
{
libusb_device **devs;
int n_devs = libusb_get_device_list(info->libusb_ctx, &devs);
if (n_devs < 0) {
fprintf(stderr, "WARN:libusb_get_device_list() failed");
return -1;
}
bool report = false;
int found_debuggers;
struct libusb_device_descriptor desc;
char serial[64];
char manufacturer[128];
char product[128];
bmp_type_t type = BMP_TYPE_NONE;
rescan:
found_debuggers = 0;
for (int i = 0; devs[i]; i++) {
libusb_device *dev = devs[i];
int res = libusb_get_device_descriptor(dev, &desc);
if (res < 0) {
fprintf(stderr, "WARN: libusb_get_device_descriptor() failed: %s",
libusb_strerror(res));
libusb_free_device_list(devs, 1);
continue;
}
libusb_device_handle *handle;
res = libusb_open(dev, &handle);
if (res != LIBUSB_SUCCESS) {
fprintf(stderr,"WARN: Open failed\n");
continue;
}
res = libusb_get_string_descriptor_ascii(
handle, desc.iSerialNumber, (uint8_t*)serial,
sizeof(serial));
if (res <= 0) {
/* This can fail for many devices. Continue silent!*/
libusb_close(handle);
continue;
}
if (cl_opts->opt_serial && !strstr(serial, cl_opts->opt_serial)) {
libusb_close(handle);
continue;
}
res = libusb_get_string_descriptor_ascii(
handle, desc.iManufacturer, (uint8_t*)manufacturer,
sizeof(manufacturer));
if (res > 0) {
res = libusb_get_string_descriptor_ascii(
handle, desc.iProduct, (uint8_t*)product,
sizeof(product));
if (res <= 0) {
fprintf(stderr, "WARN:"
"libusb_get_string_descriptor_ascii "
"for ident_string failed: %s\n",
libusb_strerror(res));
libusb_close(handle);
continue;
}
}
libusb_close(handle);
if (cl_opts->opt_ident_string) {
char *match_manu = NULL;
char *match_product = NULL;
match_manu = strstr(manufacturer, cl_opts->opt_ident_string);
match_product = strstr(product, cl_opts->opt_ident_string);
if (!match_manu && !match_product) {
continue;
}
}
/* Either serial and/or ident_string match or are not given.
* Check type.*/
if ((desc.idVendor == VENDOR_ID_BMP) &&
(desc.idProduct == PRODUCT_ID_BMP)) {
type = BMP_TYPE_BMP;
} else if (desc.idVendor == VENDOR_ID_STLINK) {
if ((desc.idProduct == PRODUCT_ID_STLINKV2) ||
(desc.idProduct == PRODUCT_ID_STLINKV21) ||
(desc.idProduct == PRODUCT_ID_STLINKV21_MSD) ||
(desc.idProduct == PRODUCT_ID_STLINKV3) ||
(desc.idProduct == PRODUCT_ID_STLINKV3E)) {
type = BMP_TYPE_STLINKV2;
} else {
if (desc.idProduct == PRODUCT_ID_STLINKV1)
fprintf(stderr, "INFO: STLINKV1 not supported\n");
continue;
}
} else {
continue;
}
found_debuggers ++;
if (report) {
printf("%2d: %s, %s, %s\n", found_debuggers,
serial,
manufacturer,product);
}
info->vid = desc.idVendor;
info->pid = desc.idProduct;
info->bmp_type = type;
strncpy(info->serial, serial, sizeof(info->serial));
strncpy(info->product, product, sizeof(info->product));
strncpy(info->manufacturer, manufacturer, sizeof(info->manufacturer));
if (cl_opts->opt_position &&
(cl_opts->opt_position == found_debuggers)) {
found_debuggers = 1;
break;
}
}
if (found_debuggers > 1) {
if (!report) {
printf("%d debuggers found! Select with -P <num>, -s <string> "
"and/or -S <string>\n",
found_debuggers);
report = true;
goto rescan;
}
}
libusb_free_device_list(devs, 1);
return (found_debuggers == 1) ? 0 : -1;
}
void platform_init(int argc, char **argv)
{
BMP_CL_OPTIONS_t cl_opts = {0};
cl_opts.opt_idstring = "Blackmagic PC-Hosted";
cl_init(&cl_opts, argc, argv);
atexit(exit_function);
signal(SIGTERM, sigterm_handler);
signal(SIGINT, sigterm_handler);
int res = libusb_init(&info.libusb_ctx);
if (res) {
fprintf(stderr, "Fatal: Failed to get USB context: %s\n",
libusb_strerror(res));
exit(-1);
}
if (cl_opts.opt_device) {
info.bmp_type = BMP_TYPE_BMP;
} else if (cl_opts.opt_cable) {
/* check for libftdi devices*/
res = ftdi_bmp_init(&cl_opts, &info);
if (res)
exit(-1);
else
info.bmp_type = BMP_TYPE_LIBFTDI;
} else if (find_debuggers(&cl_opts, &info)) {
exit(-1);
}
printf("Using %s %s %s\n", info.serial,
info.manufacturer,
info.product);
switch (info.bmp_type) {
case BMP_TYPE_BMP:
if (serial_open(&cl_opts, info.serial))
exit(-1);
remote_init();
break;
case BMP_TYPE_STLINKV2:
if (stlink_init( &info))
exit(-1);
break;
case BMP_TYPE_LIBFTDI:
break;
default:
exit(-1);
}
int ret = -1;
if (cl_opts.opt_mode != BMP_MODE_DEBUG) {
ret = cl_execute(&cl_opts);
} else {
gdb_if_init();
return;
}
exit(ret);
}
int platform_adiv5_swdp_scan(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
return adiv5_swdp_scan();
break;
case BMP_TYPE_STLINKV2:
{
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!stlink_enter_debug_swd(&info, dp)) {
adiv5_dp_init(dp);
if (target_list)
return 1;
}
free(dp);
break;
}
default:
return 0;
}
return 0;
}
int platform_swdptap_init(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_swdptap_init(&swd_proc);
case BMP_TYPE_STLINKV2:
return 0;
break;
case BMP_TYPE_LIBFTDI:
return libftdi_swdptap_init(&swd_proc);
default:
return -1;
}
return -1;
}
int platform_jtag_scan(const uint8_t *lrlens)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
return jtag_scan(lrlens);
case BMP_TYPE_STLINKV2:
return jtag_scan_stlinkv2(&info, lrlens);
default:
return -1;
}
return -1;
}
int platform_jtagtap_init(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_jtagtap_init(&jtag_proc);
case BMP_TYPE_STLINKV2:
return 0;
case BMP_TYPE_LIBFTDI:
return libftdi_jtagtap_init(&jtag_proc);
default:
return -1;
}
return -1;
}
void platform_adiv5_dp_defaults(ADIv5_DP_t *dp)
{
switch (info.bmp_type) {
case BMP_TYPE_STLINKV2:
return stlink_adiv5_dp_defaults(dp);
default:
break;
}
}
int platform_jtag_dp_init(ADIv5_DP_t *dp)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI:
return 0;
case BMP_TYPE_STLINKV2:
return stlink_jtag_dp_init(dp);
default:
return 0;
}
return 0;
}
char *platform_ident(void)
{
switch (info.bmp_type) {
case BMP_TYPE_NONE:
return "NONE";
case BMP_TYPE_BMP:
return "BMP";
case BMP_TYPE_STLINKV2:
return "STLINKV2";
case BMP_TYPE_LIBFTDI:
return "LIBFTDI";
case BMP_TYPE_CMSIS_DAP:
return "CMSIS_DAP";
case BMP_TYPE_JLINK:
return "JLINK";
}
return NULL;
}
const char *platform_target_voltage(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_target_voltage();
case BMP_TYPE_STLINKV2:
return stlink_target_voltage(&info);
case BMP_TYPE_LIBFTDI:
return libftdi_target_voltage();
default:
break;
}
return NULL;
}
void platform_srst_set_val(bool assert)
{
switch (info.bmp_type) {
case BMP_TYPE_STLINKV2:
return stlink_srst_set_val(&info, assert);
case BMP_TYPE_BMP:
return remote_srst_set_val(assert);
default:
break;
}
}
bool platform_srst_get_val(void)
{
switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_srst_get_val();
case BMP_TYPE_STLINKV2:
return stlink_srst_get_val();
default:
break;
}
return false;
}
void platform_buffer_flush(void)
{
switch (info.bmp_type) {
case BMP_TYPE_LIBFTDI:
return libftdi_buffer_flush();
default:
break;
}
}

View File

@ -0,0 +1,41 @@
#ifndef __PLATFORM_H
#define __PLATFORM_H
#include <libusb-1.0/libusb.h>
#include "libusb_utils.h"
#include <libftdi1/ftdi.h>
#include "timing.h"
char *platform_ident(void);
void platform_buffer_flush(void);
#define PLATFORM_IDENT() "NONE"
#define SET_IDLE_STATE(x)
#define SET_RUN_STATE(x)
typedef enum bmp_type_s {
BMP_TYPE_NONE = 0,
BMP_TYPE_BMP,
BMP_TYPE_STLINKV2,
BMP_TYPE_LIBFTDI,
BMP_TYPE_CMSIS_DAP,
BMP_TYPE_JLINK
} bmp_type_t;
typedef struct bmp_info_s {
bmp_type_t bmp_type;
libusb_context *libusb_ctx;
struct ftdi_context *ftdic;
usb_link_t *usb_link;
unsigned int vid;
unsigned int pid;
char dev;
char serial[64];
char manufacturer[128];
char product[128];
} bmp_info_t;
extern bmp_info_t info;
#endif

View File

@ -0,0 +1,165 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2008 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Low level JTAG implementation using FT2232 with libftdi.
*
* Issues:
* Should share interface with swdptap.c or at least clean up...
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include "remote.h"
#include "jtagtap.h"
#include "bmp_remote.h"
static void jtagtap_reset(void);
static void jtagtap_tms_seq(uint32_t MS, int ticks);
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks);
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
int remote_jtagtap_init(jtag_proc_t *jtag_proc)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "%s",
REMOTE_JTAG_INIT_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_init failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
jtag_proc->jtagtap_reset = jtagtap_reset;
jtag_proc->jtagtap_next =jtagtap_next;
jtag_proc->jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc->jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
jtag_proc->jtagtap_tdi_seq = jtagtap_tdi_seq;
return 0;
}
/* See remote.c/.h for protocol information */
static void jtagtap_reset(void)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, "%s",
REMOTE_JTAG_RESET_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_reset failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_JTAG_TMS_STR, ticks, MS);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_tms_seq failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
}
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
uint64_t DIl=*(uint64_t *)DI;
if(!ticks || !DI) return;
/* Reduce the length of DI according to the bits we're transmitting */
DIl &= (1LL << (ticks + 1))-1;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_JTAG_TDIDO_STR,
final_tms ? REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS,
ticks, DIl);
platform_buffer_write(construct,s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_tms_seq failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
if (DO) {
uint64_t DOl = remotehston(-1, (char *)&construct[1]);
*(uint64_t *)DO = DOl;
}
}
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks)
{
return jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
}
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_JTAG_NEXT,
dTMS ? '1' : '0', dTDI ? '1' : '0');
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_next failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
return remotehston(-1, (char *)&construct[1]);
}

View File

@ -0,0 +1,128 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2018 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* MPSSE bit-banging SW-DP interface over FTDI with loop unrolled.
* Speed is sensible.
*/
#include <stdio.h>
#include <assert.h>
#include "general.h"
#include "remote.h"
#include "bmp_remote.h"
static bool swdptap_seq_in_parity(uint32_t *res, int ticks);
static uint32_t swdptap_seq_in(int ticks);
static void swdptap_seq_out(uint32_t MS, int ticks);
static void swdptap_seq_out_parity(uint32_t MS, int ticks);
int remote_swdptap_init(swd_proc_t *swd_proc)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct,"%s", REMOTE_SWDP_INIT_STR);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_init failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
swd_proc->swdptap_seq_in = swdptap_seq_in;
swd_proc->swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc->swdptap_seq_out = swdptap_seq_out;
swd_proc->swdptap_seq_out_parity = swdptap_seq_out_parity;
return 0;
}
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct, REMOTE_SWDP_IN_PAR_STR, ticks);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_seq_in_parity failed, error %s\n",
s ? (char *)&(construct[1]) : "short response");
exit(-1);
}
*res=remotehston(-1, (char *)&construct[1]);
return (construct[0] != REMOTE_RESP_OK);
}
static uint32_t swdptap_seq_in(int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct, REMOTE_SWDP_IN_STR, ticks);
platform_buffer_write(construct,s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_seq_in failed, error %s\n",
s ? (char *)&(construct[1]) : "short response");
exit(-1);
}
return remotehston(-1,(char *)&construct[1]);
}
static void swdptap_seq_out(uint32_t MS, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct,REMOTE_SWDP_OUT_STR, ticks, MS);
platform_buffer_write(construct, s);
s=platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_seq_out failed, error %s\n",
s ? (char *)&(construct[1]) : "short response");
exit(-1);
}
}
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
s = sprintf((char *)construct, REMOTE_SWDP_OUT_PAR_STR, ticks, MS);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[1] == REMOTE_RESP_ERR)){
fprintf(stderr, "swdptap_seq_out_parity failed, error %s\n",
s ? (char *)&(construct[2]) : "short response");
exit(-1);
}
}

View File

@ -24,28 +24,18 @@
#define STLINK_DEBUG_PORT_ACCESS 0xffff
void stlink_init(int argc, char **argv);
int stlink_init(bmp_info_t *info);
int stlink_hwversion(void);
void stlink_leave_state(void);
const char *stlink_target_voltage(void);
void stlink_srst_set_val(bool assert);
int stlink_enter_debug_swd(void);
int stlink_enter_debug_jtag(void);
int stlink_read_idcodes(uint32_t *);
uint32_t stlink_read_coreid(void);
int stlink_read_dp_register(uint16_t port, uint16_t addr, uint32_t *res);
int stlink_write_dp_register(uint16_t port, uint16_t addr, uint32_t val);
const char *stlink_target_voltage(bmp_info_t *info);
void stlink_srst_set_val(bmp_info_t *info, bool assert);
bool stlink_srst_get_val(void);
int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp);
uint32_t stlink_dp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
uint32_t stlink_dp_read(ADIv5_DP_t *dp, uint16_t addr);
uint32_t stlink_dp_error(ADIv5_DP_t *dp);
void stlink_dp_abort(ADIv5_DP_t *dp, uint32_t abort);
int stlink_open_ap(uint8_t ap);
void stlink_close_ap(uint8_t ap);
void stlink_regs_read(ADIv5_AP_t *ap, void *data);
uint32_t stlink_reg_read(ADIv5_AP_t *ap, int idx);
void stlink_reg_write(ADIv5_AP_t *ap, int num, uint32_t val);
const char *stlink_target_voltage(bmp_info_t *info);
void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp);
int stlink_jtag_dp_init(ADIv5_DP_t *dp);
int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens);
void stlink_exit_function(bmp_info_t *info);
extern int debug_level;
# define DEBUG_STLINK if (debug_level > 0) printf
# define DEBUG_USB if (debug_level > 1) printf

View File

@ -1,13 +0,0 @@
SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG
CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1)
ifneq (, $(findstring mingw, $(SYS)))
LDFLAGS += -lusb-1.0 -lws2_32
else ifneq (, $(findstring cygwin, $(SYS)))
LDFLAGS += -lusb-1.0 -lws2_32
endif
VPATH += platforms/pc
SRC += timing.c cl_utils.c utils.c
CFLAGS +=-I ./target -I./platforms/pc
PC_HOSTED = 1

View File

@ -1,14 +0,0 @@
Compiling on windows
You can crosscompile blackmagic for windows with mingw or on windows
with cygwin. For compilation, headers for libftdi1 and libusb-1.0 are
needed. For running, libftdi1.dll and libusb-1.0.dll are needed and
the executable must be able to find them. Mingw on cygwin does not provide
a libftdi package yet.
To prepare libusb access to the ftdi device, run zadig https://zadig.akeo.ie/.
Choose WinUSB(libusb-1.0) for the BMP Ftdi device.
Running cygwin/blackmagic in a cygwin console, the program does not react
on ^C. In another console, run "ps ax" to find the WINPID of the process
and then "taskkill /F ?PID (WINPID)".

View File

@ -30,7 +30,7 @@ SRC += cdcacm.c \
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex
blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o
blackmagic_dfu.elf: usbdfu.o dfucore.o dfu_f1.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT)

View File

@ -1,16 +0,0 @@
TARGET=blackmagic_hosted
SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG
CFLAGS +=-I ./target -I./platforms/pc
ifneq (, $(findstring mingw, $(SYS)))
SRC += serial_win.c
LDFLAGS += -lws2_32
else ifneq (, $(findstring cygwin, $(SYS)))
SRC += serial_win.c
LDFLAGS += -lws2_32
else
SRC += serial_unix.c
endif
VPATH += platforms/pc
SRC += cl_utils.c timing.c utils.c
PC_HOSTED = 1

View File

@ -1,40 +0,0 @@
PC Hosted variant
THIS IS INCOMPLETE - ONLY SUPPORTS SWD AT THE MOMENT
This variant will use any BMP probe with recent firmware as a remote
actuator, with the actual probe code running on the PC. The BMP itself
is 'dumb' and doesn't do anything (although any secondary serial port
remains available).
To use it, compile for the pc-hosted target and then connect to your normal
BMP GDB port;
src/blackmagic -s /dev/ttyACM0
...you can then connect your gdb session to localhost:2000 for all your
debugging goodness;
$arm-eabi-none-gdb
(gdb) monitor swdp_scan
Target voltage: not supported
Available Targets:
No. Att Driver
1 STM32F1 medium density M3/M4
(gdb) attach 1
Attaching to program: Builds/blackmagic/src/blackmagic, Remote target
0x08001978 in ?? ()
(gdb) file src/blackmagic
A program is being debugged already.
Are you sure you want to change the file? (y or n) y
Load new symbol table from "src/blackmagic"? (y or n) y
Reading symbols from src/blackmagic...
(gdb) load
Loading section .text, size 0x1201c lma 0x8002000
Loading section .data, size 0xd8 lma 0x801401c
Start address 0x800d9fc, load size 73972
Transfer rate: 2 KB/sec, 960 bytes/write.
(gdb)
...note that the speed of the probe in this way is about 10 times less than
running native. This build is intended for debug and development only.

View File

@ -1,161 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2008 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Low level JTAG implementation using FT2232 with libftdi.
*
* Issues:
* Should share interface with swdptap.c or at least clean up...
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include "remote.h"
#include "jtagtap.h"
jtag_proc_t jtag_proc;
static void jtagtap_reset(void);
static void jtagtap_tms_seq(uint32_t MS, int ticks);
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks);
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks);
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI);
int platform_jtagtap_init(void)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_JTAG_INIT_STR);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"jtagtap_init failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
jtag_proc.jtagtap_reset = jtagtap_reset;
jtag_proc.jtagtap_next =jtagtap_next;
jtag_proc.jtagtap_tms_seq = jtagtap_tms_seq;
jtag_proc.jtagtap_tdi_tdo_seq = jtagtap_tdi_tdo_seq;
jtag_proc.jtagtap_tdi_seq = jtagtap_tdi_seq;
return 0;
}
/* See remote.c/.h for protocol information */
static void jtagtap_reset(void)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_JTAG_RESET_STR);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"jtagtap_reset failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_JTAG_TMS_STR,ticks,MS);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"jtagtap_tms_seq failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
}
static void jtagtap_tdi_tdo_seq(
uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
uint64_t DIl=*(uint64_t *)DI;
if(!ticks || !DI) return;
/* Reduce the length of DI according to the bits we're transmitting */
DIl &= (1LL << (ticks + 1)) - 1;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_JTAG_TDIDO_STR,final_tms?REMOTE_TDITDO_TMS:REMOTE_TDITDO_NOTMS,ticks,DIl);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"jtagtap_tms_seq failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
if (DO) {
uint64_t DOl = remotehston(-1, (char *)&construct[1]);
*(uint64_t *)DO = DOl;
}
}
static void jtagtap_tdi_seq(
const uint8_t final_tms, const uint8_t *DI, int ticks)
{
return jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
}
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_JTAG_NEXT,dTMS?'1':'0',dTDI?'1':'0');
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"jtagtap_next failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
return remotehston(-1,(char *)&construct[1]);
}

View File

@ -1,183 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Additions by Dave Marples <dave@marples.net>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "platform.h"
#include "remote.h"
#include "target.h"
#include <assert.h>
#include <sys/time.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include "cl_utils.h"
static BMP_CL_OPTIONS_t cl_opts; /* Portable way to nullify the struct*/
int platform_adiv5_swdp_scan(void)
{
return adiv5_swdp_scan();
}
int platform_jtag_scan(const uint8_t *lrlens)
{
return jtag_scan(lrlens);
}
int platform_jtag_dp_init()
{
return 0;
}
void platform_init(int argc, char **argv)
{
cl_opts.opt_idstring = "Blackmagic Debug Probe Remote";
cl_init(&cl_opts, argc, argv);
char construct[PLATFORM_MAX_MSG_SIZE];
printf("\nBlack Magic Probe (" FIRMWARE_VERSION ")\n");
printf("Copyright (C) 2019 Black Sphere Technologies Ltd.\n");
printf("License GPLv3+: GNU GPL version 3 or later "
"<http://gnu.org/licenses/gpl.html>\n\n");
if (serial_open(&cl_opts))
exit(-1);
int c=snprintf(construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_START_STR);
platform_buffer_write((uint8_t *)construct,c);
c=platform_buffer_read((uint8_t *)construct, PLATFORM_MAX_MSG_SIZE);
if ((!c) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"Remote Start failed, error %s\n",c?(char *)&(construct[1]):"unknown");
exit(-1);
}
printf("Remote is %s\n",&construct[1]);
if (cl_opts.opt_mode != BMP_MODE_DEBUG) {
int ret = cl_execute(&cl_opts);
if (cl_opts.opt_tpwr)
platform_target_set_power(0);
serial_close();
exit(ret);
} else {
assert(gdb_if_init() == 0);
}
}
bool platform_target_get_power(void)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_PWR_GET_STR);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"platform_target_get_power failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
return (construct[1]=='1');
}
void platform_target_set_power(bool power)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_PWR_SET_STR,power?'1':'0');
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"platform_target_set_power failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
}
void platform_srst_set_val(bool assert)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,REMOTE_SRST_SET_STR,assert?'1':'0');
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"platform_srst_set_val failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
}
bool platform_srst_get_val(void)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_SRST_GET_STR);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"platform_srst_set_val failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
return (construct[1]=='1');
}
void platform_buffer_flush(void)
{
}
const char *platform_target_voltage(void)
{
static uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=snprintf((char *)construct,PLATFORM_MAX_MSG_SIZE,"%s",REMOTE_VOLTAGE_STR);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"platform_target_voltage failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
return (char *)&construct[1];
}

View File

@ -1,55 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Additions by Dave Marples <dave@marples.net>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PLATFORM_H
#define __PLATFORM_H
#include "timing.h"
#ifndef _WIN32
# include <alloca.h>
#else
# ifndef alloca
# define alloca __builtin_alloca
# endif
#endif
#define PLATFORM_HAS_DEBUG
#define PLATFORM_HAS_POWER_SWITCH
#define PLATFORM_MAX_MSG_SIZE (256)
#define PLATFORM_IDENT "PC-HOSTED"
#define BOARD_IDENT PLATFORM_IDENT
#define SET_RUN_STATE(state)
#define SET_IDLE_STATE(state)
#define SET_ERROR_STATE(state)
/* Allow 100mS for responses to reach us */
#define RESP_TIMEOUT (100)
void platform_buffer_flush(void);
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
static inline int platform_hwversion(void)
{
return 0;
}
#endif

View File

@ -1,133 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2018 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* MPSSE bit-banging SW-DP interface over FTDI with loop unrolled.
* Speed is sensible.
*/
#include <stdio.h>
#include <assert.h>
#include "general.h"
#include "swdptap.h"
#include "remote.h"
static bool swdptap_seq_in_parity(uint32_t *res, int ticks);
static uint32_t swdptap_seq_in(int ticks);
static void swdptap_seq_out(uint32_t MS, int ticks);
static void swdptap_seq_out_parity(uint32_t MS, int ticks);
swd_proc_t swd_proc;
int platform_swdptap_init(void)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=sprintf((char *)construct,"%s",REMOTE_SWDP_INIT_STR);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((!s) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"swdptap_init failed, error %s\n",s?(char *)&(construct[1]):"unknown");
exit(-1);
}
swd_proc.swdptap_seq_in = swdptap_seq_in;
swd_proc.swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc.swdptap_seq_out = swdptap_seq_out;
swd_proc.swdptap_seq_out_parity = swdptap_seq_out_parity;
return 0;
}
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=sprintf((char *)construct,REMOTE_SWDP_IN_PAR_STR,ticks);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((s<2) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"swdptap_seq_in_parity failed, error %s\n",s?(char *)&(construct[1]):"short response");
exit(-1);
}
*res=remotehston(-1,(char *)&construct[1]);
return (construct[0]!=REMOTE_RESP_OK);
}
static uint32_t swdptap_seq_in(int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=sprintf((char *)construct,REMOTE_SWDP_IN_STR,ticks);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((s<2) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"swdptap_seq_in failed, error %s\n",s?(char *)&(construct[1]):"short response");
exit(-1);
}
return remotehston(-1,(char *)&construct[1]);
}
static void swdptap_seq_out(uint32_t MS, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=sprintf((char *)construct,REMOTE_SWDP_OUT_STR,ticks,MS);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((s<1) || (construct[0]==REMOTE_RESP_ERR))
{
fprintf(stderr,"swdptap_seq_out failed, error %s\n",s?(char *)&(construct[1]):"short response");
exit(-1);
}
}
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
s=sprintf((char *)construct,REMOTE_SWDP_OUT_PAR_STR,ticks,MS);
platform_buffer_write(construct,s);
s=platform_buffer_read(construct, PLATFORM_MAX_MSG_SIZE);
if ((s<1) || (construct[1]==REMOTE_RESP_ERR))
{
fprintf(stderr,"swdptap_seq_out_parity failed, error %s\n",s?(char *)&(construct[2]):"short response");
exit(-1);
}
}

View File

@ -1,14 +0,0 @@
TARGET=blackmagic_stlinkv2
SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DSTLINKV2 -DJTAG_HL -DENABLE_DEBUG
CFLAGS +=-I ./target -I./platforms/pc
LDFLAGS += -lusb-1.0
ifneq (, $(findstring mingw, $(SYS)))
LDFLAGS += -lws2_32
else ifneq (, $(findstring cygwin, $(SYS)))
LDFLAGS += -lws2_32
endif
VPATH += platforms/pc
SRC += timing.c stlinkv2.c cl_utils.c utils.c
OWN_HL = 1
PC_HOSTED = 1

View File

@ -1,25 +0,0 @@
ST-Link V2/3 with original STM firmware as Blackmagic Debug Probes
Recent STM ST-LINK firmware revision (V3 and V2 >= J32) expose all
functionality that BMP needs. This platform implements blackmagic debug
probe for the STM ST-LINK.
Use at your own risk, but report or better fix problems.
Compile with "make PROBE_HOST=pc-stlinkv2"
Run the resulting blackmagic_stlinkv2 executable to start the gdb server.
You can also use on the command line alone, e.g
- "blackmagic_stlinkv2 -t" to scan and display the results of the scan
- "blackmagic_stlinkv2 <file.bin>" to flash <file.bin> at 0x08000000
- "blackmagic_stlinkv2 -h" for more options
Cross-compling for windows with mingw succeeds.
Drawback:
- JTAG does not work for chains with multiple devices.
- ST-LINKV3 seem to only work on STM32 devices.
- St-LINKV3 needs connect under reset on more devices than V2
ToDo:
- Implement an SWO server

View File

@ -1,115 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019 2019 Uwe Bonnes
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "platform.h"
#include "target.h"
#include "target_internal.h"
#include "swdptap.h"
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
#include "adiv5.h"
#include "stlinkv2.h"
int platform_hwversion(void)
{
return stlink_hwversion();
}
const char *platform_target_voltage(void)
{
return stlink_target_voltage();
}
int platform_swdptap_init(void)
{
return 0;
}
swd_proc_t swd_proc;
jtag_proc_t jtag_proc;
static int adiv5_swdp_scan_stlinkv2(void)
{
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (stlink_enter_debug_swd())
return 0;
dp->idcode = stlink_read_coreid();
dp->dp_read = stlink_dp_read;
dp->error = stlink_dp_error;
dp->low_access = stlink_dp_low_access;
dp->abort = stlink_dp_abort;
stlink_dp_error(dp);
adiv5_dp_init(dp);
return target_list?1:0;
return 0;
}
int platform_adiv5_swdp_scan(void)
{
return adiv5_swdp_scan_stlinkv2();
}
int platform_jtag_scan(const uint8_t *lrlens)
{
return jtag_scan_stlinkv2(lrlens);
}
void platform_init(int argc, char **argv)
{
stlink_init(argc, argv);
}
static bool srst_status = false;
void platform_srst_set_val(bool assert)
{
stlink_srst_set_val(assert);
srst_status = assert;
}
bool platform_srst_get_val(void) { return srst_status; }
void platform_buffer_flush(void)
{
}
int platform_buffer_write(const uint8_t *data, int size)
{
(void) data;
(void) size;
return size;
}
int platform_buffer_read(uint8_t *data, int size)
{
(void) data;
return size;
}
int platform_jtagtap_init(void)
{
return 0;
}

View File

@ -1,48 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PLATFORM_H
#define __PLATFORM_H
#include <libusb-1.0/libusb.h>
#include "timing.h"
#ifndef _WIN32
# include <alloca.h>
#else
# ifndef alloca
# define alloca __builtin_alloca
# endif
#endif
#define PLATFORM_HAS_DEBUG
#define PLATFORM_IDENT "StlinkV2/3"
#define SET_RUN_STATE(state)
void stlink_check_detach(int state);
#define SET_IDLE_STATE(state) stlink_check_detach(state)
//#define SET_ERROR_STATE(state)
void platform_buffer_flush(void);
int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size);
int jtag_scan_stlinkv2(const uint8_t *irlens);
#endif

View File

@ -120,27 +120,29 @@ static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
printf("\t-h\t\t: This help.\n");
printf("\t-v[1|2]\t\t: Increasing verbosity\n");
printf("\t-d \"path\"\t: Use serial device at \"path\"\n");
printf("\t-P <num>\t: Use device found as <num>");
printf("\t-P <num>\t: Use debugger found at position <num>\n");
printf("\t-n <num>\t: Use target device found at position <num>\n");
printf("\t-s \"string\"\t: Use dongle with (partial) "
"serial number \"string\"\n");
printf("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n");
printf("\t-n\t\t: Exit immediate if no device found\n");
printf("\tRun mode related options:\n");
printf("\tDefault mode is to start the debug server at :2000\n");
printf("\t-j\t\t: Use JTAG. SWD is default.\n");
printf("\t-C\t\t: Connect under reset\n");
printf("\t-t\t\t: Scan SWD, with no target found scan jtag and exit\n");
printf("\t-t\t\t: Scan SWD and display information about connected"
"devices\n");
printf("\t-E\t\t: Erase flash until flash end or for given size\n");
printf("\t-V\t\t: Verify flash against binary file\n");
printf("\t-r\t\t: Read flash and write to binary file\n");
printf("\t-p\t\t: Supplies power to the target (where applicable)\n");
printf("\t-R\t\t: Reset device\n");
printf("\t\tDefault mode is starting the debug server\n");
printf("\tFlash operation modifiers options:\n");
printf("\t-a <num>\t: Start flash operation at flash address <num>\n"
"\t\t\tDefault start is 0x08000000\n");
"\t\t\t Default start is 0x08000000\n");
printf("\t-S <num>\t: Read <num> bytes. Default is until read fails.\n");
printf("\t-j\t\t: Use JTAG. SWD is default.\n");
printf("\t <file>\t\t: Use (binary) file <file> for flash operation\n"
"\t\t\tGiven <file> writes to flash if neither -r or -V is given\n");
"\t\t\t Given <file> writes to flash if neither -r or -V is "
"given\n");
exit(0);
}
@ -150,7 +152,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
opt->opt_target_dev = 1;
opt->opt_flash_start = 0x08000000;
opt->opt_flash_size = 16 * 1024 *1024;
while((c = getopt(argc, argv, "Ehv::d:s:I:c:CnN:tVta:S:jpP:rR")) != -1) {
while((c = getopt(argc, argv, "Ehv::d:s:I:c:Cn:tVta:S:jpP:rR")) != -1) {
switch(c) {
case 'c':
if (optarg)
@ -171,9 +173,6 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
case 'C':
opt->opt_connect_under_reset = true;
break;
case 'n':
opt->opt_no_wait = true;
break;
case 'd':
if (optarg)
opt->opt_device = optarg;
@ -208,7 +207,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
if (optarg)
opt->opt_flash_start = strtol(optarg, NULL, 0);
break;
case 'N':
case 'n':
if (optarg)
opt->opt_target_dev = strtol(optarg, NULL, 0);
break;

View File

@ -24,6 +24,8 @@
#if !defined(__CL_UTILS_H)
#define __CL_UTILS_H
#define RESP_TIMEOUT (100)
enum bmp_cl_mode {
BMP_MODE_DEBUG,
BMP_MODE_TEST,
@ -37,7 +39,6 @@ enum bmp_cl_mode {
typedef struct BMP_CL_OPTIONS_s {
enum bmp_cl_mode opt_mode;
bool opt_usejtag;
bool opt_no_wait;
bool opt_tpwr;
bool opt_connect_under_reset;
char *opt_flash_file;
@ -53,8 +54,9 @@ typedef struct BMP_CL_OPTIONS_s {
char *opt_idstring;
}BMP_CL_OPTIONS_t;
extern int cl_debuglevel;
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
int cl_execute(BMP_CL_OPTIONS_t *opt);
int serial_open(BMP_CL_OPTIONS_t *opt);
int serial_open(BMP_CL_OPTIONS_t *opt, char *serial);
void serial_close(void);
#endif

View File

@ -0,0 +1,143 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "general.h"
#include "cl_utils.h"
static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans)
{
struct trans_ctx * const ctx = trans->user_data;
if (trans->status != LIBUSB_TRANSFER_COMPLETED)
{
fprintf(stderr, "on_trans_done: ");
if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) {
fprintf(stderr, " Timeout\n");
} else if (trans->status == LIBUSB_TRANSFER_CANCELLED) {
fprintf(stderr, " cancelled\n");
} else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) {
fprintf(stderr, " no device\n");
} else {
fprintf(stderr, " unknown\n");
}
ctx->flags |= TRANS_FLAGS_HAS_ERROR;
}
ctx->flags |= TRANS_FLAGS_IS_DONE;
}
static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) {
struct trans_ctx trans_ctx;
enum libusb_error error;
trans_ctx.flags = 0;
/* brief intrusion inside the libusb interface */
trans->callback = on_trans_done;
trans->user_data = &trans_ctx;
if ((error = libusb_submit_transfer(trans))) {
fprintf(stderr, "libusb_submit_transfer(%d): %s\n", error,
libusb_strerror(error));
exit(-1);
}
uint32_t start_time = platform_time_ms();
while (trans_ctx.flags == 0) {
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) {
fprintf(stderr, "libusb_handle_events()\n");
return -1;
}
uint32_t now = platform_time_ms();
if (now - start_time > 1000) {
libusb_cancel_transfer(trans);
fprintf(stderr, "libusb_handle_events() timeout\n");
return -1;
}
}
if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) {
fprintf(stderr, "libusb_handle_events() | has_error\n");
return -1;
}
return 0;
}
/* One USB transaction */
int send_recv(usb_link_t *link,
uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize)
{
int res = 0;
if( txsize) {
int txlen = txsize;
libusb_fill_bulk_transfer(link->req_trans,
link->ul_libusb_device_handle,
link->ep_tx | LIBUSB_ENDPOINT_OUT,
txbuf, txlen,
NULL, NULL, 0);
if (cl_debuglevel > 0) {
int i = 0;
printf(" Send (%3d): ", txlen);
for (; i < txlen; i++) {
printf("%02x", txbuf[i]);
if ((i & 7) == 7)
printf(".");
if ((i & 31) == 31)
printf("\n ");
}
if (!(i & 31))
printf("\n");
}
if (submit_wait(link, link->req_trans)) {
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx);
return -1;
}
}
/* send_only */
if (rxsize != 0) {
/* read the response */
libusb_fill_bulk_transfer(link->rep_trans, link->ul_libusb_device_handle,
link->ep_rx | LIBUSB_ENDPOINT_IN,
rxbuf, rxsize, NULL, NULL, 0);
if (submit_wait(link, link->rep_trans)) {
DEBUG("clear 1\n");
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx);
return -1;
}
res = link->rep_trans->actual_length;
if (res >0) {
int i;
uint8_t *p = rxbuf;
if (cl_debuglevel > 0) {
printf(" Rec (%zu/%d)", rxsize, res);
for (i = 0; i < res && i < 32 ; i++) {
if ( i && ((i & 7) == 0))
printf(".");
printf("%02x", p[i]);
}
}
}
}
if (cl_debuglevel > 0)
printf("\n");
return res;
}

View File

@ -0,0 +1,41 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2020 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined(__LIBUSB_UTILS_H)
#define __LIBUSB_UTILS_H
#include <libusb-1.0/libusb.h>
struct trans_ctx {
#define TRANS_FLAGS_IS_DONE (1 << 0)
#define TRANS_FLAGS_HAS_ERROR (1 << 1)
volatile unsigned long flags;
};
typedef struct {
libusb_context *ul_libusb_ctx;
libusb_device_handle *ul_libusb_device_handle;
unsigned char ep_tx;
unsigned char ep_rx;
struct libusb_transfer* req_trans;
struct libusb_transfer* rep_trans;
void *priv;
} usb_link_t;
int send_recv(usb_link_t *link, uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize);
#endif

View File

@ -31,7 +31,7 @@
#include "cl_utils.h"
static int fd; /* File descriptor for connection to GDB remote */
extern int cl_debuglevel;
/* A nice routine grabbed from
* https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
*/
@ -69,10 +69,10 @@ static int set_interface_attribs(void)
}
#define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe"
#define DEVICE_BY_ID "/dev/serial/by-id/"
int serial_open(BMP_CL_OPTIONS_t *opt)
int serial_open(BMP_CL_OPTIONS_t *cl_opts, char *serial)
{
char name[4096];
if (!opt->opt_device) {
if (!cl_opts->opt_device) {
/* Try to find some BMP if0*/
struct dirent *dp;
DIR *dir = opendir(DEVICE_BY_ID);
@ -86,8 +86,7 @@ int serial_open(BMP_CL_OPTIONS_t *opt)
if ((strstr(dp->d_name, BMP_IDSTRING)) &&
(strstr(dp->d_name, "-if00"))) {
num_total++;
if (((opt->opt_serial) &&
(!strstr(dp->d_name, opt->opt_serial))))
if ((serial) && (!strstr(dp->d_name, serial)))
continue;
num_devices++;
strcpy(name, DEVICE_BY_ID);
@ -108,8 +107,8 @@ int serial_open(BMP_CL_OPTIONS_t *opt)
fprintf(stderr, "%s\n", dp->d_name);
}
closedir(dir);
if (opt->opt_serial)
fprintf(stderr, "Do no match given serial \"%s\"\n", opt->opt_serial);
if (serial)
fprintf(stderr, "Do no match given serial \"%s\"\n", serial);
else
fprintf(stderr, "Select Probe with -s <(Partial) Serial Number\n");
} else {
@ -118,7 +117,7 @@ int serial_open(BMP_CL_OPTIONS_t *opt)
return -1;
}
} else {
strncpy(name, opt->opt_device, sizeof(name) - 1);
strncpy(name, cl_opts->opt_device, sizeof(name) - 1);
}
fd = open(name, O_RDWR | O_SYNC | O_NOCTTY);
if (fd < 0) {
@ -156,15 +155,13 @@ int platform_buffer_read(uint8_t *data, int maxsize)
uint8_t *c;
int s;
int ret;
uint32_t endTime;
fd_set rset;
struct timeval tv;
c = data;
tv.tv_sec = 0;
endTime = platform_time_ms() + RESP_TIMEOUT;
tv.tv_usec = 1000 * (endTime - platform_time_ms());
tv.tv_usec = 1000 * RESP_TIMEOUT;
/* Look for start of response */
do {

View File

@ -24,20 +24,21 @@
#include "cl_utils.h"
HANDLE hComm;
extern int cl_debuglevel;
int serial_open(BMP_CL_OPTIONS_t *opt)
int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial)
{
if (!opt->opt_device) {
(void) serial; /* FIXME: Does Windows allow open with USB serial no? */
if (!cl_opts->opt_device) {
fprintf(stderr,"Specify the serial device to use!\n");
return -1;
}
char device[256];
if (strstr(opt->opt_device, "\\\\.\\")) {
strncpy(device, opt->opt_device, sizeof(device) - 1);
if (strstr(device, "\\\\.\\")) {
strncpy(device, cl_opts->opt_device, sizeof(cl_opts->opt_device) - 1);
} else {
strcpy(device, "\\\\.\\");
strncat(device, opt->opt_device, sizeof(device) - strlen(device) - 1);
strncat(device, cl_opts->opt_device,
sizeof(cl_opts->opt_device) - strlen(cl_opts->opt_device) - 1);
}
hComm = CreateFile(device, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write

View File

@ -37,18 +37,18 @@ SRC += cdcacm.c \
stlink_common.c \
ifeq ($(ST_BOOTLOADER), 1)
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex
all: blackmagic.bin
else
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex
endif
blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o stlink_common.o
blackmagic_dfu.elf: usbdfu.o dfucore.o dfu_f1.o stlink_common.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT)
dfu_upgrade: dfu_upgrade.o dfucore.o dfu_f1.o stlink_common.o
dfu_upgrade.elf: dfu_upgrade.o dfucore.o dfu_f1.o stlink_common.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS)
host_clean:
-$(Q)$(RM) blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade dfu_upgrade.bin dfu_upgrade.hex
-$(Q)$(RM) *.bin *elf *hex

View File

@ -31,11 +31,11 @@ SRC += cdcacm.c \
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex
blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o platform_common.o
blackmagic_dfu.elf: usbdfu.o dfucore.o dfu_f1.o platform_common.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT)
dfu_upgrade: dfu_upgrade.o dfucore.o dfu_f1.o platform_common.o
dfu_upgrade.elf: dfu_upgrade.o dfucore.o dfu_f1.o platform_common.o
@echo " LD $@"
$(Q)$(CC) $^ -o $@ $(LDFLAGS)

View File

@ -243,7 +243,7 @@ void remotePacketProcessGEN(uint8_t i, char *packet)
break;
#if !defined(BOARD_IDENT) && defined(PLATFORM_IDENT)
# define BOARD_IDENT PLATFORM_IDENT
# define BOARD_IDENT() PLATFORM_IDENT
#endif
case REMOTE_START:
_respondS(REMOTE_RESP_OK, BOARD_IDENT " " FIRMWARE_VERSION);

View File

@ -74,7 +74,7 @@ enum cid_class {
cidc_unknown = 0x10
};
#ifdef PLATFORM_HAS_DEBUG
#ifdef ENABLE_DEBUG
/* The reserved ones only have an R in them, to save a bit of space. */
static const char * const cidc_debug_strings[] =
{
@ -111,7 +111,7 @@ enum arm_arch {
aa_end
};
#ifdef PLATFORM_HAS_DEBUG
#ifdef ENABLE_DEBUG
#define PIDR_PN_BIT_STRINGS(...) __VA_ARGS__
#else
#define PIDR_PN_BIT_STRINGS(...)
@ -155,7 +155,7 @@ static const struct {
uint16_t part_number;
enum arm_arch arch;
enum cid_class cidc;
#ifdef PLATFORM_HAS_DEBUG
#ifdef ENABLE_DEBUG
const char *type;
const char *full;
#endif
@ -277,7 +277,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
uint64_t pidr = adiv5_ap_read_pidr(ap, addr);
uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
bool res = false;
#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG)
#if defined(ENABLE_DEBUG)
char indent[recursion + 1];
for(int i = 0; i < recursion; i++) indent[i] = ' ';
@ -303,7 +303,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
/* ROM table */
if (cid_class == cidc_romtab) {
/* Check SYSMEM bit */
#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG)
#if defined(ENABLE_DEBUG)
uint32_t memtype = adiv5_mem_read32(ap, addr | ADIV5_ROM_MEMTYPE) &
ADIV5_ROM_MEMTYPE_SYSMEM;
@ -399,8 +399,6 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
}
return res;
}
bool adiv5_ap_setup(int i);
void adiv5_ap_cleanup(int i);
ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
{
@ -441,12 +439,32 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
return ap;
}
static void ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
static uint32_t ap_read(ADIv5_AP_t *ap, uint16_t addr);
static void mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
static void mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align);
void adiv5_dp_init(ADIv5_DP_t *dp)
{
volatile bool probed = false;
volatile uint32_t ctrlstat = 0;
adiv5_dp_ref(dp);
#if PC_HOSTED == 1
platform_adiv5_dp_defaults(dp);
if (!dp->ap_write)
dp->ap_write = ap_write;
if (!dp->ap_read)
dp->ap_read = ap_read;
if (!dp->mem_read)
dp->mem_read = mem_read;
if (!dp->mem_write_sized)
dp->mem_write_sized = mem_write_sized;
#else
dp->ap_write = ap_write;
dp->ap_read = ap_read;
dp->mem_read = mem_read;
dp->mem_write_sized = mem_write_sized;
#endif
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_TIMEOUT) {
ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
@ -507,11 +525,18 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
int void_aps = 0;
for(int i = 0; (i < 256) && (void_aps < 8); i++) {
ADIv5_AP_t *ap = NULL;
if (adiv5_ap_setup(i))
#if PC_HOSTED == 1
if ((!dp->ap_setup) || dp->ap_setup(i))
ap = adiv5_new_ap(dp, i);
#else
ap = adiv5_new_ap(dp, i);
#endif
if (ap == NULL) {
void_aps++;
adiv5_ap_cleanup(i);
#if PC_HOSTED == 1
if (dp->ap_cleanup)
dp->ap_cleanup(i);
#endif
if (i == 0)
return;
else
@ -519,7 +544,10 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
}
if (ap->base == last_base) {
DEBUG("AP %d: Duplicate base\n", i);
adiv5_ap_cleanup(i);
#if PC_HOSTED == 1
if (dp->ap_cleanup)
dp->ap_cleanup(i);
#endif
free(ap);
/* FIXME: Should we expect valid APs behind duplicate ones? */
return;
@ -562,11 +590,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
#define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \
(((x) & 1) == 0 ? ALIGN_HALFWORD : ALIGN_BYTE))
#if !defined(JTAG_HL)
bool adiv5_ap_setup(int i) {(void)i; return true;}
void adiv5_ap_cleanup(int i) {(void)i;}
/* Program the CSW and TAR for sequencial access at a given width */
static void ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align)
{
@ -606,7 +629,7 @@ void * extract(void *dest, uint32_t src, uint32_t val, enum align align)
return (uint8_t *)dest + (1 << align);
}
void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
static void mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
uint32_t tmp;
uint32_t osrc = src;
@ -636,8 +659,8 @@ void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
extract(dest, src, tmp, align);
}
void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
static void mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{
uint32_t odest = dest;
@ -671,14 +694,14 @@ void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
}
}
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
static void ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
((uint32_t)ap->apsel << 24)|(addr & 0xF0));
adiv5_dp_write(ap->dp, addr, value);
}
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
static uint32_t ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
uint32_t ret;
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
@ -686,7 +709,6 @@ uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
ret = adiv5_dp_read(ap->dp, addr);
return ret;
}
#endif
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len)
{

View File

@ -129,6 +129,8 @@ enum align {
ALIGN_DWORD = 3
};
typedef struct ADIv5_AP_s ADIv5_AP_t;
/* Try to keep this somewhat absract for later adding SW-DP */
typedef struct ADIv5_DP_s {
int refcnt;
@ -142,6 +144,23 @@ typedef struct ADIv5_DP_s {
uint16_t addr, uint32_t value);
void (*abort)(struct ADIv5_DP_s *dp, uint32_t abort);
#if PC_HOSTED == 1
bool (*ap_setup)(int i);
void (*ap_cleanup)(int i);
void (*ap_regs_read)(ADIv5_AP_t *ap, void *data);
uint32_t(*ap_reg_read)(ADIv5_AP_t *ap, int num);
void (*ap_reg_write)(ADIv5_AP_t *ap, int num, uint32_t value);
void (*read_block)(uint32_t addr, uint8_t *data, int size);
void (*dap_write_block_sized)(uint32_t addr, uint8_t *data,
int size, enum align align);
#endif
uint32_t (*ap_read)(ADIv5_AP_t *ap, uint16_t addr);
void (*ap_write)(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
void (*mem_read)(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
void (*mem_write_sized)(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align);
#if PC_HOSTED == 1
jtag_dev_t *dev;
uint8_t fault;
@ -174,7 +193,7 @@ static inline void adiv5_dp_abort(struct ADIv5_DP_s *dp, uint32_t abort)
return dp->abort(dp, abort);
}
typedef struct ADIv5_AP_s {
struct ADIv5_AP_s {
int refcnt;
ADIv5_DP_t *dp;
@ -183,25 +202,42 @@ typedef struct ADIv5_AP_s {
uint32_t idr;
uint32_t base;
uint32_t csw;
} ADIv5_AP_t;
};
static inline uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
return ap->dp->ap_read(ap, addr);
}
static inline void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{
return ap->dp->ap_write(ap, addr, value);
}
static inline void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src,
size_t len)
{
return ap->dp->mem_read(ap, dest, src, len);
}
static inline void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest,
const void *src, size_t len, enum align align)
{
return ap->dp->mem_write_sized(ap, dest, src, len, align);
}
void adiv5_dp_init(ADIv5_DP_t *dp);
void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value);
void adiv5_dp_init(ADIv5_DP_t *dp);
void platform_adiv5_dp_defaults(ADIv5_DP_t *dp);
ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel);
void adiv5_ap_ref(ADIv5_AP_t *ap);
void adiv5_ap_unref(ADIv5_AP_t *ap);
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr);
void adiv5_jtag_dp_handler(jtag_dev_t *dev);
int platform_jtag_dp_init(ADIv5_DP_t *dp);
void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len);
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len);
void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align);
uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr);
void * extract(void *dest, uint32_t src, uint32_t val, enum align align);
#endif

View File

@ -478,88 +478,98 @@ static void cortexm_regs_read(target *t, void *data)
uint32_t *regs = data;
ADIv5_AP_t *ap = cortexm_ap(t);
unsigned i;
#if defined(STLINKV2)
uint32_t base_regs[21];
extern void stlink_regs_read(ADIv5_AP_t *ap, void *data);
extern uint32_t stlink_reg_read(ADIv5_AP_t *ap, int idx);
stlink_regs_read(ap, base_regs);
for(i = 0; i < sizeof(regnum_cortex_m) / 4; i++)
*regs++ = base_regs[regnum_cortex_m[i]];
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(size_t t = 0; t < sizeof(regnum_cortex_mf) / 4; t++)
*regs++ = stlink_reg_read(ap, regnum_cortex_mf[t]);
#else
/* FIXME: Describe what's really going on here */
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD);
/* Map the banked data registers (0x10-0x1c) to the
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR);
/* Walk the regnum_cortex_m array, reading the registers it
* calls out. */
adiv5_ap_write(ap, ADIV5_AP_DB(DB_DCRSR), regnum_cortex_m[0]); /* Required to switch banks */
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR));
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR),
regnum_cortex_m[i]);
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR));
#if PC_HOSTED == 1
if ((ap->dp->ap_reg_read) && (ap->dp->ap_regs_read)) {
uint32_t base_regs[21];
ap->dp->ap_regs_read(ap, base_regs);
for(i = 0; i < sizeof(regnum_cortex_m) / 4; i++)
*regs++ = base_regs[regnum_cortex_m[i]];
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(size_t t = 0; t < sizeof(regnum_cortex_mf) / 4; t++)
*regs++ = ap->dp->ap_reg_read(ap, regnum_cortex_mf[t]);
}
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRSR),
regnum_cortex_mf[i]);
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR));
}
#else
if (0) {}
#endif
else {
/* FIXME: Describe what's really going on here */
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD);
/* Map the banked data registers (0x10-0x1c) to the
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR,
CORTEXM_DHCSR);
/* Walk the regnum_cortex_m array, reading the registers it
* calls out. */
adiv5_ap_write(ap, ADIV5_AP_DB(DB_DCRSR), regnum_cortex_m[0]);
/* Required to switch banks */
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR));
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR),
regnum_cortex_m[i]);
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR));
}
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRSR),
regnum_cortex_mf[i]);
*regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR));
}
}
}
static void cortexm_regs_write(target *t, const void *data)
{
const uint32_t *regs = data;
ADIv5_AP_t *ap = cortexm_ap(t);
#if defined(STLINKV2)
extern void stlink_reg_write(ADIv5_AP_t *ap, int num, uint32_t val);
for(size_t z = 0; z < sizeof(regnum_cortex_m) / 4; z++) {
stlink_reg_write(ap, regnum_cortex_m[z], *regs);
regs++;
}
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(size_t z = 0; z < sizeof(regnum_cortex_mf) / 4; z++) {
stlink_reg_write(ap, regnum_cortex_mf[z], *regs);
#if PC_HOSTED == 1
if (ap->dp->ap_reg_write) {
for (size_t z = 0; z < sizeof(regnum_cortex_m) / 4; z++) {
ap->dp->ap_reg_write(ap, regnum_cortex_m[z], *regs);
regs++;
}
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(size_t z = 0; z < sizeof(regnum_cortex_mf) / 4; z++) {
ap->dp->ap_reg_write(ap, regnum_cortex_mf[z], *regs);
regs++;
}
}
#else
unsigned i;
/* FIXME: Describe what's really going on here */
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD);
/* Map the banked data registers (0x10-0x1c) to the
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR);
/* Walk the regnum_cortex_m array, writing the registers it
* calls out. */
adiv5_ap_write(ap, ADIV5_AP_DB(DB_DCRDR), *regs++); /* Required to switch banks */
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR),
0x10000 | regnum_cortex_m[0]);
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRDR), *regs++);
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR),
0x10000 | regnum_cortex_m[i]);
}
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRDR), *regs++);
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRSR),
0x10000 | regnum_cortex_mf[i]);
}
if (0) {}
#endif
else {
unsigned i;
/* FIXME: Describe what's really going on here */
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD);
/* Map the banked data registers (0x10-0x1c) to the
* debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR,
CORTEXM_DHCSR);
/* Walk the regnum_cortex_m array, writing the registers it
* calls out. */
adiv5_ap_write(ap, ADIV5_AP_DB(DB_DCRDR), *regs++);
/* Required to switch banks */
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR),
0x10000 | regnum_cortex_m[0]);
for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRDR), *regs++);
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR),
0x10000 | regnum_cortex_m[i]);
}
if (t->target_options & TOPT_FLAVOUR_V7MF)
for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) {
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRDR), *regs++);
adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE,
ADIV5_AP_DB(DB_DCRSR),
0x10000 | regnum_cortex_mf[i]);
}
}
}
int cortexm_mem_write_sized(

View File

@ -720,7 +720,7 @@ static int efm32_flash_write(struct target_flash *f,
int ret = cortexm_run_stub(t, SRAM_BASE, dest, STUB_BUFFER_BASE, len,
device->msc_addr);
#ifdef PLATFORM_HAS_DEBUG
#ifdef ENABLE_DEBUG
/* Check the MSC_IF */
uint32_t msc = device->msc_addr;
uint32_t msc_if = target_mem_read32(t, EFM32_MSC_IF(msc));