Merge commit 'ef816e318391c64014554140be65a5cafc6c8be2' into sam-update
# Conflicts: # .gitignore
This commit is contained in:
commit
eda19bc28d
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,5 +17,6 @@ tags
|
||||
blackmagic_upgrade
|
||||
*.exe
|
||||
.DS_Store
|
||||
*.elf
|
||||
.vscode
|
||||
cscope.out
|
||||
|
16
src/Makefile
16
src/Makefile
@ -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:
|
||||
|
@ -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());
|
||||
|
21
src/platforms/hosted/Makefile.inc
Normal file
21
src/platforms/hosted/Makefile.inc
Normal 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
|
147
src/platforms/hosted/bmp_remote.c
Normal file
147
src/platforms/hosted/bmp_remote.c
Normal 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];
|
||||
}
|
39
src/platforms/hosted/bmp_remote.h
Normal file
39
src/platforms/hosted/bmp_remote.h
Normal 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
|
@ -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";
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
418
src/platforms/hosted/platform.c
Normal file
418
src/platforms/hosted/platform.c
Normal 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;
|
||||
}
|
||||
}
|
41
src/platforms/hosted/platform.h
Normal file
41
src/platforms/hosted/platform.h
Normal 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
|
165
src/platforms/hosted/remote_jtagtap.c
Normal file
165
src/platforms/hosted/remote_jtagtap.c
Normal 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]);
|
||||
}
|
128
src/platforms/hosted/remote_swdptap.c
Normal file
128
src/platforms/hosted/remote_swdptap.c
Normal 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);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
@ -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)".
|
@ -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)
|
||||
|
||||
|
@ -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
|
@ -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.
|
@ -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]);
|
||||
}
|
@ -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];
|
||||
}
|
@ -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
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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;
|
||||
|
@ -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
|
||||
|
143
src/platforms/pc/libusb_utils.c
Normal file
143
src/platforms/pc/libusb_utils.c
Normal 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;
|
||||
}
|
41
src/platforms/pc/libusb_utils.h
Normal file
41
src/platforms/pc/libusb_utils.h
Normal 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
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user