Merge commit 'f5e305e237aba0ab8bf2f42e75505ef468f47d82' into sam-update

# Conflicts:
#	README.md
This commit is contained in:
Jason Kotzin 2022-08-10 17:36:47 -07:00
commit 65c95fb413
69 changed files with 3513 additions and 705 deletions

View File

@ -10,7 +10,7 @@ before_install:
- wget http://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.2.tar.bz2.sig - wget http://www.intra2net.com/en/developer/libftdi/download/libftdi1-1.2.tar.bz2.sig
- gpg --trust-model always --verify libftdi1-1.2.tar.bz2.sig - gpg --trust-model always --verify libftdi1-1.2.tar.bz2.sig
- tar -xjf libftdi1-1.2.tar.bz2 - tar -xjf libftdi1-1.2.tar.bz2
- sudo apt-get install -y build-essential libboost-all-dev gcc-arm-embedded libusb-1.0-0-dev - sudo apt-get install -y build-essential libboost-all-dev gcc-arm-embedded libusb-1.0-0-dev libhidapi-dev
install: install:
- cd libftdi1-1.2 - cd libftdi1-1.2

View File

@ -33,7 +33,6 @@ SRC = \
hex_utils.c \ hex_utils.c \
jtag_devs.c \ jtag_devs.c \
jtag_scan.c \ jtag_scan.c \
jtagtap.c \
lmi.c \ lmi.c \
lpc_common.c \ lpc_common.c \
lpc11xx.c \ lpc11xx.c \
@ -57,7 +56,6 @@ SRC = \
stm32h7.c \ stm32h7.c \
stm32l0.c \ stm32l0.c \
stm32l4.c \ stm32l4.c \
swdptap.c \
target.c \ target.c \
include $(PLATFORM_DIR)/Makefile.inc include $(PLATFORM_DIR)/Makefile.inc
@ -81,6 +79,7 @@ endif
ifdef PC_HOSTED ifdef PC_HOSTED
CFLAGS += -DPC_HOSTED=1 CFLAGS += -DPC_HOSTED=1
else else
SRC += swdptap.c jtagtap.c
CFLAGS += -DPC_HOSTED=0 CFLAGS += -DPC_HOSTED=0
VPATH += platforms/common VPATH += platforms/common
CFLAGS += -Iplatforms/common CFLAGS += -Iplatforms/common

View File

@ -26,7 +26,7 @@ struct exception *innermost_exception;
void raise_exception(uint32_t type, const char *msg) void raise_exception(uint32_t type, const char *msg)
{ {
struct exception *e; struct exception *e;
DEBUG("Exception: %s\n", msg); DEBUG_WARN("Exception: %s\n", msg);
for (e = innermost_exception; e; e = e->outer) { for (e = innermost_exception; e; e = e->outer) {
if (e->mask & type) { if (e->mask & type) {
e->type = type; e->type = type;

View File

@ -120,7 +120,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
gdb_putpacketz("E02"); gdb_putpacketz("E02");
break; break;
} }
DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); DEBUG_GDB("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
addr, len);
uint8_t mem[len]; uint8_t mem[len];
if (target_mem_read(cur_target, mem, addr, len)) if (target_mem_read(cur_target, mem, addr, len))
gdb_putpacketz("E01"); gdb_putpacketz("E01");
@ -145,7 +146,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
gdb_putpacketz("E02"); gdb_putpacketz("E02");
break; break;
} }
DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); DEBUG_GDB("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
addr, len);
uint8_t mem[len]; uint8_t mem[len];
unhexify(mem, pbuf + hex, len); unhexify(mem, pbuf + hex, len);
if (target_mem_write(cur_target, addr, mem, len)) if (target_mem_write(cur_target, addr, mem, len))
@ -242,7 +244,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
if (in_syscall) { if (in_syscall) {
return hostio_reply(tc, pbuf, size); return hostio_reply(tc, pbuf, size);
} else { } else {
DEBUG("*** F packet when not in syscall! '%s'\n", pbuf); DEBUG_GDB("*** F packet when not in syscall! '%s'\n", pbuf);
gdb_putpacketz(""); gdb_putpacketz("");
} }
break; break;
@ -295,7 +297,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
gdb_putpacketz("E02"); gdb_putpacketz("E02");
break; break;
} }
DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); DEBUG_GDB("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n",
addr, len);
if (target_mem_write(cur_target, addr, pbuf+bin, len)) if (target_mem_write(cur_target, addr, pbuf+bin, len))
gdb_putpacketz("E01"); gdb_putpacketz("E01");
else else
@ -319,7 +322,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall)
break; break;
default: /* Packet not implemented */ default: /* Packet not implemented */
DEBUG("*** Unsupported packet: %s\n", pbuf); DEBUG_GDB("*** Unsupported packet: %s\n", pbuf);
gdb_putpacketz(""); gdb_putpacketz("");
} }
} }
@ -410,7 +413,7 @@ handle_q_packet(char *packet, int len)
gdb_putpacket_f("C%lx", generic_crc32(cur_target, addr, alen)); gdb_putpacket_f("C%lx", generic_crc32(cur_target, addr, alen));
} else { } else {
DEBUG("*** Unsupported packet: %s\n", packet); DEBUG_GDB("*** Unsupported packet: %s\n", packet);
gdb_putpacket("", 0); gdb_putpacket("", 0);
} }
} }
@ -478,7 +481,7 @@ handle_v_packet(char *packet, int plen)
} else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) { } else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) {
/* Erase Flash Memory */ /* Erase Flash Memory */
DEBUG("Flash Erase %08lX %08lX\n", addr, len); DEBUG_GDB("Flash Erase %08lX %08lX\n", addr, len);
if(!cur_target) { gdb_putpacketz("EFF"); return; } if(!cur_target) { gdb_putpacketz("EFF"); return; }
if(!flash_mode) { if(!flash_mode) {
@ -495,7 +498,7 @@ handle_v_packet(char *packet, int plen)
} else if (sscanf(packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) { } else if (sscanf(packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) {
/* Write Flash Memory */ /* Write Flash Memory */
len = plen - bin; len = plen - bin;
DEBUG("Flash Write %08lX %08lX\n", addr, len); DEBUG_GDB("Flash Write %08lX %08lX\n", addr, len);
if(cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0) if(cur_target && target_flash_write(cur_target, addr, (void*)packet + bin, len) == 0)
gdb_putpacketz("OK"); gdb_putpacketz("OK");
else else
@ -507,7 +510,7 @@ handle_v_packet(char *packet, int plen)
flash_mode = 0; flash_mode = 0;
} else { } else {
DEBUG("*** Unsupported packet: %s\n", packet); DEBUG_GDB("*** Unsupported packet: %s\n", packet);
gdb_putpacket("", 0); gdb_putpacket("", 0);
} }
} }

View File

@ -118,16 +118,16 @@ int gdb_getpacket(char *packet, int size)
gdb_if_putchar('+', 1); /* send ack */ gdb_if_putchar('+', 1); /* send ack */
packet[i] = 0; packet[i] = 0;
#ifdef DEBUG_GDBPACKET #if PC_HOSTED == 1
DEBUG("%s : ", __func__); DEBUG_GDB_WIRE("%s : ", __func__);
for(int j = 0; j < i; j++) { for(int j = 0; j < i; j++) {
c = packet[j]; c = packet[j];
if ((c >= 32) && (c < 127)) if ((c >= 32) && (c < 127))
DEBUG("%c", c); DEBUG_GDB_WIRE("%c", c);
else else
DEBUG("\\x%02X", c); DEBUG_GDB_WIRE("\\x%02X", c);
} }
DEBUG("\n"); DEBUG_GDB_WIRE("\n");
#endif #endif
return i; return i;
} }
@ -141,18 +141,16 @@ void gdb_putpacket(const char *packet, int size)
int tries = 0; int tries = 0;
do { do {
#ifdef DEBUG_GDBPACKET DEBUG_GDB_WIRE("%s : ", __func__);
DEBUG("%s : ", __func__);
#endif
csum = 0; csum = 0;
gdb_if_putchar('$', 0); gdb_if_putchar('$', 0);
for(i = 0; i < size; i++) { for(i = 0; i < size; i++) {
c = packet[i]; c = packet[i];
#ifdef DEBUG_GDBPACKET #if PC_HOSTED == 1
if ((c >= 32) && (c < 127)) if ((c >= 32) && (c < 127))
DEBUG("%c", c); DEBUG_GDB_WIRE("%c", c);
else else
DEBUG("\\x%02X", c); DEBUG_GDB_WIRE("\\x%02X", c);
#endif #endif
if((c == '$') || (c == '#') || (c == '}')) { if((c == '$') || (c == '#') || (c == '}')) {
gdb_if_putchar('}', 0); gdb_if_putchar('}', 0);
@ -167,9 +165,7 @@ void gdb_putpacket(const char *packet, int size)
snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum); snprintf(xmit_csum, sizeof(xmit_csum), "%02X", csum);
gdb_if_putchar(xmit_csum[0], 0); gdb_if_putchar(xmit_csum[0], 0);
gdb_if_putchar(xmit_csum[1], 1); gdb_if_putchar(xmit_csum[1], 1);
#ifdef DEBUG_GDBPACKET DEBUG_GDB_WIRE("\n");
DEBUG("\n");
#endif
} while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); } while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3));
} }

View File

@ -37,8 +37,116 @@
#include "platform.h" #include "platform.h"
#include "platform_support.h" #include "platform_support.h"
#ifndef DEBUG enum BMP_DEBUG {
#define DEBUG printf BMP_DEBUG_NONE = 0,
BMP_DEBUG_INFO = 1,
BMP_DEBUG_GDB = 2,
BMP_DEBUG_TARGET = 4,
BMP_DEBUG_PROBE = 8,
BMP_DEBUG_WIRE = 0x10,
BMP_DEBUG_MAX = 0x20,
BMP_DEBUG_STDOUT = 0x8000,
};
#if PC_HOSTED == 0
/* For BMP debug output on a firmware BMP platform, using
* BMP PC-Hosted is the preferred way. Printing DEBUG_WARN
* and DEBUG_INFO is kept for comptibiluty.
*/
# if defined(ENABLE_DEBUG)
# define DEBUG_WARN printf
# define DEBUG_INFO printf
# else
# define DEBUG_WARN(...)
# define DEBUG_INFO(...)
# endif
# define DEBUG_GDB(...)
# define DEBUG_TARGET(...)
# define DEBUG_PROBE(...)
# define DEBUG_WIRE(...)
# define DEBUG_GDB_WIRE(...)
#else
# include <stdarg.h>
extern int cl_debuglevel;
static inline void DEBUG_WARN(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_INFO(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_INFO)
return;
va_list ap;
va_start(ap, format);
if (cl_debuglevel & BMP_DEBUG_STDOUT)
vfprintf(stdout, format, ap);
else
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_GDB(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_GDB)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_GDB_WIRE(const char *format, ...)
{
if ((cl_debuglevel & (BMP_DEBUG_GDB | BMP_DEBUG_WIRE)) !=
(BMP_DEBUG_GDB | BMP_DEBUG_WIRE))
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_TARGET(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_TARGET)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_PROBE(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_PROBE)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
static inline void DEBUG_WIRE(const char *format, ...)
{
if (~cl_debuglevel & BMP_DEBUG_WIRE)
return;
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
va_end(ap);
return;
}
#endif #endif
#define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1)) #define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1))

View File

@ -24,6 +24,8 @@
# error "Include 'general.h' instead" # error "Include 'general.h' instead"
#endif #endif
#include "target.h"
#if PC_HOSTED == 1 #if PC_HOSTED == 1
void platform_init(int argc, char **argv); void platform_init(int argc, char **argv);
#else #else

View File

@ -61,7 +61,7 @@ void morse(const char *msg, char repeat)
{ {
#if PC_HOSTED == 1 #if PC_HOSTED == 1
if (msg) if (msg)
DEBUG("%s\n", msg); DEBUG_WARN("%s\n", msg);
(void) repeat; (void) repeat;
#else #else
morse_msg = morse_ptr = msg; morse_msg = morse_ptr = msg;

View File

@ -27,6 +27,14 @@ enum {
SWDIO_STATUS_FLOAT = 0, SWDIO_STATUS_FLOAT = 0,
SWDIO_STATUS_DRIVE SWDIO_STATUS_DRIVE
}; };
static void swdptap_turnaround(int dir) __attribute__ ((optimize(3)));
static uint32_t swdptap_seq_in(int ticks) __attribute__ ((optimize(3)));
static bool swdptap_seq_in_parity(uint32_t *ret, int ticks)
__attribute__ ((optimize(3)));
static void swdptap_seq_out(uint32_t MS, int ticks)
__attribute__ ((optimize(3)));
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
__attribute__ ((optimize(3)));
static void swdptap_turnaround(int dir) static void swdptap_turnaround(int dir)
{ {
@ -76,33 +84,33 @@ static uint32_t swdptap_seq_in(int ticks)
static bool swdptap_seq_in_parity(uint32_t *ret, int ticks) static bool swdptap_seq_in_parity(uint32_t *ret, int ticks)
{ {
uint32_t index = 1; uint32_t index = 1;
uint8_t parity = 0;
uint32_t res = 0; uint32_t res = 0;
bool bit; bool bit;
int len = ticks; int len = ticks;
swdptap_turnaround(SWDIO_STATUS_FLOAT); swdptap_turnaround(SWDIO_STATUS_FLOAT);
while (len--) { while (len--) {
gpio_clear(SWCLK_PORT, SWCLK_PIN);
bit = gpio_get(SWDIO_PORT, SWDIO_PIN); bit = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_set(SWCLK_PORT, SWCLK_PIN);
if (bit) { if (bit) {
res |= index; res |= index;
parity ^= 1;
} }
index <<= 1; index <<= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN);
} }
gpio_clear(SWCLK_PORT, SWCLK_PIN);
int parity = __builtin_popcount(res);
bit = gpio_get(SWDIO_PORT, SWDIO_PIN); bit = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_set(SWCLK_PORT, SWCLK_PIN);
if (bit) if (bit)
parity ^= 1; parity++;
gpio_clear(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN);
#ifdef DEBUG_SWD_BITS #ifdef DEBUG_SWD_BITS
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
DEBUG("%d", (res & (1 << i)) ? 1 : 0); DEBUG("%d", (res & (1 << i)) ? 1 : 0);
#endif #endif
*ret = res; *ret = res;
return parity; return (parity & 1);
} }
static void swdptap_seq_out(uint32_t MS, int ticks) static void swdptap_seq_out(uint32_t MS, int ticks)
@ -115,30 +123,30 @@ static void swdptap_seq_out(uint32_t MS, int ticks)
swdptap_turnaround(SWDIO_STATUS_DRIVE); swdptap_turnaround(SWDIO_STATUS_DRIVE);
while (ticks--) { while (ticks--) {
gpio_set_val(SWDIO_PORT, SWDIO_PIN, data); gpio_set_val(SWDIO_PORT, SWDIO_PIN, data);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
MS >>= 1; MS >>= 1;
data = MS & 1; data = MS & 1;
gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
} }
gpio_clear(SWCLK_PORT, SWCLK_PIN);
} }
static void swdptap_seq_out_parity(uint32_t MS, int ticks) static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{ {
uint8_t parity = 0; int parity = __builtin_popcount(MS);
int data = MS & 1; int data = MS & 1;
#ifdef DEBUG_SWD_BITS #ifdef DEBUG_SWD_BITS
for (int i = 0; i < ticks; i++) for (int i = 0; i < ticks; i++)
DEBUG("%d", (MS & (1 << i)) ? 1 : 0); DEBUG("%d", (MS & (1 << i)) ? 1 : 0);
#endif #endif
swdptap_turnaround(SWDIO_STATUS_DRIVE); swdptap_turnaround(SWDIO_STATUS_DRIVE);
while (ticks--) {
gpio_set_val(SWDIO_PORT, SWDIO_PIN, data); gpio_set_val(SWDIO_PORT, SWDIO_PIN, data);
parity ^= MS;
MS >>= 1; MS >>= 1;
gpio_set(SWCLK_PORT, SWCLK_PIN); while (ticks--) {
data = MS & 1; data = MS & 1;
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, data);
MS >>= 1;
gpio_clear(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN);
} }
gpio_set_val(SWDIO_PORT, SWDIO_PIN, parity & 1); gpio_set_val(SWDIO_PORT, SWDIO_PIN, parity & 1);

View File

@ -135,8 +135,6 @@
#define TRACE_IRQ NVIC_TIM3_IRQ #define TRACE_IRQ NVIC_TIM3_IRQ
#define TRACE_ISR tim3_isr #define TRACE_ISR tim3_isr
#define DEBUG(...)
#define gpio_set_val(port, pin, val) do { \ #define gpio_set_val(port, pin, val) do { \
if(val) \ if(val) \
gpio_set((port), (pin)); \ gpio_set((port), (pin)); \

View File

@ -1,21 +1,42 @@
SYS = $(shell $(CC) -dumpmachine) SYS = $(shell $(CC) -dumpmachine)
CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG
CFLAGS +=-I ./target -I./platforms/pc CFLAGS +=-I ./target -I./platforms/pc
LDFLAGS += -lusb-1.0
CFLAGS += $(shell pkg-config --cflags libftdi1) ifneq (, $(findstring linux, $(SYS)))
LDFLAGS += $(shell pkg-config --libs libftdi1) SRC += serial_unix.c
ifneq (, $(findstring mingw, $(SYS))) CFLAGS += -fsanitize=address
LDFLAGS += -lasan
else ifneq (, $(findstring mingw, $(SYS)))
SRC += serial_win.c SRC += serial_win.c
LDFLAGS += -lws2_32 LDFLAGS += -lws2_32
LDFLAGS += -lsetupapi
else ifneq (, $(findstring cygwin, $(SYS))) else ifneq (, $(findstring cygwin, $(SYS)))
SRC += serial_win.c SRC += serial_win.c
LDFLAGS += -lws2_32 LDFLAGS += -lws2_32
else LDFLAGS += -lsetupapi
SRC += serial_unix.c #https://github.com/dmlc/xgboost/issues/1945 indicates macosx as indicator
else ifneq (filter, macosx darwin, $(SYS)))
LDFLAGS += -lsetupapi
LDFLAGS += hidapi/mac/.libs/libhidapi.a -framework IOKit
LDFLAGS += -framework CoreFoundation hidapi/mac/.libs/libhidapi.a
CFLAGS += -Ihidapi/hidapi
endif endif
LDFLAGS += -lusb-1.0
CFLAGS += $(shell pkg-config --cflags libftdi1)
LDFLAGS += $(shell pkg-config --libs libftdi1)
ifeq ($(shell pkg-config --exists hidapi-libusb && echo 0), 0)
CFLAGS += $(shell pkg-config --cflags hidapi-libusb)
LDFLAGS += $(shell pkg-config --libs hidapi-libusb)
CFLAGS += -DCMSIS_DAP
SRC += cmsis_dap.c dap.c
endif
VPATH += platforms/pc VPATH += platforms/pc
SRC += timing.c cl_utils.c utils.c libusb_utils.c SRC += timing.c cl_utils.c utils.c libusb_utils.c
SRC += stlinkv2.c SRC += stlinkv2.c
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c SRC += ftdi_bmp.c libftdi_swdptap.c libftdi_jtagtap.c
SRC += jlink.c jlink_adiv5_swdp.c jlink_jtagtap.c
PC_HOSTED = 1 PC_HOSTED = 1

View File

@ -0,0 +1,54 @@
# PC-Hosted BMP
Compile in src with "make PROBE_HOST=hosted"
## Description
PC-hosted BMP run on the PC and compiles as "blackmagic". When started,
it either presents a list of available probes or starts the BMP process
if either only one probe is attached to the PC or enough information is
given on the command line to select one of several probes.
When started without any other argument beside the probe selection, a
GDB server is started as port 2000 and up. Connect to the server as you would
connect to the BMP with the CDCACM GDB serial server. GDB functionality
is the same, monitor option may vary.
More arguments allow to
### print information on the connected target "blackmagiv -t"
### directly flash a binary file at 0x0800000 "blackmagic <file.bin>"
or with the -S argument at some other address
### read flash to binary file "blackmagic -r <file>.bin
### verify flash against binary file "blackmagic -V <file>.bin
Use "blackmagic -h" to see all options.
## Used libraries:
### libusb
### libftdi, for FTDI support
### hidapi-libusb, for CMSIS-DAP support
## Supported debuggers
REMOTE_BMP is a "normal" BMP usb connected
| Debugger | Speed | Remarks
| ------------ | ----- | ------
| REMOTE_BMP | +++ | Requires recent firmware for decent speed
| ST-Link V3 | ++++ | Requires recent firmware, Only STM32 devices supported!
| ST-Link V2 | +++ | Requires recent firmware, No CDCACM uart! Cortex only!
| ST-Link V2/1 | +++ | Requires recent firmware, Cortex only!
| CMSIS-DAP | +++ | Speed varies with MCU implementing CMSIS-DAP
| FTDI MPSSE | ++ | Requires a device descrition
| JLINK | - | Usefull to add BMP support for MCUs with built-in JLINK
## Feedback
### Issues and Pull request on https://github.com/blacksphere/blackmagic/
### Discussions on Discord.
You can find the Discord link here: https://1bitsquared.com/pages/chat
### Blackmagic mailing list http://sourceforge.net/mail/?group_id=407419
## Known deficiencies
### For REMOTE_BMP
#### On windows, the device node must be given on the command line
Finding the device from USB VID/PID/Serial in not yet implemented
### FTDI MPSSE
#### No auto detection
Cable description must be given on the command line

View File

@ -4,7 +4,7 @@
* Copyright (C) 2011 Black Sphere Technologies Ltd. * Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz> * Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Additions by Dave Marples <dave@marples.net> * Additions by Dave Marples <dave@marples.net>
* Additions by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * Modifications (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -26,6 +26,8 @@
#include "remote.h" #include "remote.h"
#include "target.h" #include "target.h"
#include "bmp_remote.h" #include "bmp_remote.h"
#include "cl_utils.h"
#include "hex_utils.h"
#include <assert.h> #include <assert.h>
#include <sys/time.h> #include <sys/time.h>
@ -35,7 +37,7 @@
#include "adiv5.h" #include "adiv5.h"
int remote_init(void) int remote_init(bool verbose)
{ {
char construct[REMOTE_MAX_MSG_SIZE]; char construct[REMOTE_MAX_MSG_SIZE];
int c = snprintf(construct, REMOTE_MAX_MSG_SIZE, "%s", REMOTE_START_STR); int c = snprintf(construct, REMOTE_MAX_MSG_SIZE, "%s", REMOTE_START_STR);
@ -43,12 +45,23 @@ int remote_init(void)
c = platform_buffer_read((uint8_t *)construct, REMOTE_MAX_MSG_SIZE); c = platform_buffer_read((uint8_t *)construct, REMOTE_MAX_MSG_SIZE);
if ((!c) || (construct[0] == REMOTE_RESP_ERR)) { if ((!c) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr,"Remote Start failed, error %s\n", DEBUG_WARN("Remote Start failed, error %s\n",
c ? (char *)&(construct[1]) : "unknown"); c ? (char *)&(construct[1]) : "unknown");
return -1; return -1;
} }
if (verbose)
printf("Remote is %s\n", &construct[1]); DEBUG_WARN("Remote is %s\n", &construct[1]);
char *p = strstr(&construct[1], "(Firmware v");
if (!p)
return -1;
int major = 0, minor = 0, step = 0;
int res = sscanf(p, "(Firmware v%d.%d.%d", &major, &minor, &step);
if (res !=3)
return -1;
uint32_t version = major * 10000 + minor * 100 + step;
/* check that firmare is > 1.6.1 */
if (version < 10602)
return -1;
return 0; return 0;
} }
@ -64,7 +77,7 @@ bool remote_target_get_power(void)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr," platform_target_get_power failed, error %s\n", DEBUG_WARN(" platform_target_get_power failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit (-1); exit (-1);
} }
@ -84,7 +97,7 @@ void remote_target_set_power(bool power)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_target_set_power failed, error %s\n", DEBUG_WARN("platform_target_set_power failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -102,7 +115,7 @@ void remote_srst_set_val(bool assert)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_srst_set_val failed, error %s\n", DEBUG_WARN("platform_srst_set_val failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -120,7 +133,7 @@ bool remote_srst_get_val(void)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_srst_set_val failed, error %s\n", DEBUG_WARN("platform_srst_set_val failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -139,9 +152,209 @@ const char *remote_target_voltage(void)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "platform_target_voltage failed, error %s\n", DEBUG_WARN("platform_target_voltage failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(- 1); exit(- 1);
} }
return (char *)&construct[1]; return (char *)&construct[1];
} }
static uint32_t remote_adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr)
{
(void)dp;
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, REMOTE_DP_READ_STR,
addr);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
unhexify(dest, (const char*)&construct[1], 4);
DEBUG_PROBE("dp_read addr %04x: %08" PRIx32 "\n", dest[0]);
return dest[0];
}
static uint32_t remote_adiv5_low_access(
ADIv5_DP_t *dp, uint8_t RnW, uint16_t addr, uint32_t value)
{
(void)dp;
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_LOW_ACCESS_STR, RnW, addr, value);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
unhexify(dest, (const char*)&construct[1], 4);
return dest[0];
}
static uint32_t remote_adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_AP_READ_STR,
ap->apsel, addr);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
uint32_t dest[1];
unhexify(dest, (const char*)&construct[1], 4);
return dest[0];
}
static void remote_adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,REMOTE_AP_WRITE_STR,
ap->apsel, addr, value);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
DEBUG_WARN("%s error %d\n", __func__, s);
}
return;
}
#if 0
static void remote_mem_read(
ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
(void)ap;
if (len == 0)
return;
DEBUG_WIRE("memread @ %" PRIx32 " len %ld, start: \n",
src, len);
uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s;
int batchsize = (REMOTE_MAX_MSG_SIZE - 32) / 2;
while(len) {
int count = len;
if (count > batchsize)
count = batchsize;
s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
REMOTE_MEM_READ_STR, src, count);
platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s > 0) && (construct[0] == REMOTE_RESP_OK)) {
unhexify(dest, (const char*)&construct[1], count);
src += count;
dest += count;
len -= count;
continue;
} else {
if(construct[0] == REMOTE_RESP_ERR) {
ap->dp->fault = 1;
DEBUG_WARN("%s returned REMOTE_RESP_ERR at addr: 0x%08x\n",
__func__, src);
break;
} else {
DEBUG_WARN("%s error %d\n", __func__, s);
break;
}
}
}
}
#endif
static void remote_ap_mem_read(
ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
(void)ap;
if (len == 0)
return;
char construct[REMOTE_MAX_MSG_SIZE];
int batchsize = (REMOTE_MAX_MSG_SIZE - 0x20) / 2;
while(len) {
int s;
int count = len;
if (count > batchsize)
count = batchsize;
s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
REMOTE_AP_MEM_READ_STR, ap->apsel, ap->csw, src, count);
platform_buffer_write((uint8_t*)construct, s);
s = platform_buffer_read((uint8_t*)construct, REMOTE_MAX_MSG_SIZE);
if ((s > 0) && (construct[0] == REMOTE_RESP_OK)) {
unhexify(dest, (const char*)&construct[1], count);
src += count;
dest += count;
len -= count;
continue;
} else {
if(construct[0] == REMOTE_RESP_ERR) {
ap->dp->fault = 1;
DEBUG_WARN("%s returned REMOTE_RESP_ERR at apsel %d, "
"addr: 0x%08" PRIx32 "\n", __func__, ap->apsel, src);
break;
} else {
DEBUG_WARN("%s error %d around 0x%08" PRIx32 "\n",
__func__, s, src);
break;
}
}
}
}
static void remote_ap_mem_write_sized(
ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len,
enum align align)
{
(void)ap;
if (len == 0)
return;
char construct[REMOTE_MAX_MSG_SIZE];
/* (5 * 1 (char)) + (2 * 2 (bytes)) + (3 * 8 (words)) */
int batchsize = (REMOTE_MAX_MSG_SIZE - 0x30) / 2;
while (len) {
int count = len;
if (count > batchsize)
count = batchsize;
int s = snprintf(construct, REMOTE_MAX_MSG_SIZE,
REMOTE_AP_MEM_WRITE_SIZED_STR,
ap->apsel, ap->csw, align, dest, count);
char *p = construct + s;
hexify(p, src, count);
p += 2 * count;
src += count;
dest += count;
len -= count;
*p++ = REMOTE_EOM;
*p = 0;
platform_buffer_write((uint8_t*)construct, p - construct);
s = platform_buffer_read((uint8_t*)construct, REMOTE_MAX_MSG_SIZE);
if ((s > 0) && (construct[0] == REMOTE_RESP_OK))
continue;
if ((s > 0) && (construct[0] == REMOTE_RESP_ERR)) {
ap->dp->fault = 1;
DEBUG_WARN("%s returned REMOTE_RESP_ERR at apsel %d, "
"addr: 0x%08x\n", __func__, ap->apsel, dest);
} else {
DEBUG_WARN("%s error %d around address 0x%08" PRIx32 "\n",
__func__, s, dest);
break;
}
}
}
void remote_adiv5_dp_defaults(ADIv5_DP_t *dp)
{
if (remote_init(false)) {
DEBUG_WARN(
"Please update BMP firmware for substantial speed increase!\n");
return;
}
dp->low_access = remote_adiv5_low_access;
dp->dp_read = remote_adiv5_dp_read;
dp->ap_write = remote_adiv5_ap_write;
dp->ap_read = remote_adiv5_ap_read;
dp->mem_read = remote_ap_mem_read;
dp->mem_write_sized = remote_ap_mem_write_sized;
}

View File

@ -20,13 +20,16 @@
#define __BMP_REMOTE_H_ #define __BMP_REMOTE_H_
#include "swdptap.h" #include "swdptap.h"
#include "jtagtap.h" #include "jtagtap.h"
#include "adiv5.h"
#include "target.h"
#include "target_internal.h"
#define REMOTE_MAX_MSG_SIZE (256) #define REMOTE_MAX_MSG_SIZE (1024)
int platform_buffer_write(const uint8_t *data, int size); int platform_buffer_write(const uint8_t *data, int size);
int platform_buffer_read(uint8_t *data, int size); int platform_buffer_read(uint8_t *data, int size);
int remote_init(void); int remote_init(bool verbose);
int remote_swdptap_init(swd_proc_t *swd_proc); int remote_swdptap_init(swd_proc_t *swd_proc);
int remote_jtagtap_init(jtag_proc_t *jtag_proc); int remote_jtagtap_init(jtag_proc_t *jtag_proc);
bool remote_target_get_power(void); bool remote_target_get_power(void);
@ -35,5 +38,6 @@ void remote_target_set_power(bool power);
void remote_srst_set_val(bool assert); void remote_srst_set_val(bool assert);
bool remote_srst_get_val(void); bool remote_srst_get_val(void);
const char *platform_target_voltage(void); const char *platform_target_voltage(void);
void remote_adiv5_dp_defaults(ADIv5_DP_t *dp);
#define __BMP_REMOTE_H_ #define __BMP_REMOTE_H_
#endif #endif

View File

@ -0,0 +1,357 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2019-20 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/>.
*/
/* Modified from edbg.c
* Links between bmp and edbg
*
* https://arm-software.github.io/CMSIS_5/DAP/html/index.html
*/
#include "general.h"
#include "gdb_if.h"
#include "adiv5.h"
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <sys/time.h>
#include <hidapi.h>
#include <wchar.h>
#include "dap.h"
#include "cmsis_dap.h"
#include "cl_utils.h"
#include "target.h"
#include "target_internal.h"
uint8_t dap_caps;
uint8_t mode;
/*- Variables ---------------------------------------------------------------*/
static hid_device *handle = NULL;
static uint8_t hid_buffer[1024 + 1];
static int report_size = 512 + 1; // TODO: read actual report size
/* LPC845 Breakout Board Rev. 0 report invalid response with > 65 bytes */
int dap_init(bmp_info_t *info)
{
if (hid_init())
return -1;
int size = strlen(info->serial);
wchar_t serial[size + 1], *wc = serial;
for (int i = 0; i < size; i++)
*wc++ = info->serial[i];
*wc = 0;
/* Blacklist devices that do not wirk with 513 byte report length
* FIXME: Find a solution to decipher from the device.
*/
if ((info->vid == 0x1fc9) && (info->pid == 0x0132)) {
DEBUG_WARN("Blacklist\n");
report_size = 64 + 1;
}
handle = hid_open(info->vid, info->pid, serial);
if (!handle)
return -1;
dap_disconnect();
size = dap_info(DAP_INFO_CAPABILITIES, hid_buffer, sizeof(hid_buffer));
dap_caps = hid_buffer[0];
DEBUG_INFO(" Cap (0x%2x): %s%s%s", hid_buffer[0],
(hid_buffer[0] & 1)? "SWD" : "",
((hid_buffer[0] & 3) == 3) ? "/" : "",
(hid_buffer[0] & 2)? "JTAG" : "");
if (hid_buffer[0] & 4)
DEBUG_INFO(", SWO_UART");
if (hid_buffer[0] & 8)
DEBUG_INFO(", SWO_MANCHESTER");
if (hid_buffer[0] & 0x10)
DEBUG_INFO(", Atomic Cmds");
DEBUG_INFO("\n");
return 0;
}
static void dap_dp_abort(ADIv5_DP_t *dp, uint32_t abort)
{
/* DP Write to Reg 0.*/
dap_write_reg(dp, ADIV5_DP_ABORT, abort);
}
static uint32_t dap_dp_error(ADIv5_DP_t *dp)
{
uint32_t ctrlstat = dap_read_reg(dp, ADIV5_DP_CTRLSTAT);
uint32_t err = ctrlstat &
(ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP |
ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR);
uint32_t clr = 0;
if(err & ADIV5_DP_CTRLSTAT_STICKYORUN)
clr |= ADIV5_DP_ABORT_ORUNERRCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYCMP)
clr |= ADIV5_DP_ABORT_STKCMPCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYERR)
clr |= ADIV5_DP_ABORT_STKERRCLR;
if(err & ADIV5_DP_CTRLSTAT_WDATAERR)
clr |= ADIV5_DP_ABORT_WDERRCLR;
dap_write_reg(dp, ADIV5_DP_ABORT, clr);
dp->fault = 0;
return err;
}
static uint32_t dap_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
uint16_t addr, uint32_t value)
{
bool APnDP = addr & ADIV5_APnDP;
uint32_t res = 0;
uint8_t reg = (addr & 0xc) | ((APnDP)? 1 : 0);
if (RnW) {
res = dap_read_reg(dp, reg);
}
else {
dap_write_reg(dp, reg, value);
}
return res;
}
static uint32_t dap_dp_read_reg(ADIv5_DP_t *dp, uint16_t addr)
{
return dap_read_reg(dp, addr);
}
void dap_exit_function(void)
{
if (handle) {
dap_disconnect();
hid_close(handle);
}
}
int dbg_get_report_size(void)
{
return report_size;
}
int dbg_dap_cmd(uint8_t *data, int size, int rsize)
{
char cmd = data[0];
int res;
memset(hid_buffer, 0xff, report_size + 1);
hid_buffer[0] = 0x00; // Report ID??
memcpy(&hid_buffer[1], data, rsize);
DEBUG_WIRE("cmd : ");
for(int i = 0; (i < 16) && (i < rsize + 1); i++)
DEBUG_WIRE("%02x.", hid_buffer[i]);
DEBUG_WIRE("\n");
res = hid_write(handle, hid_buffer, rsize + 1);
if (res < 0) {
DEBUG_WARN( "Error: %ls\n", hid_error(handle));
exit(-1);
}
if (size) {
res = hid_read(handle, hid_buffer, report_size + 1);
if (res < 0) {
DEBUG_WARN( "debugger read(): %ls\n", hid_error(handle));
exit(-1);
}
if (size && hid_buffer[0] != cmd) {
DEBUG_WARN("cmd %02x invalid response received %02x\n",
cmd, hid_buffer[0]);
}
res--;
memcpy(data, &hid_buffer[1], (size < res) ? size : res);
DEBUG_WIRE("cmd res:");
for(int i = 0; (i < 16) && (i < size + 4); i++)
DEBUG_WIRE("%02x.", hid_buffer[i]);
DEBUG_WIRE("\n");
}
return res;
}
#define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \
(((x) & 1) == 0 ? ALIGN_HALFWORD : ALIGN_BYTE))
static void dap_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
if (len == 0)
return;
enum align align = MIN(ALIGNOF(src), ALIGNOF(len));
DEBUG_WIRE("memread @ %" PRIx32 " len %ld, align %d , start: \n",
src, len, align);
if (((unsigned)(1 << align)) == len)
return dap_read_single(ap, dest, src, align);
/* One word transfer for every byte/halfword/word
* Total number of bytes in transfer*/
unsigned int max_size = (dbg_get_report_size() - 5) >> (2 - align);
while (len) {
dap_ap_mem_access_setup(ap, src, align);
/* Calculate length until next access setup is needed */
unsigned int blocksize = (src | 0x3ff) - src + 1;
if (blocksize > len)
blocksize = len;
while (blocksize) {
unsigned int transfersize = blocksize;
if (transfersize > max_size)
transfersize = max_size;
unsigned int res = dap_read_block(ap, dest, src, transfersize,
align);
if (res) {
DEBUG_WIRE("mem_read failed %02x\n", res);
ap->dp->fault = 1;
return;
}
blocksize -= transfersize;
len -= transfersize;
dest += transfersize;
src += transfersize;
}
}
DEBUG_WIRE("memread res last data %08" PRIx32 "\n", ((uint32_t*)dest)[-1]);
}
static void dap_mem_write_sized(
ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{
if (len == 0)
return;
DEBUG_WIRE("memwrite @ %" PRIx32 " len %ld, align %d , %08x start: \n",
dest, len, align, *(uint32_t *)src);
if (((unsigned)(1 << align)) == len)
return dap_write_single(ap, dest, src, align);
unsigned int max_size = (dbg_get_report_size() - 5) >> (2 - align);
while (len) {
dap_ap_mem_access_setup(ap, dest, align);
unsigned int blocksize = (dest | 0x3ff) - dest + 1;
if (blocksize > len)
blocksize = len;
while (blocksize) {
unsigned int transfersize = blocksize;
if (transfersize > max_size)
transfersize = max_size;
unsigned int res = dap_write_block(ap, dest, src, transfersize,
align);
if (res) {
DEBUG_WARN("mem_write failed %02x\n", res);
ap->dp->fault = 1;
return;
}
blocksize -= transfersize;
len -= transfersize;
dest += transfersize;
src += transfersize;
}
}
DEBUG_WIRE("memwrite done\n");
}
int dap_enter_debug_swd(ADIv5_DP_t *dp)
{
target_list_free();
if (!(dap_caps & DAP_CAP_SWD))
return -1;
mode = DAP_CAP_SWD;
dap_swj_clock(2000000);
dap_transfer_configure(2, 128, 128);
dap_swd_configure(0);
dap_connect(false);
dap_led(0, 1);
dap_reset_link(false);
dp->idcode = dap_read_idcode(dp);
dp->dp_read = dap_dp_read_reg;
dp->error = dap_dp_error;
dp->low_access = dap_dp_low_access;
dp->abort = dap_dp_abort; /* DP Write to Reg 0.*/
return 0;
}
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp)
{
if ((mode == DAP_CAP_JTAG) && dap_jtag_configure())
return;
dp->ap_read = dap_ap_read;
dp->ap_write = dap_ap_write;
dp->mem_read = dap_mem_read;
dp->mem_write_sized = dap_mem_write_sized;
}
static void cmsis_dap_jtagtap_reset(void)
{
jtagtap_soft_reset();
/* Is there a way to know if TRST is available?*/
}
static void cmsis_dap_jtagtap_tms_seq(uint32_t MS, int ticks)
{
uint8_t TMS[4] = {MS & 0xff, (MS >> 8) & 0xff, (MS >> 16) & 0xff,
(MS >> 24) & 0xff};
dap_jtagtap_tdi_tdo_seq(NULL, false, TMS, NULL, ticks);
DEBUG_PROBE("tms_seq DI %08x %d\n", MS, ticks);
}
static void cmsis_dap_jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms,
const uint8_t *DI, int ticks)
{
dap_jtagtap_tdi_tdo_seq(DO, (final_tms), NULL, DI, ticks);
DEBUG_PROBE("jtagtap_tdi_tdo_seq %d, %02x-> %02x\n", ticks, DI[0], DO[0]);
}
static void cmsis_dap_jtagtap_tdi_seq(const uint8_t final_tms,
const uint8_t *DI, int ticks)
{
dap_jtagtap_tdi_tdo_seq(NULL, (final_tms), NULL, DI, ticks);
DEBUG_PROBE("jtagtap_tdi_seq %d, %02x\n", ticks, DI[0]);
}
static uint8_t cmsis_dap_jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
uint8_t tdo[1];
dap_jtagtap_tdi_tdo_seq(tdo, false, &dTMS, &dTDI, 1);
DEBUG_PROBE("next tms %02x tdi %02x tdo %02x\n", dTMS, dTDI, tdo[0]);
return (tdo[0] & 1);
}
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc)
{
DEBUG_PROBE("jtap_init\n");
if (!(dap_caps & DAP_CAP_JTAG))
return -1;
mode = DAP_CAP_JTAG;
dap_disconnect();
dap_connect(true);
dap_swj_clock(2000000);
jtag_proc->jtagtap_reset = cmsis_dap_jtagtap_reset;
jtag_proc->jtagtap_next = cmsis_dap_jtagtap_next;
jtag_proc->jtagtap_tms_seq = cmsis_dap_jtagtap_tms_seq;
jtag_proc->jtagtap_tdi_tdo_seq = cmsis_dap_jtagtap_tdi_tdo_seq;
jtag_proc->jtagtap_tdi_seq = cmsis_dap_jtagtap_tdi_seq;
dap_reset_link(true);
return 0;
}
int dap_jtag_dp_init(ADIv5_DP_t *dp)
{
dp->dp_read = dap_dp_read_reg;
dp->error = dap_dp_error;
dp->low_access = dap_dp_low_access;
dp->abort = dap_dp_abort;
return true;
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 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/>.
*/
#if !defined(__CMSIS_DAP_H_)
#define __CMSIS_DAP_H_
#include "adiv5.h"
#include "cl_utils.h"
#if defined(CMSIS_DAP)
int dap_init(bmp_info_t *info);
int dap_enter_debug_swd(ADIv5_DP_t *dp);
void dap_exit_function(void);
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp);
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc);
int dap_jtag_dp_init(ADIv5_DP_t *dp);
#else
int dap_init(bmp_info_t *info) {(void)info; return -1;}
int dap_enter_debug_swd(ADIv5_DP_t *dp) {(void)dp; return -1;}
void dap_exit_function(void) {return;};
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp) {(void)dp; return; }
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc)
{
(void)jtag_proc;
return -1;
}
int dap_jtag_dp_init(ADIv5_DP_t *dp)
{
(void)dp;
return -1;
}
#endif
#endif

750
src/platforms/hosted/dap.c Normal file
View File

@ -0,0 +1,750 @@
/*
* Copyright (c) 2013-2015, Alex Taradov <alex@taradov.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Modified for Blackmagic Probe
* Copyright (c) 2020 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
*/
/*- Includes ----------------------------------------------------------------*/
#include <general.h>
#include <stdlib.h>
#include "dap.h"
#include "jtag_scan.h"
/*- Definitions -------------------------------------------------------------*/
enum
{
ID_DAP_INFO = 0x00,
ID_DAP_LED = 0x01,
ID_DAP_CONNECT = 0x02,
ID_DAP_DISCONNECT = 0x03,
ID_DAP_TRANSFER_CONFIGURE = 0x04,
ID_DAP_TRANSFER = 0x05,
ID_DAP_TRANSFER_BLOCK = 0x06,
ID_DAP_TRANSFER_ABORT = 0x07,
ID_DAP_WRITE_ABORT = 0x08,
ID_DAP_DELAY = 0x09,
ID_DAP_RESET_TARGET = 0x0a,
ID_DAP_SWJ_PINS = 0x10,
ID_DAP_SWJ_CLOCK = 0x11,
ID_DAP_SWJ_SEQUENCE = 0x12,
ID_DAP_SWD_CONFIGURE = 0x13,
ID_DAP_JTAG_SEQUENCE = 0x14,
ID_DAP_JTAG_CONFIGURE = 0x15,
ID_DAP_JTAG_IDCODE = 0x16,
};
enum
{
DAP_TRANSFER_APnDP = 1 << 0,
DAP_TRANSFER_RnW = 1 << 1,
DAP_TRANSFER_A2 = 1 << 2,
DAP_TRANSFER_A3 = 1 << 3,
DAP_TRANSFER_MATCH_VALUE = 1 << 4,
DAP_TRANSFER_MATCH_MASK = 1 << 5,
};
enum
{
DAP_TRANSFER_INVALID = 0,
DAP_TRANSFER_OK = 1 << 0,
DAP_TRANSFER_WAIT = 1 << 1,
DAP_TRANSFER_FAULT = 1 << 2,
DAP_TRANSFER_ERROR = 1 << 3,
DAP_TRANSFER_MISMATCH = 1 << 4,
DAP_TRANSFER_NO_TARGET = 7,
};
enum
{
DAP_SWJ_SWCLK_TCK = 1 << 0,
DAP_SWJ_SWDIO_TMS = 1 << 1,
DAP_SWJ_TDI = 1 << 2,
DAP_SWJ_TDO = 1 << 3,
DAP_SWJ_nTRST = 1 << 5,
DAP_SWJ_nRESET = 1 << 7,
};
enum
{
DAP_OK = 0x00,
DAP_ERROR = 0xff,
};
enum
{
DAP_JTAG_TMS = 1 << 6,
DAP_JTAG_TDO_CAPTURE = 1 << 7,
};
enum
{
SWD_DP_R_IDCODE = 0x00,
SWD_DP_W_ABORT = 0x00,
SWD_DP_R_CTRL_STAT = 0x04,
SWD_DP_W_CTRL_STAT = 0x04, // When CTRLSEL == 0
SWD_DP_W_WCR = 0x04, // When CTRLSEL == 1
SWD_DP_R_RESEND = 0x08,
SWD_DP_W_SELECT = 0x08,
SWD_DP_R_RDBUFF = 0x0c,
};
enum
{
SWD_AP_CSW = 0x00 | DAP_TRANSFER_APnDP,
SWD_AP_TAR = 0x04 | DAP_TRANSFER_APnDP,
SWD_AP_DRW = 0x0c | DAP_TRANSFER_APnDP,
SWD_AP_DB0 = 0x00 | DAP_TRANSFER_APnDP, // 0x10
SWD_AP_DB1 = 0x04 | DAP_TRANSFER_APnDP, // 0x14
SWD_AP_DB2 = 0x08 | DAP_TRANSFER_APnDP, // 0x18
SWD_AP_DB3 = 0x0c | DAP_TRANSFER_APnDP, // 0x1c
SWD_AP_CFG = 0x04 | DAP_TRANSFER_APnDP, // 0xf4
SWD_AP_BASE = 0x08 | DAP_TRANSFER_APnDP, // 0xf8
SWD_AP_IDR = 0x0c | DAP_TRANSFER_APnDP, // 0xfc
};
#define DP_ABORT_DAPABORT (1 << 0)
#define DP_ABORT_STKCMPCLR (1 << 1)
#define DP_ABORT_STKERRCLR (1 << 2)
#define DP_ABORT_WDERRCLR (1 << 3)
#define DP_ABORT_ORUNERRCLR (1 << 4)
#define DP_CST_ORUNDETECT (1 << 0)
#define DP_CST_STICKYORUN (1 << 1)
#define DP_CST_TRNMODE_NORMAL (0 << 2)
#define DP_CST_TRNMODE_VERIFY (1 << 2)
#define DP_CST_TRNMODE_COMPARE (2 << 2)
#define DP_CST_STICKYCMP (1 << 4)
#define DP_CST_STICKYERR (1 << 5)
#define DP_CST_READOK (1 << 6)
#define DP_CST_WDATAERR (1 << 7)
#define DP_CST_MASKLANE(x) ((x) << 8)
#define DP_CST_TRNCNT(x) ((x) << 12)
#define DP_CST_CDBGRSTREQ (1 << 26)
#define DP_CST_CDBGRSTACK (1 << 27)
#define DP_CST_CDBGPWRUPREQ (1 << 28)
#define DP_CST_CDBGPWRUPACK (1 << 29)
#define DP_CST_CSYSPWRUPREQ (1 << 30)
#define DP_CST_CSYSPWRUPACK (1 << 31)
#define DP_SELECT_CTRLSEL (1 << 0)
#define DP_SELECT_APBANKSEL(x) ((x) << 4)
#define DP_SELECT_APSEL(x) ((x) << 24)
#define AP_CSW_SIZE_BYTE (0 << 0)
#define AP_CSW_SIZE_HALF (1 << 0)
#define AP_CSW_SIZE_WORD (2 << 0)
#define AP_CSW_ADDRINC_OFF (0 << 4)
#define AP_CSW_ADDRINC_SINGLE (1 << 4)
#define AP_CSW_ADDRINC_PACKED (2 << 4)
#define AP_CSW_DEVICEEN (1 << 6)
#define AP_CSW_TRINPROG (1 << 7)
#define AP_CSW_SPIDEN (1 << 23)
#define AP_CSW_PROT(x) ((x) << 24)
#define AP_CSW_DBGSWENABLE (1 << 31)
/*- Implementations ---------------------------------------------------------*/
//-----------------------------------------------------------------------------
void dap_led(int index, int state)
{
uint8_t buf[3];
buf[0] = ID_DAP_LED;
buf[1] = index;
buf[2] = state;
dbg_dap_cmd(buf, sizeof(buf), 3);
}
//-----------------------------------------------------------------------------
void dap_connect(bool jtag)
{
uint8_t buf[2];
buf[0] = ID_DAP_CONNECT;
buf[1] = (jtag) ? DAP_CAP_JTAG : DAP_CAP_SWD;
dbg_dap_cmd(buf, sizeof(buf), 2);
}
//-----------------------------------------------------------------------------
void dap_disconnect(void)
{
uint8_t buf[1];
buf[0] = ID_DAP_DISCONNECT;
dbg_dap_cmd(buf, sizeof(buf), 1);
}
//-----------------------------------------------------------------------------
void dap_swj_clock(uint32_t clock)
{
uint8_t buf[5];
buf[0] = ID_DAP_SWJ_CLOCK;
buf[1] = clock & 0xff;
buf[2] = (clock >> 8) & 0xff;
buf[3] = (clock >> 16) & 0xff;
buf[4] = (clock >> 24) & 0xff;
dbg_dap_cmd(buf, sizeof(buf), 5);
}
//-----------------------------------------------------------------------------
void dap_transfer_configure(uint8_t idle, uint16_t count, uint16_t retry)
{
uint8_t buf[6];
buf[0] = ID_DAP_TRANSFER_CONFIGURE;
buf[1] = idle;
buf[2] = count & 0xff;
buf[3] = (count >> 8) & 0xff;
buf[4] = retry & 0xff;
buf[5] = (retry >> 8) & 0xff;
dbg_dap_cmd(buf, sizeof(buf), 6);
}
//-----------------------------------------------------------------------------
void dap_swd_configure(uint8_t cfg)
{
uint8_t buf[2];
buf[0] = ID_DAP_SWD_CONFIGURE;
buf[1] = cfg;
dbg_dap_cmd(buf, sizeof(buf), 2);
}
//-----------------------------------------------------------------------------
int dap_info(int info, uint8_t *data, int size)
{
uint8_t buf[256];
int rsize;
buf[0] = ID_DAP_INFO;
buf[1] = info;
dbg_dap_cmd(buf, sizeof(buf), 2);
rsize = (size < buf[0]) ? size : buf[0];
memcpy(data, &buf[1], rsize);
if (rsize < size)
data[rsize] = 0;
return rsize;
}
void dap_reset_pin(int state)
{
uint8_t buf[7];
buf[0] = ID_DAP_SWJ_PINS;
buf[1] = state ? DAP_SWJ_nRESET : 0; // Value
buf[2] = DAP_SWJ_nRESET; // Select
buf[3] = 0; // Wait
buf[4] = 0;
buf[5] = 0;
buf[6] = 0;
dbg_dap_cmd(buf, sizeof(buf), 7);
}
void dap_trst_reset(void)
{
uint8_t buf[7];
buf[0] = ID_DAP_SWJ_PINS;
buf[1] = DAP_SWJ_nTRST;
buf[2] = 0;
buf[3] = 0;
buf[4] = 4; /* ~ 1 ms*/
buf[5] = 0;
buf[6] = 0;
dbg_dap_cmd(buf, sizeof(buf), 7);
buf[0] = ID_DAP_SWJ_PINS;
buf[1] = DAP_SWJ_nTRST;
buf[2] = DAP_SWJ_nTRST;
dbg_dap_cmd(buf, sizeof(buf), 7);
}
static void dap_line_reset(void)
{
uint8_t buf[] = {
ID_DAP_SWJ_SEQUENCE,
64,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0xff,
0
};
dbg_dap_cmd(buf, sizeof(buf), 10);
if (buf[0])
DEBUG_WARN("line reset failed\n");
}
static uint32_t wait_word(uint8_t *buf, int size, int len, uint8_t *dp_fault)
{
do {
dbg_dap_cmd(buf, size, len);
if (buf[1] < DAP_TRANSFER_WAIT)
break;
} while (buf[1] == DAP_TRANSFER_WAIT);
if (buf[1] > DAP_TRANSFER_WAIT) {
// DEBUG_WARN("dap_read_reg fault\n");
*dp_fault = 1;
}
if (buf[1] == DAP_TRANSFER_ERROR) {
DEBUG_WARN("dap_read_reg, protocoll error\n");
dap_line_reset();
}
uint32_t res =
((uint32_t)buf[5] << 24) | ((uint32_t)buf[4] << 16) |
((uint32_t)buf[3] << 8) | (uint32_t)buf[2];
return res;
}
//-----------------------------------------------------------------------------
uint32_t dap_read_reg(ADIv5_DP_t *dp, uint8_t reg)
{
uint8_t buf[8];
uint8_t dap_index = 0;
if (dp->dev)
dap_index = dp->dev->dev;
buf[0] = ID_DAP_TRANSFER;
buf[1] = dap_index;
buf[2] = 0x01; // Request size
buf[3] = reg | DAP_TRANSFER_RnW;
uint32_t res = wait_word(buf, 8, 4, &dp->fault);
DEBUG_WIRE("\tdap_read_reg %02x %08x\n", reg, res);
return res;
}
//-----------------------------------------------------------------------------
void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data)
{
uint8_t buf[8];
DEBUG_PROBE("\tdap_write_reg %02x %08x\n", reg, data);
buf[0] = ID_DAP_TRANSFER;
uint8_t dap_index = 0;
if (dp->dev)
dap_index = dp->dev->dev;
buf[1] = dap_index;
buf[2] = 0x01; // Request size
buf[3] = reg & ~DAP_TRANSFER_RnW;;
buf[4] = data & 0xff;
buf[5] = (data >> 8) & 0xff;
buf[6] = (data >> 16) & 0xff;
buf[7] = (data >> 24) & 0xff;
do {
dbg_dap_cmd(buf, sizeof(buf), 8);
if (buf[1] < DAP_TRANSFER_WAIT)
break;
} while (buf[1] == DAP_TRANSFER_WAIT);
if (buf[1] > DAP_TRANSFER_WAIT) {
DEBUG_PROBE("dap_write_reg %02x data %08x:fault\n", reg, data);
dp->fault = 1;
}
if (buf[1] == DAP_TRANSFER_ERROR) {
DEBUG_PROBE("dap_write_reg %02x data %08x: protocoll error\n",
reg, data);
dap_line_reset();
}
}
unsigned int dap_read_block(ADIv5_AP_t *ap, void *dest, uint32_t src,
size_t len, enum align align)
{
uint8_t buf[1024];
unsigned int sz = len >> align;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
buf[0] = ID_DAP_TRANSFER_BLOCK;
buf[1] = dap_index;
buf[2] = sz & 0xff;
buf[3] = (sz >> 8) & 0xff;
buf[4] = SWD_AP_DRW | DAP_TRANSFER_RnW;
dbg_dap_cmd(buf, 1023, 5 + 1);
unsigned int transferred = buf[0] + (buf[1] << 8);
if (buf[2] > DAP_TRANSFER_FAULT) {
DEBUG_PROBE("line_reset\n");
dap_line_reset();
}
if (sz != transferred) {
return 1;
} else if (align > ALIGN_HALFWORD) {
memcpy(dest, &buf[3], len);
} else {
uint32_t *p = (uint32_t *)&buf[3];
while(sz) {
dest = extract(dest, src, *p, align);
p++;
src += (1 << align);
dest += (1 << align);
sz--;
}
}
return (buf[2] > DAP_TRANSFER_WAIT) ? 1 : 0;
}
unsigned int dap_write_block(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{
uint8_t buf[1024];
unsigned int sz = len >> align;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
buf[0] = ID_DAP_TRANSFER_BLOCK;
buf[1] = dap_index;
buf[2] = sz & 0xff;
buf[3] = (sz >> 8) & 0xff;
buf[4] = SWD_AP_DRW;
if (align > ALIGN_HALFWORD) {
memcpy(&buf[5], src, len);
} else {
unsigned int size = len;
uint32_t *p = (uint32_t *)&buf[5];
while (size) {
uint32_t tmp = 0;
/* Pack data into correct data lane */
if (align == ALIGN_BYTE) {
tmp = ((uint32_t)*(uint8_t *)src) << ((dest & 3) << 3);
} else {
tmp = ((uint32_t)*(uint16_t *)src) << ((dest & 2) << 3);
}
src = src + (1 << align);
dest += (1 << align);
size--;
*p++ = tmp;
}
}
dbg_dap_cmd(buf, 1023, 5 + (sz << 2));
if (buf[2] > DAP_TRANSFER_FAULT) {
dap_line_reset();
}
return (buf[2] > DAP_TRANSFER_WAIT) ? 1 : 0;
}
//-----------------------------------------------------------------------------
void dap_reset_link(bool jtag)
{
uint8_t buf[128], *p = buf;
//-------------
*p++ = ID_DAP_SWJ_SEQUENCE;
p++;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
if (jtag) {
*p++ = 0x3c;
*p++ = 0xe7;
*p++ = 0x1f;
buf[1] = ((p - &buf[2]) * 8) - 2;
} else {
*p++ = 0x9e;
*p++ = 0xe7;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0xff;
*p++ = 0x00;
buf[1] = (p - &buf[2]) * 8;
}
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (!jtag) {
//-------------
buf[0] = ID_DAP_TRANSFER;
buf[1] = 0; // DAP index
buf[2] = 1; // Request size
buf[3] = SWD_DP_R_IDCODE | DAP_TRANSFER_RnW;
dbg_dap_cmd(buf, sizeof(buf), 4);
}
}
//-----------------------------------------------------------------------------
uint32_t dap_read_idcode(ADIv5_DP_t *dp)
{
return dap_read_reg(dp, SWD_DP_R_IDCODE);
}
static uint8_t *mem_access_setup(ADIv5_AP_t *ap, uint8_t *p,
uint32_t addr, enum align align)
{
uint32_t csw = ap->csw | ADIV5_AP_CSW_ADDRINC_SINGLE;
switch (align) {
case ALIGN_BYTE:
csw |= ADIV5_AP_CSW_SIZE_BYTE;
break;
case ALIGN_HALFWORD:
csw |= ADIV5_AP_CSW_SIZE_HALFWORD;
break;
case ALIGN_DWORD:
case ALIGN_WORD:
csw |= ADIV5_AP_CSW_SIZE_WORD;
break;
}
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 3; /* Nr transfers */
*p++ = SWD_DP_W_SELECT;
*p++ = ADIV5_AP_CSW & 0xF0;
*p++ = 0;
*p++ = 0;
*p++ = ap->apsel & 0xff;
*p++ = SWD_AP_CSW;
*p++ = (csw >> 0) & 0xff;
*p++ = (csw >> 8) & 0xff;
*p++ = (csw >> 16) & 0xff;
*p++ = (csw >> 24) & 0xff;
*p++ = SWD_AP_TAR ;
*p++ = (addr >> 0) & 0xff;
*p++ = (addr >> 8) & 0xff;
*p++ = (addr >> 16) & 0xff;
*p++ = (addr >> 24) & 0xff;
return p;
}
void dap_ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align)
{
uint8_t buf[63];
uint8_t *p = mem_access_setup(ap, buf, addr, align);
dbg_dap_cmd(buf, sizeof(buf), p - buf);
}
uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
DEBUG_PROBE("dap_ap_read_start\n");
uint8_t buf[63], *p = buf;
buf[0] = ID_DAP_TRANSFER;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 2; /* Nr transfers */
*p++ = SWD_DP_W_SELECT;
*p++ = (addr & 0xF0);
*p++ = 0;
*p++ = 0;
*p++ = ap->apsel & 0xff;
*p++ = (addr & 0x0c) | DAP_TRANSFER_RnW |
((addr & 0x100) ? DAP_TRANSFER_APnDP : 0);
uint32_t res = wait_word(buf, 63, p - buf, &ap->dp->fault);
return res;
}
void dap_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{
DEBUG_PROBE("dap_ap_write addr %04x value %08x\n", addr, value);
uint8_t buf[63], *p = buf;
uint8_t dap_index = 0;
if (ap->dp->dev)
dap_index = ap->dp->dev->dev;
*p++ = ID_DAP_TRANSFER;
*p++ = dap_index;
*p++ = 2; /* Nr transfers */
*p++ = SWD_DP_W_SELECT;
*p++ = (addr & 0xF0);
*p++ = 0;
*p++ = 0;
*p++ = ap->apsel & 0xff;
*p++ = (addr & 0x0c) | ((addr & 0x100) ? DAP_TRANSFER_APnDP : 0);
*p++ = (value >> 0) & 0xff;
*p++ = (value >> 8) & 0xff;
*p++ = (value >> 16) & 0xff;
*p++ = (value >> 24) & 0xff;
dbg_dap_cmd(buf, sizeof(buf), p - buf);
}
void dap_read_single(ADIv5_AP_t *ap, void *dest, uint32_t src, enum align align)
{
uint8_t buf[63];
uint8_t *p = mem_access_setup(ap, buf, src, align);
*p++ = SWD_AP_DRW | DAP_TRANSFER_RnW;
buf[2] = 4;
uint32_t tmp = wait_word(buf, 63, p - buf, &ap->dp->fault);
dest = extract(dest, src, tmp, align);
}
void dap_write_single(ADIv5_AP_t *ap, uint32_t dest, const void *src,
enum align align)
{
uint8_t buf[63];
uint8_t *p = mem_access_setup(ap, buf, dest, align);
*p++ = SWD_AP_DRW;
uint32_t tmp = 0;
/* Pack data into correct data lane */
switch (align) {
case ALIGN_BYTE:
tmp = ((uint32_t)*(uint8_t *)src) << ((dest & 3) << 3);
break;
case ALIGN_HALFWORD:
tmp = ((uint32_t)*(uint16_t *)src) << ((dest & 2) << 3);
break;
case ALIGN_DWORD:
case ALIGN_WORD:
tmp = *(uint32_t *)src;
break;
}
*p++ = (tmp >> 0) & 0xff;
*p++ = (tmp >> 8) & 0xff;
*p++ = (tmp >> 16) & 0xff;
*p++ = (tmp >> 24) & 0xff;
buf[2] = 4;
dbg_dap_cmd(buf, sizeof(buf), p - buf);
}
void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
const uint8_t *DI, int ticks)
{
uint8_t buf[64];
if (!TMS) {
int last_byte = 0;
int last_bit = 0;
if (final_tms) {
last_byte = ticks >> 3;
last_bit = ticks & 7;
ticks --;
}
while (ticks) {
int transfers = ticks;
if (transfers > 64)
transfers = 64;
uint8_t *p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = 1;
*p++ = transfers | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0);
int n_di_bytes = (transfers + 7) >> 3;
if (DI) {
p = memcpy(p, DI, n_di_bytes);
DI += n_di_bytes;
} else {
p = memset(p, 0xff, n_di_bytes);
}
p += n_di_bytes;
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] != DAP_OK)
DEBUG_WARN("dap_jtagtap_tdi_tdo_seq failed %02x\n", buf[0]);
if (DO) {
memcpy(DO, &buf[1], (transfers + 7) >> 3);
DO += (transfers + 7) >> 3;
}
ticks -= transfers;
}
if (final_tms) {
uint8_t *p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = 1;
*p++ = 1 | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0) | DAP_JTAG_TMS;
if (DI) {
*p++ = ((DI[last_byte] & (1 << last_bit)) ? 1 : 0);
} else {
*p++ = 0;
}
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] == DAP_ERROR)
DEBUG_WARN("dap_jtagtap_tdi_tdo_seq failed %02x\n", buf[0]);
if (DO) {
if (buf[1] & 1)
DO[last_byte] |= (1 << last_bit);
else
DO[last_byte] &= ~(1 << last_bit);
}
}
} else {
while(ticks) {
uint8_t *p = buf;
int transfers = ticks;
if (transfers > 64)
transfers = 64;
p = buf;
*p++ = ID_DAP_JTAG_SEQUENCE;
*p++ = transfers;
for (int i = 0; i < transfers; i++) {
*p++ = 1 | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0) |
((TMS[i >> 8] & (1 << (i & 7))) ? DAP_JTAG_TMS : 0);
if (DI)
*p++ = (DI[i >> 8] & (1 << (i & 7))) ? 1 : 0;
else
*p++ = 0x55;
}
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] == DAP_ERROR)
DEBUG_WARN("dap_jtagtap_tdi_tdo_seq failed %02x\n", buf[0]);
if (DO) {
for (int i = 0; i < transfers; i++) {
if (buf[i + 1])
DO[i >> 8] |= (1 << (i & 7));
else
DO[i >> 8] &= ~(1 << (i & 7));
}
}
ticks -= transfers;
}
}
}
int dap_jtag_configure(void)
{
uint8_t buf[64], *p = &buf[2];
int i = 0;
for (; i < jtag_dev_count; i++) {
struct jtag_dev_s *jtag_dev = &jtag_devs[i];
*p++ = jtag_dev->ir_len;
DEBUG_PROBE("irlen %d\n", jtag_dev->ir_len);
}
if ((!i || i >= JTAG_MAX_DEVS))
return -1;
buf[0] = 0x15;
buf[1] = i;
dbg_dap_cmd(buf, sizeof(buf), p - buf);
if (buf[0] != DAP_OK)
DEBUG_WARN("dap_jtag_configure Failed %02x\n", buf[0]);
return 0;
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2013-2015, Alex Taradov <alex@taradov.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DAP_H_
#define _DAP_H_
/*- Includes ----------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include "adiv5.h"
/*- Definitions -------------------------------------------------------------*/
enum
{
DAP_INFO_VENDOR = 0x01,
DAP_INFO_PRODUCT = 0x02,
DAP_INFO_SER_NUM = 0x03,
DAP_INFO_FW_VER = 0x04,
DAP_INFO_DEVICE_VENDOR = 0x05,
DAP_INFO_DEVICE_NAME = 0x06,
DAP_INFO_CAPABILITIES = 0xf0,
DAP_INFO_TDT = 0xf1,
DAP_INFO_SWO_BUF_SIZE = 0xfd,
DAP_INFO_PACKET_COUNT = 0xfe,
DAP_INFO_PACKET_SIZE = 0xff,
};
enum
{
DAP_CAP_SWD = (1 << 0),
DAP_CAP_JTAG = (1 << 1),
DAP_CAP_SWO_UART = (1 << 2),
DAP_CAP_SWO_MANCHESTER = (1 << 3),
DAP_CAP_ATOMIC_CMD = (1 << 4),
DAP_CAP_TDT = (1 << 5),
DAP_CAP_SWO_STREAMING = (1 << 6),
};
/*- Prototypes --------------------------------------------------------------*/
void dap_led(int index, int state);
void dap_connect(bool jtag);
void dap_disconnect(void);
void dap_swj_clock(uint32_t clock);
void dap_transfer_configure(uint8_t idle, uint16_t count, uint16_t retry);
void dap_swd_configure(uint8_t cfg);
int dap_info(int info, uint8_t *data, int size);
void dap_reset_target(void);
void dap_trst_reset(void);
void dap_reset_target_hw(int state);
void dap_reset_pin(int state);
uint32_t dap_read_reg(ADIv5_DP_t *dp, uint8_t reg);
void dap_write_reg(ADIv5_DP_t *dp, uint8_t reg, uint32_t data);
void dap_reset_link(bool jtag);
uint32_t dap_read_idcode(ADIv5_DP_t *dp);
unsigned int dap_read_block(ADIv5_AP_t *ap, void *dest, uint32_t src,
size_t len, enum align align);
unsigned int dap_write_block(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align);
void dap_ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align);
uint32_t dap_ap_read(ADIv5_AP_t *ap, uint16_t addr);
void dap_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
void dap_read_single(ADIv5_AP_t *ap, void *dest, uint32_t src, enum align align);
void dap_write_single(ADIv5_AP_t *ap, uint32_t dest, const void *src,
enum align align);
int dbg_dap_cmd(uint8_t *data, int size, int rsize);
void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS,
const uint8_t *DI, int ticks);
int dap_jtag_configure(void);
#endif // _DAP_H_

View File

@ -191,53 +191,49 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
break; break;
if (index == sizeof(cable_desc)/sizeof(cable_desc[0])) { if (index == sizeof(cable_desc)/sizeof(cable_desc[0])) {
fprintf(stderr, "No cable matching %s found\n", cl_opts->opt_cable); DEBUG_WARN( "No cable matching %s found\n", cl_opts->opt_cable);
return -1; return -1;
} }
active_cable = &cable_desc[index]; active_cable = &cable_desc[index];
printf("\nBlack Magic Probe (" FIRMWARE_VERSION ")\n"); DEBUG_WARN("Black Magic Probe for FTDI/MPSSE\n");
printf("Copyright (C) 2015 Black Sphere Technologies Ltd.\n");
printf("License GPLv3+: GNU GPL version 3 or later "
"<http://gnu.org/licenses/gpl.html>\n\n");
if(ftdic) { if(ftdic) {
ftdi_usb_close(ftdic); ftdi_usb_close(ftdic);
ftdi_free(ftdic); ftdi_free(ftdic);
ftdic = NULL; ftdic = NULL;
} }
if((ftdic = ftdi_new()) == NULL) { if((ftdic = ftdi_new()) == NULL) {
fprintf(stderr, "ftdi_new: %s\n", DEBUG_WARN( "ftdi_new: %s\n",
ftdi_get_error_string(ftdic)); ftdi_get_error_string(ftdic));
abort(); abort();
} }
info->ftdic = ftdic; info->ftdic = ftdic;
if((err = ftdi_set_interface(ftdic, active_cable->interface)) != 0) { if((err = ftdi_set_interface(ftdic, active_cable->interface)) != 0) {
fprintf(stderr, "ftdi_set_interface: %d: %s\n", DEBUG_WARN( "ftdi_set_interface: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
goto error_1; goto error_1;
} }
if((err = ftdi_usb_open_desc( if((err = ftdi_usb_open_desc(
ftdic, active_cable->vendor, active_cable->product, 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", DEBUG_WARN( "unable to open ftdi device: %d (%s)\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
goto error_1; goto error_1;
} }
if((err = ftdi_set_latency_timer(ftdic, 1)) != 0) { if((err = ftdi_set_latency_timer(ftdic, 1)) != 0) {
fprintf(stderr, "ftdi_set_latency_timer: %d: %s\n", DEBUG_WARN( "ftdi_set_latency_timer: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
goto error_2; goto error_2;
} }
if((err = ftdi_set_baudrate(ftdic, 1000000)) != 0) { if((err = ftdi_set_baudrate(ftdic, 1000000)) != 0) {
fprintf(stderr, "ftdi_set_baudrate: %d: %s\n", DEBUG_WARN( "ftdi_set_baudrate: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
goto error_2; goto error_2;
} }
if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) { if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) {
fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n", DEBUG_WARN( "ftdi_write_data_set_chunksize: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
goto error_2; goto error_2;
} }
@ -260,7 +256,7 @@ bool libftdi_srst_get_val(void) { return false; }
void libftdi_buffer_flush(void) void libftdi_buffer_flush(void)
{ {
assert(ftdi_write_data(ftdic, outbuf, bufptr) == bufptr); assert(ftdi_write_data(ftdic, outbuf, bufptr) == bufptr);
// printf("FT2232 libftdi_buffer flush: %d bytes\n", bufptr); DEBUG_WIRE("FT2232 libftdi_buffer flush: %d bytes\n", bufptr);
bufptr = 0; bufptr = 0;
} }

View File

@ -0,0 +1,238 @@
/*
* 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/>.
*/
/* Base on code from git://repo.or.cz/libjaylink.git
* and https://github.com/afaerber/jlink.git*/
#include "general.h"
#include "gdb_if.h"
#include "adiv5.h"
#include "exception.h"
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <ctype.h>
#include <sys/time.h>
#include "cl_utils.h"
#include "jlink.h"
#define USB_PID_SEGGER 0x1366
/* Only two devices PIDS tested so long */
#define USB_VID_SEGGER_0101 0x0101
#define USB_VID_SEGGER_0105 0x0105
static void jlink_print_caps(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_CAPS};
uint8_t res[4];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint32_t caps = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24);
DEBUG_INFO("Caps %" PRIx32 "\n", caps);
if (caps & JLINK_CAP_GET_HW_VERSION) {
uint8_t cmd[1] = {CMD_GET_HW_VERSION};
send_recv(info->usb_link, cmd, 1, NULL, 0);
send_recv(info->usb_link, NULL, 0, res, sizeof(res));
DEBUG_INFO("HW: Type %d, Major %d, Minor %d, Rev %d\n",
res[3], res[2], res[1], res[0]);
}
}
static void jlink_print_speed(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_SPEED};
uint8_t res[6];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint32_t speed = res[0] | (res[1] << 8) | (res[2] << 16) | (res[3] << 24);
double freq_mhz = speed / 1000000.0;
uint16_t divisor = res[4] | (res[5] << 8);
DEBUG_INFO("Emulator speed %3.1f MHz, Mindiv %d\n", freq_mhz, divisor);
}
static void jlink_print_version(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_VERSION};
uint8_t len_str[2];
send_recv(info->usb_link, cmd, 1, len_str, sizeof(len_str));
uint8_t version[0x70];
send_recv(info->usb_link, NULL, 0, version, sizeof(version));
DEBUG_INFO("%s\n", version );
}
static void jlink_print_interfaces(bmp_info_t *info)
{
uint8_t cmd[2] = {CMD_GET_SELECT_IF, JLINK_IF_GET_ACTIVE};
uint8_t res[4];
send_recv(info->usb_link, cmd, 2, res, sizeof(res));
cmd[1] = JLINK_IF_GET_AVAILABLE;
uint8_t res1[4];
send_recv(info->usb_link, cmd, 2, res1, sizeof(res1));
DEBUG_INFO("%s active", (res[0] == SELECT_IF_SWD) ? "SWD":
(res[0] == SELECT_IF_JTAG) ? "JTAG" : "NONE");
uint8_t other_interface = res1[0] - (res[0] + 1);
if (other_interface)
DEBUG_INFO(", %s available\n",
(other_interface == JLINK_IF_SWD) ? "SWD": "JTAG");
else
DEBUG_WARN(", %s not available\n",
((res[0] + 1) == JLINK_IF_SWD) ? "JTAG": "SWD");
}
static void jlink_info(bmp_info_t *info)
{
jlink_print_version(info);
jlink_print_speed(info);
jlink_print_caps(info);
jlink_print_interfaces(info);
}
/* On success endpoints are set and return 0, !0 else */
static int initialize_handle(bmp_info_t *info, libusb_device *dev)
{
struct libusb_config_descriptor *config;
int ret = libusb_get_active_config_descriptor(dev, &config);
if (ret != LIBUSB_SUCCESS) {
DEBUG_WARN( "Failed to get configuration descriptor: %s.",
libusb_error_name(ret));
return -1;
}
const struct libusb_interface *interface;
bool found_interface = false;
const struct libusb_interface_descriptor *desc;
for (int i = 0; i < config->bNumInterfaces; i++) {
interface = &config->interface[i];
desc = &interface->altsetting[0];
if (desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)
continue;
if (desc->bInterfaceSubClass != LIBUSB_CLASS_VENDOR_SPEC)
continue;
if (desc->bNumEndpoints < 2)
continue;
found_interface = true;
if (libusb_claim_interface (
info->usb_link->ul_libusb_device_handle, i)) {
DEBUG_WARN( " Can not claim handle\n");
found_interface = false;
}
break;
}
if (!found_interface) {
DEBUG_WARN( "No suitable interface found.");
libusb_free_config_descriptor(config);
return -1;
}
for (int i = 0; i < desc->bNumEndpoints; i++) {
const struct libusb_endpoint_descriptor *epdesc = &desc->endpoint[i];
if (epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
info->usb_link->ep_rx = epdesc->bEndpointAddress;
} else {
info->usb_link->ep_tx = epdesc->bEndpointAddress;
}
}
libusb_free_config_descriptor(config);
return 0;
}
/* Return 0 if single J-Link device connected or
* serial given matches one of several J-Link devices.
*/
int jlink_init(bmp_info_t *info)
{
usb_link_t *jl = calloc(1, sizeof(usb_link_t));
if (!jl)
return -1;
info->usb_link = jl;
jl->ul_libusb_ctx = info->libusb_ctx;
int ret = -1;
libusb_device **devs;
if (libusb_get_device_list(info->libusb_ctx, &devs) < 0) {
DEBUG_WARN( "libusb_get_device_list() failed");
return ret;
}
int i = 0;
for (; devs[i]; i++) {
libusb_device *dev = devs[i];
struct libusb_device_descriptor desc;
if (libusb_get_device_descriptor(dev, &desc) < 0) {
DEBUG_WARN( "libusb_get_device_descriptor() failed");
goto error;;
}
if (desc.idVendor != USB_PID_SEGGER)
continue;
if ((desc.idProduct != USB_VID_SEGGER_0101) &&
(desc.idProduct != USB_VID_SEGGER_0105))
continue;
int res = libusb_open(dev, &jl->ul_libusb_device_handle);
if (res != LIBUSB_SUCCESS)
continue;
char buf[32];
res = libusb_get_string_descriptor_ascii(jl->ul_libusb_device_handle,
desc.iSerialNumber, (uint8_t*) buf, sizeof(buf));
if ((res <= 0) || (!strstr(buf, info->serial))) {
libusb_close(jl->ul_libusb_device_handle);
continue;
}
break;
}
if (!devs[i])
goto error;
if (initialize_handle(info, devs[i]))
goto error;
jl->req_trans = libusb_alloc_transfer(0);
jl->rep_trans = libusb_alloc_transfer(0);
if (!jl->req_trans || !jl->rep_trans ||
!jl->ep_tx || !jl->ep_rx) {
DEBUG_WARN("Device setup failed\n");
goto error;
}
libusb_free_device_list(devs, 1);
jlink_info(info);
return 0;
error:
libusb_free_device_list(devs, 1);
return -1;
}
const char *jlink_target_voltage(bmp_info_t *info)
{
uint8_t cmd[1] = {CMD_GET_HW_STATUS};
uint8_t res[8];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
uint16_t mVolt = res[0] | (res[1] << 8);
static char ret[7];
sprintf(ret, "%2d.%03d", mVolt / 1000, mVolt % 1000);
return ret;
}
static bool srst_status = false;
void jlink_srst_set_val(bmp_info_t *info, bool assert)
{
uint8_t cmd[1];
cmd[0]= (assert)? CMD_HW_RESET0: CMD_HW_RESET1;
send_recv(info->usb_link, cmd, 1, NULL, 0);
platform_delay(2);
srst_status = assert;
}
bool jlink_srst_get_val(bmp_info_t *info) {
uint8_t cmd[1] = {CMD_GET_HW_STATUS};
uint8_t res[8];
send_recv(info->usb_link, cmd, 1, res, sizeof(res));
return !(res[6]);
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 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/>.
*/
#if !defined(__JLINK_H_)
#define __JLINK_H_
#include "jtagtap.h"
/** @cond PRIVATE */
#define CMD_GET_VERSION 0x01
#define CMD_GET_HW_STATUS 0x07
#define CMD_GET_SPEED 0xc0
#define CMD_GET_SELECT_IF 0xc7
#define CMD_HW_JTAG3 0xcf
#define CMD_HW_RESET0 0xdc
#define CMD_HW_RESET1 0xdd
#define CMD_GET_CAPS 0xe8
#define CMD_GET_EXT_CAPS 0xed
#define CMD_GET_HW_VERSION 0xf0
#define JLINK_IF_GET_ACTIVE 0xfe
#define JLINK_IF_GET_AVAILABLE 0xff
#define JLINK_CAP_GET_HW_VERSION 2
#define JLINK_IF_JTAG 1
#define JLINK_IF_SWD 2
#define SELECT_IF_JTAG 0
#define SELECT_IF_SWD 1
int jlink_init(bmp_info_t *info);
int jlink_swdp_scan(bmp_info_t *info);
int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc);
const char *jlink_target_voltage(bmp_info_t *info);
void jlink_srst_set_val(bmp_info_t *info, bool assert);
bool jlink_srst_get_val(bmp_info_t *info);
#endif

View File

@ -0,0 +1,318 @@
/*
* 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>
* Copyright (C) 2019 - 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/>.
*/
/* This file implements the SW-DP specific functions of the
* ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A.
*/
#include "general.h"
#include "exception.h"
#include "target.h"
#include "target_internal.h"
#include "adiv5.h"
#include "jlink.h"
#include "cl_utils.h"
#define SWDP_ACK_OK 0x01
#define SWDP_ACK_WAIT 0x02
#define SWDP_ACK_FAULT 0x04
static uint32_t jlink_adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr);
static uint32_t jlink_adiv5_swdp_error(ADIv5_DP_t *dp);
static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
static void jlink_adiv5_swdp_abort(ADIv5_DP_t *dp, uint32_t abort);
enum {
SWDIO_WRITE = 0,
SWDIO_READ
};
/* Write at least 50 bits high, two bits low and read DP_IDR and put
* idle cyccles at the end*/
static int line_reset(bmp_info_t *info)
{
uint8_t cmd[44];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
/* write 19 Bytes.*/
cmd[2] = 19 * 8;
cmd[3] = 0;
uint8_t *direction = cmd + 4;
direction[0] = 0;
direction[1] = 0;
direction[2] = 0;
direction[3] = 0;
direction[4] = 0;
direction[5] = 0xff;
direction[6] = 0xff;
direction[7] = 0xff;
direction[8] = 0xff;
direction[9] = 0xff;
direction[10] = 0xff;
direction[11] = 0xff;
direction[12] = 0xff;
direction[13] = 0xff;
direction[14] = 0x0;
direction[15] = 0x0;
direction[16] = 0x0;
direction[17] = 0x0;
direction[18] = 0xe0;
uint8_t *data = direction + 19;
data[5] = 0xff;
data[6] = 0xff;
data[7] = 0xff;
data[8] = 0xff;
data[9] = 0xff;
data[10] = 0xff;
data[11] = 0xff;
data[12] = 0;
data[13] = 0xa5;
data[18] = 0;
uint8_t res[18];
send_recv(info->usb_link, cmd, 42, res, 19);
send_recv(info->usb_link, NULL, 0, res, 1);
if (res[0] != 0) {
DEBUG_WARN( "Line reset failed\n");
return -1;
}
return 0;
}
static int swdptap_init(bmp_info_t *info)
{
uint8_t cmd[2] = {CMD_GET_SELECT_IF, JLINK_IF_GET_AVAILABLE};
uint8_t res[4];
send_recv(info->usb_link, cmd, 2, res, sizeof(res));
if (!(res[0] & JLINK_IF_SWD))
return -1;
cmd[1] = SELECT_IF_SWD;
send_recv(info->usb_link, cmd, 2, res, sizeof(res));
platform_delay(10);
/* Set speed 256 kHz*/
unsigned int speed = 2000;
uint8_t jtag_speed[3] = {5, speed & 0xff, speed >> 8};
send_recv(info->usb_link, jtag_speed, 3, NULL, 0);
return 0;
}
int jlink_swdp_scan(bmp_info_t *info)
{
swdptap_init(info);
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dp) /* calloc failed: heap exhaustion */
return 0;
uint8_t cmd[44];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
/* write 18 Bytes.*/
cmd[2] = 17 * 8;
cmd[3] = 0;
uint8_t *direction = cmd + 4;
direction[0] = 0xff;
direction[1] = 0xff;
direction[2] = 0xff;
direction[3] = 0xff;
direction[4] = 0xff;
direction[5] = 0xff;
direction[6] = 0xff;
direction[7] = 0xff;
direction[8] = 0xff;
direction[9] = 0xff;
direction[10] = 0xff;
direction[11] = 0xff;
direction[12] = 0xff;
direction[13] = 0xff;
direction[14] = 0xff;
direction[15] = 0xff;
direction[16] = 0xff;
uint8_t *data = direction + 17;
data[0] = 0xff;
data[1] = 0xff;
data[2] = 0xff;
data[3] = 0xff;
data[4] = 0xff;
data[5] = 0xff;
data[6] = 0xff;
data[7] = 0x9e;
data[8] = 0xe7;
data[9] = 0xff;
data[10] = 0xff;
data[11] = 0xff;
data[12] = 0xff;
data[13] = 0xff;
data[14] = 0xff;
data[15] = 0;
data[16] = 0;
uint8_t res[18];
send_recv(info->usb_link, cmd, 38, res, 17);
send_recv(info->usb_link, NULL, 0, res, 1);
if (res[0] != 0) {
DEBUG_WARN( "Line reset failed\n");
return 0;
}
dp->idcode = jlink_adiv5_swdp_low_access(dp, 1, ADIV5_DP_IDCODE, 0);
dp->dp_read = jlink_adiv5_swdp_read;
dp->error = jlink_adiv5_swdp_error;
dp->low_access = jlink_adiv5_swdp_low_access;
dp->abort = jlink_adiv5_swdp_abort;
jlink_adiv5_swdp_error(dp);
adiv5_dp_init(dp);
return target_list?1:0;
}
static uint32_t jlink_adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr)
{
if (addr & ADIV5_APnDP) {
adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
return adiv5_dp_low_access(dp, ADIV5_LOW_READ,
ADIV5_DP_RDBUFF, 0);
} else {
return jlink_adiv5_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0);
}
}
static uint32_t jlink_adiv5_swdp_error(ADIv5_DP_t *dp)
{
uint32_t err, clr = 0;
err = jlink_adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) &
(ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP |
ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR);
if(err & ADIV5_DP_CTRLSTAT_STICKYORUN)
clr |= ADIV5_DP_ABORT_ORUNERRCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYCMP)
clr |= ADIV5_DP_ABORT_STKCMPCLR;
if(err & ADIV5_DP_CTRLSTAT_STICKYERR)
clr |= ADIV5_DP_ABORT_STKERRCLR;
if(err & ADIV5_DP_CTRLSTAT_WDATAERR)
clr |= ADIV5_DP_ABORT_WDERRCLR;
if (clr)
adiv5_dp_write(dp, ADIV5_DP_ABORT, clr);
if (dp->fault)
err |= 0x8000;
dp->fault = 0;
return err;
}
static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value)
{
bool APnDP = addr & ADIV5_APnDP;
uint8_t addr8 = addr & 0xff;
uint8_t request = 0x81;
uint32_t response = 0;
uint8_t ack;
platform_timeout timeout;
if(APnDP && dp->fault) return 0;
if(APnDP) request ^= 0x22;
if(RnW) request ^= 0x24;
addr8 &= 0xC;
request |= (addr8 << 1) & 0x18;
if((addr8 == 4) || (addr8 == 8))
request ^= 0x20;
uint8_t cmd[16];
uint8_t res[8];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = 13;
cmd[3] = 0;
cmd[4] = 0xff;
cmd[5] = 0xe3;
cmd[6] = request << 2;
cmd[7] = request >> 6;
platform_timeout_set(&timeout, 2000);
do {
send_recv(info.usb_link, cmd, 8, res, 2);
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "Low access setup failed");
ack = res[1] >> 2;
ack &= 7;
} while (ack == SWDP_ACK_WAIT && !platform_timeout_is_expired(&timeout));
if (ack == SWDP_ACK_WAIT)
raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout");
if(ack == SWDP_ACK_FAULT) {
if (cl_debuglevel & BMP_DEBUG_TARGET)
DEBUG_WARN( "Fault\n");
dp->fault = 1;
return 0;
}
if(ack != SWDP_ACK_OK) {
if (cl_debuglevel & BMP_DEBUG_TARGET)
DEBUG_WARN( "Protocol\n");
line_reset(&info);
return 0;
}
cmd[3] = 0;
/* Always prepend an idle cycle (SWDIO = 0)!*/
if(RnW) {
memset(cmd + 4, 0, 10);
cmd[2] = 34;
cmd[8] = 0xfe;
cmd[13] = 0;
send_recv(info.usb_link, cmd, 14, res, 5);
send_recv(info.usb_link, NULL, 0, res + 5, 1);
if (res[5] != 0)
raise_exception(EXCEPTION_ERROR, "Low access read failed");
response = res[0] | res[1] << 8 | res[2] << 16 | res[3] << 24;
int parity = res[4] & 1;
int bit_count = __builtin_popcount (response) + parity;
if (bit_count & 1) /* Give up on parity error */
raise_exception(EXCEPTION_ERROR, "SWDP Parity error");
} else {
cmd[2] = 35;
memset(cmd + 4, 0xff, 5);
cmd[ 9] = ((value << 2) & 0xfc);
cmd[10] = ((value >> 6) & 0xff);
cmd[11] = ((value >> 14) & 0xff);
cmd[12] = ((value >> 22) & 0xff);
cmd[13] = ((value >> 30) & 0x03);
int bit_count = __builtin_popcount(value);
cmd[13] |= ((bit_count & 1) ? 4 : 0);
send_recv(info.usb_link, cmd, 14, res, 5);
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "Low access write failed");
}
return response;
}
static void jlink_adiv5_swdp_abort(ADIv5_DP_t *dp, uint32_t abort)
{
adiv5_dp_write(dp, ADIV5_DP_ABORT, abort);
}

View File

@ -0,0 +1,185 @@
/*
* 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/>.
*/
/* Low level JTAG implementation using jlink.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include "exception.h"
#include "jlink.h"
#include "cl_utils.h"
static void jtagtap_reset(void)
{
jtagtap_soft_reset();
}
static void jtagtap_tms_seq(uint32_t MS, int ticks)
{
DEBUG_PROBE("jtagtap_tms_seq 0x%08" PRIx32 ", ticks %d\n", MS, ticks);
int len = (ticks + 7) / 8;
uint8_t cmd[12];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = ticks;
cmd[3] = 0;
uint8_t *tms = cmd + 4;
for (int i = 0; i < len; i++) {
*tms = MS & 0xff;
*(tms + len) = *tms;
tms++;
MS >>= 8;
}
uint8_t res[4];
send_recv(info.usb_link, cmd, 4 + 2 * len, res, len);
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "tagtap_tms_seq failed");
}
static void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms,
const uint8_t *DI, int ticks)
{
if (!ticks)
return;
int len = (ticks + 7) / 8;
if (cl_debuglevel & BMP_DEBUG_PROBE) {
DEBUG_PROBE("jtagtap_tdi_tdo %s, ticks %d, DI: ",
(final_tms) ? "Final TMS" : "", ticks);
for (int i = 0; i < len; i++) {
DEBUG_PROBE("%02x", DI[i]);
}
DEBUG_PROBE("\n");
}
uint8_t *cmd = alloca(4 + 2 * len);
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = ticks;
cmd[3] = 0;
uint8_t *tms = cmd + 4;
for (int i = 0; i < len; i++)
*tms++ = 0;
if (final_tms)
cmd[4 + (ticks - 1) / 8] |= (1 << ((ticks - 1) % 8));
uint8_t *tdi = tms;
if (DI)
for (int i = 0; i < len; i++)
*tdi++ = DI[i];
if (DO)
send_recv(info.usb_link, cmd, 4 + 2 * len, DO, len);
else
send_recv(info.usb_link, cmd, 4 + 2 * len, cmd, len);
uint8_t res[1];
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "jtagtap_tdi_tdi failed");
}
static void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI,
int ticks)
{
if (cl_debuglevel & BMP_DEBUG_PROBE) {
DEBUG_PROBE("jtagtap_tdi_seq %s:", (final_tms)? "final_tms" : "");
const uint8_t *p = DI;
unsigned int i = (ticks & 7) & ~7 ;
if (i > 16)
i = 16;
while (i--)
DEBUG_PROBE(" %02x", *p++);
if (ticks > (16 * 8))
DEBUG_PROBE(" ...");
DEBUG_PROBE("\n");
}
return jtagtap_tdi_tdo_seq(NULL, final_tms, DI, ticks);
}
static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
{
DEBUG_PROBE("jtagtap_next TMS 0x%02x, TDI %02x\n", dTMS, dTDI);
uint8_t cmd[6];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
cmd[2] = 1;
cmd[3] = 0;
cmd[4] = (dTMS) ? 0xff : 0;
cmd[5] = (dTDI) ? 0xff : 0;
uint8_t ret[1];
send_recv(info.usb_link, cmd, 6, ret, 1);
uint8_t res[1];
send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "jtagtap_next failed");
return (ret[0] & 1);
}
int jlink_jtagtap_init(bmp_info_t *info, jtag_proc_t *jtag_proc)
{
DEBUG_PROBE("jtap_init\n");
uint8_t cmd_switch[2] = {CMD_GET_SELECT_IF, JLINK_IF_GET_AVAILABLE};
uint8_t res[4];
send_recv(info->usb_link, cmd_switch, 2, res, sizeof(res));
if (!(res[0] & JLINK_IF_JTAG)) {
DEBUG_WARN("JTAG not available\n");
return -1;
}
cmd_switch[1] = SELECT_IF_JTAG;
send_recv(info->usb_link, cmd_switch, 2, res, sizeof(res));
platform_delay(10);
/* Set speed 256 kHz*/
unsigned int speed = 2000;
uint8_t jtag_speed[3] = {5, speed & 0xff, speed >> 8};
send_recv(info->usb_link, jtag_speed, 3, NULL, 0);
uint8_t cmd[44];
cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0;
/* write 8 Bytes.*/
cmd[2] = 9 * 8;
cmd[3] = 0;
uint8_t *tms = cmd + 4;
tms[0] = 0xff;
tms[1] = 0xff;
tms[2] = 0xff;
tms[3] = 0xff;
tms[4] = 0xff;
tms[5] = 0xff;
tms[6] = 0xff;
tms[7] = 0x3c;
tms[8] = 0xe7;
send_recv(info->usb_link, cmd, 4 + 2 * 9, cmd, 9);
send_recv(info->usb_link, NULL, 0, res, 1);
if (res[0] != 0) {
DEBUG_WARN("Switch to JTAG failed\n");
return 0;
}
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;
}

View File

@ -49,21 +49,21 @@ int libftdi_jtagtap_init(jtag_proc_t *jtag_proc)
assert(ftdic != NULL); assert(ftdic != NULL);
int err = ftdi_usb_purge_buffers(ftdic); int err = ftdi_usb_purge_buffers(ftdic);
if (err != 0) { if (err != 0) {
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n", DEBUG_WARN("ftdi_usb_purge_buffer: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
abort(); abort();
} }
/* Reset MPSSE controller. */ /* Reset MPSSE controller. */
err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET); err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET);
if (err != 0) { if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", DEBUG_WARN("ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
return -1; return -1;
} }
/* Enable MPSSE controller. Pin directions are set later.*/ /* Enable MPSSE controller. Pin directions are set later.*/
err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE); err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE);
if (err != 0) { if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", DEBUG_WARN("ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
return -1; return -1;
} }
@ -111,7 +111,7 @@ static void jtagtap_tdi_tdo_seq(
if(!ticks) return; if(!ticks) return;
if (!DI && !DO) return; if (!DI && !DO) return;
// printf("ticks: %d\n", ticks); // DEBUG_PROBE("ticks: %d\n", ticks);
if(final_tms) ticks--; if(final_tms) ticks--;
rticks = ticks & 7; rticks = ticks & 7;
ticks >>= 3; ticks >>= 3;
@ -153,7 +153,7 @@ static void jtagtap_tdi_tdo_seq(
if(final_tms) rsize--; if(final_tms) rsize--;
while(rsize--) { while(rsize--) {
/*if(rsize) printf("%02X ", tmp[index]);*/ if(rsize) DEBUG_WIRE("%02X ", tmp[index]);
*DO++ = tmp[index++]; *DO++ = tmp[index++];
} }
if (rticks == 0) if (rticks == 0)
@ -166,7 +166,7 @@ static void jtagtap_tdi_tdo_seq(
if(rticks) { if(rticks) {
*DO >>= (8-rticks); *DO >>= (8-rticks);
} }
/*printf("%02X\n", *DO);*/ DEBUG_WIRE("%02X\n", *DO);
} }
} }

View File

@ -43,26 +43,26 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks);
int libftdi_swdptap_init(swd_proc_t *swd_proc) int libftdi_swdptap_init(swd_proc_t *swd_proc)
{ {
if (!active_cable->bitbang_tms_in_pin) { if (!active_cable->bitbang_tms_in_pin) {
DEBUG("SWD not possible or missing item in cable description.\n"); DEBUG_WARN("SWD not possible or missing item in cable description.\n");
return -1; return -1;
} }
int err = ftdi_usb_purge_buffers(ftdic); int err = ftdi_usb_purge_buffers(ftdic);
if (err != 0) { if (err != 0) {
fprintf(stderr, "ftdi_usb_purge_buffer: %d: %s\n", DEBUG_WARN("ftdi_usb_purge_buffer: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
return -1; return -1;
} }
/* Reset MPSSE controller. */ /* Reset MPSSE controller. */
err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET); err = ftdi_set_bitmode(ftdic, 0, BITMODE_RESET);
if (err != 0) { if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", DEBUG_WARN("ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
return -1; return -1;
} }
/* Enable MPSSE controller. Pin directions are set later.*/ /* Enable MPSSE controller. Pin directions are set later.*/
err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE); err = ftdi_set_bitmode(ftdic, 0, BITMODE_MPSSE);
if (err != 0) { if (err != 0) {
fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", DEBUG_WARN("ftdi_set_bitmode: %d: %s\n",
err, ftdi_get_error_string(ftdic)); err, ftdi_get_error_string(ftdic));
return -1; return -1;
} }

View File

@ -1,8 +1,7 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2020 * Copyright (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* Written by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -35,6 +34,8 @@
#include "bmp_remote.h" #include "bmp_remote.h"
#include "stlinkv2.h" #include "stlinkv2.h"
#include "ftdi_bmp.h" #include "ftdi_bmp.h"
#include "jlink.h"
#include "cmsis_dap.h"
#define VENDOR_ID_BMP 0x1d50 #define VENDOR_ID_BMP 0x1d50
#define PRODUCT_ID_BMP 0x6018 #define PRODUCT_ID_BMP 0x6018
@ -49,6 +50,8 @@
#define PRODUCT_ID_STLINKV3 0x374f #define PRODUCT_ID_STLINKV3 0x374f
#define PRODUCT_ID_STLINKV3E 0x374e #define PRODUCT_ID_STLINKV3E 0x374e
#define VENDOR_ID_SEGGER 0x1366
bmp_info_t info; bmp_info_t info;
swd_proc_t swd_proc; swd_proc_t swd_proc;
@ -66,6 +69,9 @@ static void exit_function(void)
} }
} }
switch (info.bmp_type) { switch (info.bmp_type) {
case BMP_TYPE_CMSIS_DAP:
dap_exit_function();
break;
default: default:
break; break;
} }
@ -84,7 +90,7 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
libusb_device **devs; libusb_device **devs;
int n_devs = libusb_get_device_list(info->libusb_ctx, &devs); int n_devs = libusb_get_device_list(info->libusb_ctx, &devs);
if (n_devs < 0) { if (n_devs < 0) {
fprintf(stderr, "WARN:libusb_get_device_list() failed"); DEBUG_WARN( "WARN:libusb_get_device_list() failed");
return -1; return -1;
} }
bool report = false; bool report = false;
@ -94,13 +100,14 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
char manufacturer[128]; char manufacturer[128];
char product[128]; char product[128];
bmp_type_t type = BMP_TYPE_NONE; bmp_type_t type = BMP_TYPE_NONE;
bool access_problems = false;
rescan: rescan:
found_debuggers = 0; found_debuggers = 0;
for (int i = 0; devs[i]; i++) { for (int i = 0; devs[i]; i++) {
libusb_device *dev = devs[i]; libusb_device *dev = devs[i];
int res = libusb_get_device_descriptor(dev, &desc); int res = libusb_get_device_descriptor(dev, &desc);
if (res < 0) { if (res < 0) {
fprintf(stderr, "WARN: libusb_get_device_descriptor() failed: %s", DEBUG_WARN( "WARN: libusb_get_device_descriptor() failed: %s",
libusb_strerror(res)); libusb_strerror(res));
libusb_free_device_list(devs, 1); libusb_free_device_list(devs, 1);
continue; continue;
@ -108,7 +115,11 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
libusb_device_handle *handle; libusb_device_handle *handle;
res = libusb_open(dev, &handle); res = libusb_open(dev, &handle);
if (res != LIBUSB_SUCCESS) { if (res != LIBUSB_SUCCESS) {
fprintf(stderr,"WARN: Open failed\n"); if (!access_problems) {
DEBUG_INFO("INFO: Open USB %04x:%04x failed\n",
desc.idVendor, desc.idProduct);
access_problems = true;
}
continue; continue;
} }
res = libusb_get_string_descriptor_ascii( res = libusb_get_string_descriptor_ascii(
@ -131,7 +142,7 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
handle, desc.iProduct, (uint8_t*)product, handle, desc.iProduct, (uint8_t*)product,
sizeof(product)); sizeof(product));
if (res <= 0) { if (res <= 0) {
fprintf(stderr, "WARN:" DEBUG_WARN( "WARN:"
"libusb_get_string_descriptor_ascii " "libusb_get_string_descriptor_ascii "
"for ident_string failed: %s\n", "for ident_string failed: %s\n",
libusb_strerror(res)); libusb_strerror(res));
@ -163,15 +174,19 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
type = BMP_TYPE_STLINKV2; type = BMP_TYPE_STLINKV2;
} else { } else {
if (desc.idProduct == PRODUCT_ID_STLINKV1) if (desc.idProduct == PRODUCT_ID_STLINKV1)
fprintf(stderr, "INFO: STLINKV1 not supported\n"); DEBUG_WARN( "INFO: STLINKV1 not supported\n");
continue; continue;
} }
} else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) {
type = BMP_TYPE_CMSIS_DAP;
} else if (desc.idVendor == VENDOR_ID_SEGGER) {
type = BMP_TYPE_JLINK;
} else{ } else{
continue; continue;
} }
found_debuggers ++; found_debuggers ++;
if (report) { if (report) {
printf("%2d: %s, %s, %s\n", found_debuggers, DEBUG_WARN("%2d: %s, %s, %s\n", found_debuggers,
serial, serial,
manufacturer,product); manufacturer,product);
} }
@ -187,15 +202,23 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
break; break;
} }
} }
if (found_debuggers > 1) { if ((found_debuggers > 1) ||
((found_debuggers == 1) && (cl_opts->opt_list_only))) {
if (!report) { if (!report) {
printf("%d debuggers found! Select with -P <num>, -s <string> " if (found_debuggers > 1)
"and/or -S <string>\n", DEBUG_WARN("%d debuggers found!\nSelect with -P <pos>, "
"-s <(partial)serial no.> "
"and/or -S <(partial)description>\n",
found_debuggers); found_debuggers);
report = true; report = true;
goto rescan; goto rescan;
} else {
found_debuggers = 0;
} }
} }
if (!found_debuggers && access_problems)
DEBUG_WARN(
"No debugger found. Please check access rights to USB devices!\n");
libusb_free_device_list(devs, 1); libusb_free_device_list(devs, 1);
return (found_debuggers == 1) ? 0 : -1; return (found_debuggers == 1) ? 0 : -1;
} }
@ -210,7 +233,7 @@ void platform_init(int argc, char **argv)
signal(SIGINT, sigterm_handler); signal(SIGINT, sigterm_handler);
int res = libusb_init(&info.libusb_ctx); int res = libusb_init(&info.libusb_ctx);
if (res) { if (res) {
fprintf(stderr, "Fatal: Failed to get USB context: %s\n", DEBUG_WARN( "Fatal: Failed to get USB context: %s\n",
libusb_strerror(res)); libusb_strerror(res));
exit(-1); exit(-1);
} }
@ -226,21 +249,29 @@ void platform_init(int argc, char **argv)
} else if (find_debuggers(&cl_opts, &info)) { } else if (find_debuggers(&cl_opts, &info)) {
exit(-1); exit(-1);
} }
printf("Using %s %s %s\n", info.serial, DEBUG_WARN("Using %04x:%04x %s %s %s\n", info.vid, info.pid, info.serial,
info.manufacturer, info.manufacturer,
info.product); info.product);
switch (info.bmp_type) { switch (info.bmp_type) {
case BMP_TYPE_BMP: case BMP_TYPE_BMP:
if (serial_open(&cl_opts, info.serial)) if (serial_open(&cl_opts, info.serial))
exit(-1); exit(-1);
remote_init(); remote_init(true);
break; break;
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
if (stlink_init( &info)) if (stlink_init( &info))
exit(-1); exit(-1);
break; break;
case BMP_TYPE_CMSIS_DAP:
if (dap_init( &info))
exit(-1);
break;
case BMP_TYPE_LIBFTDI: case BMP_TYPE_LIBFTDI:
break; break;
case BMP_TYPE_JLINK:
if (jlink_init(&info))
exit(-1);
break;
default: default:
exit(-1); exit(-1);
} }
@ -273,6 +304,20 @@ int platform_adiv5_swdp_scan(void)
free(dp); free(dp);
break; break;
} }
case BMP_TYPE_CMSIS_DAP:
{
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dap_enter_debug_swd(dp)) {
adiv5_dp_init(dp);
if (target_list)
return 1;
}
free(dp);
break;
}
case BMP_TYPE_JLINK:
return jlink_swdp_scan(&info);
default: default:
return 0; return 0;
} }
@ -285,8 +330,9 @@ int platform_swdptap_init(void)
case BMP_TYPE_BMP: case BMP_TYPE_BMP:
return remote_swdptap_init(&swd_proc); return remote_swdptap_init(&swd_proc);
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
case BMP_TYPE_CMSIS_DAP:
case BMP_TYPE_JLINK:
return 0; return 0;
break;
case BMP_TYPE_LIBFTDI: case BMP_TYPE_LIBFTDI:
return libftdi_swdptap_init(&swd_proc); return libftdi_swdptap_init(&swd_proc);
default: default:
@ -300,6 +346,8 @@ int platform_jtag_scan(const uint8_t *lrlens)
switch (info.bmp_type) { switch (info.bmp_type) {
case BMP_TYPE_BMP: case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI: case BMP_TYPE_LIBFTDI:
case BMP_TYPE_JLINK:
case BMP_TYPE_CMSIS_DAP:
return jtag_scan(lrlens); return jtag_scan(lrlens);
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
return jtag_scan_stlinkv2(&info, lrlens); return jtag_scan_stlinkv2(&info, lrlens);
@ -318,6 +366,10 @@ int platform_jtagtap_init(void)
return 0; return 0;
case BMP_TYPE_LIBFTDI: case BMP_TYPE_LIBFTDI:
return libftdi_jtagtap_init(&jtag_proc); return libftdi_jtagtap_init(&jtag_proc);
case BMP_TYPE_JLINK:
return jlink_jtagtap_init(&info, &jtag_proc);
case BMP_TYPE_CMSIS_DAP:
return cmsis_dap_jtagtap_init(&jtag_proc);
default: default:
return -1; return -1;
} }
@ -327,8 +379,12 @@ int platform_jtagtap_init(void)
void platform_adiv5_dp_defaults(ADIv5_DP_t *dp) void platform_adiv5_dp_defaults(ADIv5_DP_t *dp)
{ {
switch (info.bmp_type) { switch (info.bmp_type) {
case BMP_TYPE_BMP:
return remote_adiv5_dp_defaults(dp);
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
return stlink_adiv5_dp_defaults(dp); return stlink_adiv5_dp_defaults(dp);
case BMP_TYPE_CMSIS_DAP:
return dap_adiv5_dp_defaults(dp);
default: default:
break; break;
} }
@ -339,9 +395,12 @@ int platform_jtag_dp_init(ADIv5_DP_t *dp)
switch (info.bmp_type) { switch (info.bmp_type) {
case BMP_TYPE_BMP: case BMP_TYPE_BMP:
case BMP_TYPE_LIBFTDI: case BMP_TYPE_LIBFTDI:
case BMP_TYPE_JLINK:
return 0; return 0;
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
return stlink_jtag_dp_init(dp); return stlink_jtag_dp_init(dp);
case BMP_TYPE_CMSIS_DAP:
return dap_jtag_dp_init(dp);
default: default:
return 0; return 0;
} }
@ -376,6 +435,8 @@ const char *platform_target_voltage(void)
return stlink_target_voltage(&info); return stlink_target_voltage(&info);
case BMP_TYPE_LIBFTDI: case BMP_TYPE_LIBFTDI:
return libftdi_target_voltage(); return libftdi_target_voltage();
case BMP_TYPE_JLINK:
return jlink_target_voltage(&info);
default: default:
break; break;
} }
@ -389,6 +450,8 @@ void platform_srst_set_val(bool assert)
return stlink_srst_set_val(&info, assert); return stlink_srst_set_val(&info, assert);
case BMP_TYPE_BMP: case BMP_TYPE_BMP:
return remote_srst_set_val(assert); return remote_srst_set_val(assert);
case BMP_TYPE_JLINK:
return jlink_srst_set_val(&info, assert);
default: default:
break; break;
} }
@ -401,6 +464,8 @@ bool platform_srst_get_val(void)
return remote_srst_get_val(); return remote_srst_get_val();
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
return stlink_srst_get_val(); return stlink_srst_get_val();
case BMP_TYPE_JLINK:
return jlink_srst_get_val(&info);
default: default:
break; break;
} }
@ -416,3 +481,138 @@ void platform_buffer_flush(void)
break; break;
} }
} }
static void ap_decode_access(uint16_t addr, uint8_t RnW)
{
if (RnW)
fprintf(stderr, "Read ");
else
fprintf(stderr, "Write ");
switch(addr) {
case 0x00:
if (RnW)
fprintf(stderr, "DP_DPIDR :");
else
fprintf(stderr, "DP_ABORT :");
break;
case 0x004: fprintf(stderr, "CTRL/STAT:");
break;
case 0x008:
if (RnW)
fprintf(stderr, "RESEND :");
else
fprintf(stderr, "DP_SELECT:");
break;
case 0x00c: fprintf(stderr, "DP_RDBUFF:");
break;
case 0x100: fprintf(stderr, "AP_CSW :");
break;
case 0x104: fprintf(stderr, "AP_TAR :");
break;
case 0x10c: fprintf(stderr, "AP_DRW :");
break;
case 0x1f8: fprintf(stderr, "AP_BASE :");
break;
case 0x1fc: fprintf(stderr, "AP_IDR :");
break;
}
}
void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
{
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_WRITE);
fprintf(stderr, " 0x%08" PRIx32 "\n", value);
}
dp->low_access(dp, ADIV5_LOW_WRITE, addr, value);
}
uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr)
{
uint32_t ret = dp->dp_read(dp, addr);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_READ);
fprintf(stderr, " 0x%08" PRIx32 "\n", ret);
}
return ret;
}
uint32_t adiv5_dp_error(ADIv5_DP_t *dp)
{
uint32_t ret = dp->error(dp);
DEBUG_TARGET( "DP Error 0x%08" PRIx32 "\n", ret);
return ret;
}
uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
uint16_t addr, uint32_t value)
{
uint32_t ret = dp->low_access(dp, RnW, addr, value);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, RnW);
fprintf(stderr, " 0x%08" PRIx32 "\n", (RnW)? ret : value);
}
return ret;
}
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{
uint32_t ret = ap->dp->ap_read(ap, addr);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_READ);
fprintf(stderr, " 0x%08" PRIx32 "\n", ret);
}
return ret;
}
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{
if (cl_debuglevel & BMP_DEBUG_TARGET) {
ap_decode_access(addr, ADIV5_LOW_WRITE);
fprintf(stderr, " 0x%08" PRIx32 "\n", value);
}
return ap->dp->ap_write(ap, addr, value);
}
void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{
ap->dp->mem_read(ap, dest, src, len);
if (cl_debuglevel & BMP_DEBUG_TARGET) {
fprintf(stderr, "ap_memread @ %" PRIx32 " len %" PRIx32 ":",
src, (uint32_t)len);
uint8_t *p = (uint8_t *) dest;
unsigned int i = len;
if (i > 16)
i = 16;
while (i--)
fprintf(stderr, " %02x", *p++);
if (len > 16)
fprintf(stderr, " ...");
fprintf(stderr, "\n");
}
return;
}
void adiv5_mem_write_sized( ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align)
{
if (cl_debuglevel & BMP_DEBUG_TARGET) {
fprintf(stderr, "ap_mem_write_sized @ %" PRIx32 " len %" PRIx32
", align %d:", dest, (uint32_t)len, 1 << align);
uint8_t *p = (uint8_t *) src;
unsigned int i = len;
if (i > 16)
i = 16;
while (i--)
fprintf(stderr, " %02x", *p++);
if (len > 16)
fprintf(stderr, " ...");
fprintf(stderr, "\n");
}
return ap->dp->mem_write_sized(ap, dest, src, len, align);
}
void adiv5_dp_abort(struct ADIv5_DP_s *dp, uint32_t abort)
{
DEBUG_TARGET("Abort: %08" PRIx32 "\n", abort);
return dp->abort(dp, abort);
}

View File

@ -4,6 +4,7 @@
* Copyright (C) 2008 Black Sphere Technologies Ltd. * Copyright (C) 2008 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz> * Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net> * Modified by Dave Marples <dave@marples.net>
* Modified (c) 2020 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -55,7 +56,7 @@ int remote_jtagtap_init(jtag_proc_t *jtag_proc)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_init failed, error %s\n", DEBUG_WARN("jtagtap_init failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -82,7 +83,7 @@ static void jtagtap_reset(void)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_reset failed, error %s\n", DEBUG_WARN("jtagtap_reset failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -99,7 +100,7 @@ static void jtagtap_tms_seq(uint32_t MS, int ticks)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_tms_seq failed, error %s\n", DEBUG_WARN("jtagtap_tms_seq failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -126,7 +127,7 @@ static void jtagtap_tdi_tdo_seq(
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_tms_seq failed, error %s\n", DEBUG_WARN("jtagtap_tms_seq failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -156,7 +157,7 @@ static uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "jtagtap_next failed, error %s\n", DEBUG_WARN("jtagtap_next failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }

View File

@ -1,9 +1,9 @@
/* /*
* This file is part of the Black Magic Debug project. * 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> * Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Modified by Dave Marples <dave@marples.net> * Modified by Dave Marples <dave@marples.net>
* Modification (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -37,15 +37,15 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks);
int remote_swdptap_init(swd_proc_t *swd_proc) int remote_swdptap_init(swd_proc_t *swd_proc)
{ {
DEBUG_WIRE("remote_swdptap_init\n");
uint8_t construct[REMOTE_MAX_MSG_SIZE]; uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s; int s;
s = sprintf((char *)construct,"%s", REMOTE_SWDP_INIT_STR); s = sprintf((char *)construct,"%s", REMOTE_SWDP_INIT_STR);
platform_buffer_write(construct, s); platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { if ((!s) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_init failed, error %s\n", DEBUG_WARN("swdptap_init failed, error %s\n",
s ? (char *)&(construct[1]) : "unknown"); s ? (char *)&(construct[1]) : "unknown");
exit(-1); exit(-1);
} }
@ -68,12 +68,14 @@ static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) { if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_seq_in_parity failed, error %s\n", DEBUG_WARN("swdptap_seq_in_parity failed, error %s\n",
s ? (char *)&(construct[1]) : "short response"); s ? (char *)&(construct[1]) : "short response");
exit(-1); exit(-1);
} }
*res=remotehston(-1, (char *)&construct[1]); *res=remotehston(-1, (char *)&construct[1]);
DEBUG_PROBE("swdptap_seq_in_parity %2d ticks: %08" PRIx32 " %s\n",
ticks, *res, (construct[0] != REMOTE_RESP_OK) ? "ERR" : "OK");
return (construct[0] != REMOTE_RESP_OK); return (construct[0] != REMOTE_RESP_OK);
} }
@ -87,12 +89,14 @@ static uint32_t swdptap_seq_in(int ticks)
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) { if ((s<2) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_seq_in failed, error %s\n", DEBUG_WARN("swdptap_seq_in failed, error %s\n",
s ? (char *)&(construct[1]) : "short response"); s ? (char *)&(construct[1]) : "short response");
exit(-1); exit(-1);
} }
uint32_t res = remotehston(-1,(char *)&construct[1]);
return remotehston(-1,(char *)&construct[1]); DEBUG_PROBE("swdptap_seq_in %2d ticks: %08" PRIx32 "\n",
ticks, res);
return res;
} }
static void swdptap_seq_out(uint32_t MS, int ticks) static void swdptap_seq_out(uint32_t MS, int ticks)
@ -100,12 +104,14 @@ static void swdptap_seq_out(uint32_t MS, int ticks)
uint8_t construct[REMOTE_MAX_MSG_SIZE]; uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s; int s;
DEBUG_PROBE("swdptap_seq_out %2d ticks: %08" PRIx32 "\n",
ticks, MS);
s = sprintf((char *)construct,REMOTE_SWDP_OUT_STR, ticks, MS); s = sprintf((char *)construct,REMOTE_SWDP_OUT_STR, ticks, MS);
platform_buffer_write(construct, s); platform_buffer_write(construct, s);
s=platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s=platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) { if ((s < 1) || (construct[0] == REMOTE_RESP_ERR)) {
fprintf(stderr, "swdptap_seq_out failed, error %s\n", DEBUG_WARN("swdptap_seq_out failed, error %s\n",
s ? (char *)&(construct[1]) : "short response"); s ? (char *)&(construct[1]) : "short response");
exit(-1); exit(-1);
} }
@ -116,12 +122,14 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks)
uint8_t construct[REMOTE_MAX_MSG_SIZE]; uint8_t construct[REMOTE_MAX_MSG_SIZE];
int s; int s;
DEBUG_PROBE("swdptap_seq_out_parity %2d ticks: %08" PRIx32 "\n",
ticks, MS);
s = sprintf((char *)construct, REMOTE_SWDP_OUT_PAR_STR, ticks, MS); s = sprintf((char *)construct, REMOTE_SWDP_OUT_PAR_STR, ticks, MS);
platform_buffer_write(construct, s); platform_buffer_write(construct, s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
if ((s < 1) || (construct[1] == REMOTE_RESP_ERR)){ if ((s < 1) || (construct[1] == REMOTE_RESP_ERR)){
fprintf(stderr, "swdptap_seq_out_parity failed, error %s\n", DEBUG_WARN("swdptap_seq_out_parity failed, error %s\n",
s ? (char *)&(construct[2]) : "short response"); s ? (char *)&(construct[2]) : "short response");
exit(-1); exit(-1);
} }

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2019 Uwe Bonnes * Copyright (C) 2019-2020 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -232,43 +232,46 @@ static int stlink_usb_error_check(uint8_t *data, bool verbose)
return STLINK_ERROR_OK; return STLINK_ERROR_OK;
case STLINK_DEBUG_ERR_FAULT: case STLINK_DEBUG_ERR_FAULT:
if (verbose) if (verbose)
DEBUG("SWD fault response (0x%x)\n", STLINK_DEBUG_ERR_FAULT); DEBUG_WARN("SWD fault response (0x%x)\n",
STLINK_DEBUG_ERR_FAULT);
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_JTAG_UNKNOWN_JTAG_CHAIN: case STLINK_JTAG_UNKNOWN_JTAG_CHAIN:
if (verbose) if (verbose)
DEBUG("Unknown JTAG chain\n"); DEBUG_WARN("Unknown JTAG chain\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_NO_DEVICE_CONNECTED: case STLINK_NO_DEVICE_CONNECTED:
if (verbose) if (verbose)
DEBUG("No device connected\n"); DEBUG_WARN("No device connected\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_JTAG_COMMAND_ERROR: case STLINK_JTAG_COMMAND_ERROR:
if (verbose) if (verbose)
DEBUG("Command error\n"); DEBUG_WARN("Command error\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_JTAG_GET_IDCODE_ERROR: case STLINK_JTAG_GET_IDCODE_ERROR:
if (verbose) if (verbose)
DEBUG("Failure reading IDCODE\n"); DEBUG_WARN("Failure reading IDCODE\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_JTAG_DBG_POWER_ERROR: case STLINK_JTAG_DBG_POWER_ERROR:
if (verbose) if (verbose)
DEBUG("Failure powering DBG\n"); DEBUG_WARN("Failure powering DBG\n");
return STLINK_ERROR_WAIT; return STLINK_ERROR_WAIT;
case STLINK_SWD_AP_WAIT: case STLINK_SWD_AP_WAIT:
if (verbose) if (verbose)
DEBUG("wait status SWD_AP_WAIT (0x%x)\n", STLINK_SWD_AP_WAIT); DEBUG_WARN("wait status SWD_AP_WAIT (0x%x)\n",
STLINK_SWD_AP_WAIT);
return STLINK_ERROR_WAIT; return STLINK_ERROR_WAIT;
case STLINK_SWD_DP_WAIT: case STLINK_SWD_DP_WAIT:
if (verbose) if (verbose)
DEBUG("wait status SWD_DP_WAIT (0x%x)\n", STLINK_SWD_DP_WAIT); DEBUG_WARN("wait status SWD_DP_WAIT (0x%x)\n",
STLINK_SWD_DP_WAIT);
return STLINK_ERROR_WAIT; return STLINK_ERROR_WAIT;
case STLINK_JTAG_WRITE_ERROR: case STLINK_JTAG_WRITE_ERROR:
if (verbose) if (verbose)
DEBUG("Write error\n"); DEBUG_WARN("Write error\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_JTAG_WRITE_VERIF_ERROR: case STLINK_JTAG_WRITE_VERIF_ERROR:
if (verbose) if (verbose)
DEBUG("Write verify error, ignoring\n"); DEBUG_WARN("Write verify error, ignoring\n");
return STLINK_ERROR_OK; return STLINK_ERROR_OK;
case STLINK_SWD_AP_FAULT: case STLINK_SWD_AP_FAULT:
/* git://git.ac6.fr/openocd commit 657e3e885b9ee10 /* git://git.ac6.fr/openocd commit 657e3e885b9ee10
@ -278,40 +281,40 @@ static int stlink_usb_error_check(uint8_t *data, bool verbose)
*/ */
Stlink.ap_error = true; Stlink.ap_error = true;
if (verbose) if (verbose)
DEBUG("STLINK_SWD_AP_FAULT\n"); DEBUG_WARN("STLINK_SWD_AP_FAULT\n");
return STLINK_ERROR_DP_FAULT; return STLINK_ERROR_DP_FAULT;
case STLINK_SWD_AP_ERROR: case STLINK_SWD_AP_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_AP_ERROR\n"); DEBUG_WARN("STLINK_SWD_AP_ERROR\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_SWD_AP_PARITY_ERROR: case STLINK_SWD_AP_PARITY_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_AP_PARITY_ERROR\n"); DEBUG_WARN("STLINK_SWD_AP_PARITY_ERROR\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_SWD_DP_FAULT: case STLINK_SWD_DP_FAULT:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_DP_FAULT\n"); DEBUG_WARN("STLINK_SWD_DP_FAULT\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_SWD_DP_ERROR: case STLINK_SWD_DP_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_DP_ERROR\n"); DEBUG_WARN("STLINK_SWD_DP_ERROR\n");
raise_exception(EXCEPTION_ERROR, "STLINK_SWD_DP_ERROR"); raise_exception(EXCEPTION_ERROR, "STLINK_SWD_DP_ERROR");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_SWD_DP_PARITY_ERROR: case STLINK_SWD_DP_PARITY_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_DP_PARITY_ERROR\n"); DEBUG_WARN("STLINK_SWD_DP_PARITY_ERROR\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_SWD_AP_WDATA_ERROR: case STLINK_SWD_AP_WDATA_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_AP_WDATA_ERROR\n"); DEBUG_WARN("STLINK_SWD_AP_WDATA_ERROR\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_SWD_AP_STICKY_ERROR: case STLINK_SWD_AP_STICKY_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_AP_STICKY_ERROR\n"); DEBUG_WARN("STLINK_SWD_AP_STICKY_ERROR\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_SWD_AP_STICKYORUN_ERROR: case STLINK_SWD_AP_STICKYORUN_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_AP_STICKYORUN_ERROR\n"); DEBUG_WARN("STLINK_SWD_AP_STICKYORUN_ERROR\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_BAD_AP_ERROR: case STLINK_BAD_AP_ERROR:
/* ADIV5 probe 256 APs, most of them are non exisitant.*/ /* ADIV5 probe 256 APs, most of them are non exisitant.*/
@ -319,20 +322,20 @@ static int stlink_usb_error_check(uint8_t *data, bool verbose)
case STLINK_TOO_MANY_AP_ERROR: case STLINK_TOO_MANY_AP_ERROR:
/* TI TM4C duplicates AP. Error happens at AP9.*/ /* TI TM4C duplicates AP. Error happens at AP9.*/
if (verbose) if (verbose)
DEBUG("STLINK_TOO_MANY_AP_ERROR\n"); DEBUG_WARN("STLINK_TOO_MANY_AP_ERROR\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
case STLINK_JTAG_UNKNOWN_CMD : case STLINK_JTAG_UNKNOWN_CMD :
if (verbose) if (verbose)
DEBUG("STLINK_JTAG_UNKNOWN_CMD\n"); DEBUG_WARN("STLINK_JTAG_UNKNOWN_CMD\n");
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
default: default:
if (verbose) if (verbose)
DEBUG("unknown/unexpected STLINK status code 0x%x\n", data[0]); DEBUG_WARN("unknown/unexpected STLINK status code 0x%x\n", data[0]);
return STLINK_ERROR_FAIL; return STLINK_ERROR_FAIL;
} }
} }
static int send_recv_retry(uint8_t *txbuf, size_t txsize, static int stlink_send_recv_retry(uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize) uint8_t *rxbuf, size_t rxsize)
{ {
uint32_t start = platform_time_ms(); uint32_t start = platform_time_ms();
@ -345,7 +348,7 @@ static int send_recv_retry(uint8_t *txbuf, size_t txsize,
return res; return res;
uint32_t now = platform_time_ms(); uint32_t now = platform_time_ms();
if (((now - start) > 1000) || (res != STLINK_ERROR_WAIT)) { if (((now - start) > 1000) || (res != STLINK_ERROR_WAIT)) {
DEBUG("write_retry failed. "); DEBUG_WARN("write_retry failed. ");
return res; return res;
} }
} }
@ -364,7 +367,7 @@ static int read_retry(uint8_t *txbuf, size_t txsize,
return res; return res;
uint32_t now = platform_time_ms(); uint32_t now = platform_time_ms();
if (((now -start) > 1000) || (res != STLINK_ERROR_WAIT)) { if (((now -start) > 1000) || (res != STLINK_ERROR_WAIT)) {
DEBUG("read_retry failed. "); DEBUG_WARN("read_retry failed. ");
stlink_usb_get_rw_status(true); stlink_usb_get_rw_status(true);
return res; return res;
} }
@ -400,7 +403,7 @@ static void stlink_version(bmp_info_t *info)
uint8_t data[12]; uint8_t data[12];
int size = send_recv(info->usb_link, cmd, 16, data, 12); int size = send_recv(info->usb_link, cmd, 16, data, 12);
if (size == -1) { if (size == -1) {
printf("[!] send_recv STLINK_APIV3_GET_VERSION_EX\n"); DEBUG_WARN("[!] stlink_send_recv STLINK_APIV3_GET_VERSION_EX\n");
} }
Stlink.ver_stlink = data[0]; Stlink.ver_stlink = data[0];
Stlink.ver_swim = data[1]; Stlink.ver_swim = data[1];
@ -415,7 +418,7 @@ static void stlink_version(bmp_info_t *info)
uint8_t data[6]; uint8_t data[6];
int size = send_recv(info->usb_link, cmd, 16, data, 6); int size = send_recv(info->usb_link, cmd, 16, data, 6);
if (size == -1) { if (size == -1) {
printf("[!] send_recv STLINK_GET_VERSION_EX\n"); DEBUG_WARN("[!] stlink_send_recv STLINK_GET_VERSION_EX\n");
} }
Stlink.vid = data[3] << 8 | data[2]; Stlink.vid = data[3] << 8 | data[2];
Stlink.pid = data[5] << 8 | data[4]; Stlink.pid = data[5] << 8 | data[4];
@ -430,15 +433,15 @@ static void stlink_version(bmp_info_t *info)
Stlink.ver_swim = (version >> 0) & 0x3f; Stlink.ver_swim = (version >> 0) & 0x3f;
} }
} }
DEBUG("V%dJ%d",Stlink.ver_stlink, Stlink.ver_jtag); DEBUG_INFO("V%dJ%d",Stlink.ver_stlink, Stlink.ver_jtag);
if (Stlink.ver_hw == 30) { if (Stlink.ver_hw == 30) {
DEBUG("M%dB%dS%d", Stlink.ver_mass, Stlink.ver_bridge, Stlink.ver_swim); DEBUG_INFO("M%dB%dS%d", Stlink.ver_mass, Stlink.ver_bridge, Stlink.ver_swim);
} else if (Stlink.ver_hw == 20) { } else if (Stlink.ver_hw == 20) {
DEBUG("S%d", Stlink.ver_swim); DEBUG_INFO("S%d", Stlink.ver_swim);
} else if (Stlink.ver_hw == 21) { } else if (Stlink.ver_hw == 21) {
DEBUG("M%d", Stlink.ver_mass); DEBUG_INFO("M%d", Stlink.ver_mass);
} }
DEBUG("\n"); DEBUG_INFO("\n");
} }
static bool stlink_leave_state(bmp_info_t *info) static bool stlink_leave_state(bmp_info_t *info)
@ -448,23 +451,23 @@ static bool stlink_leave_state(bmp_info_t *info)
send_recv(info->usb_link,cmd, 16, data, 2); send_recv(info->usb_link,cmd, 16, data, 2);
if (data[0] == STLINK_DEV_DFU_MODE) { if (data[0] == STLINK_DEV_DFU_MODE) {
uint8_t dfu_cmd[16] = {STLINK_DFU_COMMAND, STLINK_DFU_EXIT}; uint8_t dfu_cmd[16] = {STLINK_DFU_COMMAND, STLINK_DFU_EXIT};
DEBUG("Leaving DFU Mode\n"); DEBUG_INFO("Leaving DFU Mode\n");
send_recv(info->usb_link, dfu_cmd, 16, NULL, 0); send_recv(info->usb_link, dfu_cmd, 16, NULL, 0);
return true; return true;
} else if (data[0] == STLINK_DEV_SWIM_MODE) { } else if (data[0] == STLINK_DEV_SWIM_MODE) {
uint8_t swim_cmd[16] = {STLINK_SWIM_COMMAND, STLINK_SWIM_EXIT}; uint8_t swim_cmd[16] = {STLINK_SWIM_COMMAND, STLINK_SWIM_EXIT};
DEBUG("Leaving SWIM Mode\n"); DEBUG_INFO("Leaving SWIM Mode\n");
send_recv(info->usb_link, swim_cmd, 16, NULL, 0); send_recv(info->usb_link, swim_cmd, 16, NULL, 0);
} else if (data[0] == STLINK_DEV_DEBUG_MODE) { } else if (data[0] == STLINK_DEV_DEBUG_MODE) {
uint8_t dbg_cmd[16] = {STLINK_DEBUG_COMMAND, STLINK_DEBUG_EXIT}; uint8_t dbg_cmd[16] = {STLINK_DEBUG_COMMAND, STLINK_DEBUG_EXIT};
DEBUG("Leaving DEBUG Mode\n"); DEBUG_INFO("Leaving DEBUG Mode\n");
send_recv(info->usb_link, dbg_cmd, 16, NULL, 0); send_recv(info->usb_link, dbg_cmd, 16, NULL, 0);
} else if (data[0] == STLINK_DEV_BOOTLOADER_MODE) { } else if (data[0] == STLINK_DEV_BOOTLOADER_MODE) {
DEBUG("Leaving BOOTLOADER Mode\n"); DEBUG_INFO("Leaving BOOTLOADER Mode\n");
} else if (data[0] == STLINK_DEV_MASS_MODE) { } else if (data[0] == STLINK_DEV_MASS_MODE) {
DEBUG("Leaving MASS Mode\n"); DEBUG_INFO("Leaving MASS Mode\n");
} else { } else {
DEBUG("Unknown Mode %02x\n", data[0]); DEBUG_INFO("Unknown Mode %02x\n", data[0]);
} }
return false; return false;
} }
@ -503,7 +506,7 @@ int stlink_init(bmp_info_t *info)
ssize_t cnt; ssize_t cnt;
cnt = libusb_get_device_list(info->libusb_ctx, &devs); cnt = libusb_get_device_list(info->libusb_ctx, &devs);
if (cnt < 0) { if (cnt < 0) {
fprintf(stderr, "FATAL: Stlink libusb_get_device_list failed\n"); DEBUG_WARN("FATAL: Stlink libusb_get_device_list failed\n");
return -1; return -1;
} }
int i = 0; int i = 0;
@ -512,7 +515,7 @@ int stlink_init(bmp_info_t *info)
struct libusb_device_descriptor desc; struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc); int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) { if (r < 0) {
fprintf(stderr, "libusb_get_device_descriptor failed %s", DEBUG_WARN("libusb_get_device_descriptor failed %s",
libusb_strerror(r)); libusb_strerror(r));
return -1; return -1;
} }
@ -555,21 +558,21 @@ int stlink_init(bmp_info_t *info)
int config; int config;
int r = libusb_get_configuration(sl->ul_libusb_device_handle, &config); int r = libusb_get_configuration(sl->ul_libusb_device_handle, &config);
if (r) { if (r) {
fprintf(stderr, "FATAL: Stlink libusb_get_configuration failed %d: %s", DEBUG_WARN("FATAL: Stlink libusb_get_configuration failed %d: %s",
r, libusb_strerror(r)); r, libusb_strerror(r));
return -1; return -1;
} }
if (config != 1) { if (config != 1) {
r = libusb_set_configuration(sl->ul_libusb_device_handle, 0); r = libusb_set_configuration(sl->ul_libusb_device_handle, 0);
if (r) { if (r) {
fprintf(stderr, "FATAL: Stlinklibusb_set_configuration " DEBUG_WARN("FATAL: Stlinklibusb_set_configuration "
"failed %d: %s", r, libusb_strerror(r)); "failed %d: %s", r, libusb_strerror(r));
return -1; return -1;
} }
} }
r = libusb_claim_interface(sl->ul_libusb_device_handle, 0); r = libusb_claim_interface(sl->ul_libusb_device_handle, 0);
if (r) { if (r) {
fprintf(stderr, "FATAL: Stlink libusb_claim_interface failed %s\n", DEBUG_WARN("FATAL: Stlink libusb_claim_interface failed %s\n",
libusb_strerror(r)); libusb_strerror(r));
return -1; return -1;
} }
@ -580,24 +583,24 @@ int stlink_init(bmp_info_t *info)
(Stlink.ver_stlink == 3 && Stlink.ver_jtag < 3)) { (Stlink.ver_stlink == 3 && Stlink.ver_jtag < 3)) {
/* Maybe the adapter is in some strange state. Try to reset */ /* Maybe the adapter is in some strange state. Try to reset */
int result = libusb_reset_device(sl->ul_libusb_device_handle); int result = libusb_reset_device(sl->ul_libusb_device_handle);
fprintf(stderr, "INFO: Trying Stlink reset\n"); DEBUG_WARN("INFO: Trying Stlink reset\n");
if (result == LIBUSB_ERROR_BUSY) { /* Try again */ if (result == LIBUSB_ERROR_BUSY) { /* Try again */
platform_delay(50); platform_delay(50);
result = libusb_reset_device(sl->ul_libusb_device_handle); result = libusb_reset_device(sl->ul_libusb_device_handle);
} }
if (result != LIBUSB_SUCCESS) { if (result != LIBUSB_SUCCESS) {
fprintf(stderr, "FATAL: Stlink libusb_reset_device failed\n"); DEBUG_WARN("FATAL: Stlink libusb_reset_device failed\n");
return -1; return -1;
} }
stlink_version(info); stlink_version(info);
} }
if ((Stlink.ver_stlink < 3 && Stlink.ver_jtag < 32) || if ((Stlink.ver_stlink < 3 && Stlink.ver_jtag < 32) ||
(Stlink.ver_stlink == 3 && Stlink.ver_jtag < 3)) { (Stlink.ver_stlink == 3 && Stlink.ver_jtag < 3)) {
DEBUG("Please update Firmware\n"); DEBUG_WARN("Please update Firmware\n");
return -1; return -1;
} }
if (stlink_leave_state(info)) { if (stlink_leave_state(info)) {
printf("Stlink board was in DFU mode. Restart\n"); DEBUG_WARN("Stlink board was in DFU mode. Restart\n");
return -1; return -1;
} }
stlink_resetsys(info); stlink_resetsys(info);
@ -646,7 +649,7 @@ static bool stlink3_set_freq_divisor(bmp_info_t *info, uint16_t divisor)
divisor = size; divisor = size;
uint8_t *p = data + 12 + divisor * sizeof(uint32_t); uint8_t *p = data + 12 + divisor * sizeof(uint32_t);
uint32_t freq = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24; uint32_t freq = p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
DEBUG("Selected %" PRId32 " khz\n", freq); DEBUG_INFO("Selected %" PRId32 " khz\n", freq);
cmd[1] = STLINK_APIV3_SET_COM_FREQ; cmd[1] = STLINK_APIV3_SET_COM_FREQ;
cmd[2] = Stlink.transport_mode; cmd[2] = Stlink.transport_mode;
cmd[3] = 0; cmd[3] = 0;
@ -676,7 +679,7 @@ static int stlink_enter_debug_jtag(bmp_info_t *info)
STLINK_DEBUG_APIV2_ENTER, STLINK_DEBUG_APIV2_ENTER,
STLINK_DEBUG_ENTER_JTAG_NO_RESET}; STLINK_DEBUG_ENTER_JTAG_NO_RESET};
uint8_t data[2]; uint8_t data[2];
DEBUG("Enter JTAG\n"); DEBUG_INFO("Enter JTAG\n");
send_recv(info->usb_link, cmd, 16, data, 2); send_recv(info->usb_link, cmd, 16, data, 2);
return stlink_usb_error_check(data, true); return stlink_usb_error_check(data, true);
} }
@ -688,7 +691,7 @@ static uint32_t stlink_read_coreid(void)
uint8_t data[4]; uint8_t data[4];
send_recv(info.usb_link, cmd, 16, data, 4); send_recv(info.usb_link, cmd, 16, data, 4);
uint32_t id = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24; uint32_t id = data[0] | data[1] << 8 | data[2] << 16 | data[3] << 24;
DEBUG("Read Core ID: 0x%08" PRIx32 "\n", id); DEBUG_INFO("Read Core ID: 0x%08" PRIx32 "\n", id);
return id; return id;
} }
@ -713,12 +716,10 @@ uint32_t stlink_dp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
static uint32_t stlink_dp_read(ADIv5_DP_t *dp, uint16_t addr) static uint32_t stlink_dp_read(ADIv5_DP_t *dp, uint16_t addr)
{ {
if (addr & ADIV5_APnDP) { if (addr & ADIV5_APnDP) {
DEBUG_STLINK("AP read addr 0x%04" PRIx16 "\n", addr);
stlink_dp_low_access(dp, ADIV5_LOW_READ, addr, 0); stlink_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
return stlink_dp_low_access(dp, ADIV5_LOW_READ, return stlink_dp_low_access(dp, ADIV5_LOW_READ,
ADIV5_DP_RDBUFF, 0); ADIV5_DP_RDBUFF, 0);
} else { } else {
DEBUG_STLINK("DP read addr 0x%04" PRIx16 "\n", addr);
return stlink_dp_low_access(dp, ADIV5_LOW_READ, addr, 0); return stlink_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
} }
} }
@ -743,7 +744,7 @@ uint32_t stlink_dp_error(ADIv5_DP_t *dp)
adiv5_dp_write(dp, ADIV5_DP_ABORT, clr); adiv5_dp_write(dp, ADIV5_DP_ABORT, clr);
dp->fault = 0; dp->fault = 0;
if (err) if (err)
DEBUG("stlink_dp_error %d\n", err); DEBUG_WARN("stlink_dp_error %d\n", err);
err |= Stlink.ap_error; err |= Stlink.ap_error;
Stlink.ap_error = false; Stlink.ap_error = false;
return err; return err;
@ -764,15 +765,13 @@ static int stlink_read_dp_register(uint16_t port, uint16_t addr, uint32_t *reg)
cmd[4] = ((Stlink.dap_select & 0xf) << 4) | (addr & 0xf); cmd[4] = ((Stlink.dap_select & 0xf) << 4) | (addr & 0xf);
else else
cmd[4] = addr & 0xff; cmd[4] = addr & 0xff;
DEBUG_STLINK("Read DP, Addr 0x%04" PRIx16 ": \n", addr);
uint8_t data[8]; uint8_t data[8];
int res = send_recv_retry(cmd, 16, data, 8); int res = stlink_send_recv_retry(cmd, 16, data, 8);
if (res == STLINK_ERROR_OK) { if (res == STLINK_ERROR_OK) {
uint32_t ret = data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24; uint32_t ret = data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24;
DEBUG_STLINK("0x%08" PRIx32" \n", ret);
*reg = ret; *reg = ret;
} else { } else {
DEBUG_STLINK("failed, res %d\n", res); DEBUG_WARN("%s error %d\n", __func__, res);
} }
return res; return res;
} }
@ -781,7 +780,7 @@ static int stlink_write_dp_register(uint16_t port, uint16_t addr, uint32_t val)
{ {
if (port == STLINK_DEBUG_PORT_ACCESS && addr == 8) { if (port == STLINK_DEBUG_PORT_ACCESS && addr == 8) {
Stlink.dap_select = val; Stlink.dap_select = val;
DEBUG_STLINK("Caching SELECT 0x%02" PRIx32 "\n", val); DEBUG_PROBE("Caching SELECT 0x%02" PRIx32 "\n", val);
return STLINK_ERROR_OK; return STLINK_ERROR_OK;
} else { } else {
uint8_t cmd[16] = { uint8_t cmd[16] = {
@ -791,9 +790,7 @@ static int stlink_write_dp_register(uint16_t port, uint16_t addr, uint32_t val)
val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff,
(val >> 24) & 0xff}; (val >> 24) & 0xff};
uint8_t data[2]; uint8_t data[2];
send_recv_retry(cmd, 16, data, 2); stlink_send_recv_retry(cmd, 16, data, 2);
DEBUG_STLINK("Write DP, Addr 0x%04" PRIx16 ": 0x%08" PRIx32
" \n", addr, val);
return stlink_usb_error_check(data, true); return stlink_usb_error_check(data, true);
} }
} }
@ -806,11 +803,7 @@ uint32_t stlink_dp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
if (RnW) { if (RnW) {
res = stlink_read_dp_register( res = stlink_read_dp_register(
STLINK_DEBUG_PORT_ACCESS, addr, &response); STLINK_DEBUG_PORT_ACCESS, addr, &response);
DEBUG_STLINK("SWD read addr %04" PRIx16 ": %08" PRIx32 "\n",
addr, response);
} else { } else {
DEBUG_STLINK("SWD write addr %04" PRIx16 ": %08" PRIx32 "\n",
addr, value);
res = stlink_write_dp_register(STLINK_DEBUG_PORT_ACCESS, addr, value); res = stlink_write_dp_register(STLINK_DEBUG_PORT_ACCESS, addr, value);
} }
if (res == STLINK_ERROR_WAIT) if (res == STLINK_ERROR_WAIT)
@ -837,11 +830,11 @@ static bool stlink_ap_setup(int ap)
}; };
uint8_t data[2]; uint8_t data[2];
send_recv(info.usb_link, cmd, 16, data, 2); send_recv(info.usb_link, cmd, 16, data, 2);
DEBUG_STLINK("Open AP %d\n", ap); DEBUG_PROBE("Open AP %d\n", ap);
int res = stlink_usb_error_check(data, true); int res = stlink_usb_error_check(data, true);
if (res) { if (res) {
if (Stlink.ver_hw == 30) { if (Stlink.ver_hw == 30) {
DEBUG("STLINKV3 only connects to STM8/32!\n"); DEBUG_WARN("STLINKV3 only connects to STM8/32!\n");
} }
return false; return false;
} }
@ -857,7 +850,7 @@ static void stlink_ap_cleanup(int ap)
}; };
uint8_t data[2]; uint8_t data[2];
send_recv(info.usb_link, cmd, 16, data, 2); send_recv(info.usb_link, cmd, 16, data, 2);
DEBUG_STLINK("Close AP %d\n", ap); DEBUG_PROBE("Close AP %d\n", ap);
stlink_usb_error_check(data, true); stlink_usb_error_check(data, true);
} }
static int stlink_usb_get_rw_status(bool verbose) static int stlink_usb_get_rw_status(bool verbose)
@ -877,26 +870,19 @@ static void stlink_readmem(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
return; return;
size_t read_len = len; size_t read_len = len;
uint8_t type; uint8_t type;
char *CMD;
if (src & 1 || len & 1) { if (src & 1 || len & 1) {
CMD = "READMEM_8BIT";
type = STLINK_DEBUG_READMEM_8BIT; type = STLINK_DEBUG_READMEM_8BIT;
if (len > Stlink.block_size) { if (len > Stlink.block_size) {
DEBUG(" Too large!\n"); DEBUG_WARN(" Too large!\n");
return; return;
} }
if (len == 1) if (len == 1)
read_len ++; /* Fix read length as in openocd*/ read_len ++; /* Fix read length as in openocd*/
} else if (src & 3 || len & 3) { } else if (src & 3 || len & 3) {
CMD = "READMEM_16BIT";
type = STLINK_DEBUG_APIV2_READMEM_16BIT; type = STLINK_DEBUG_APIV2_READMEM_16BIT;
} else { } else {
CMD = "READMEM_32BIT";
type = STLINK_DEBUG_READMEM_32BIT; type = STLINK_DEBUG_READMEM_32BIT;
} }
DEBUG_STLINK("%s len %zu addr 0x%08" PRIx32 " AP %d : ",
CMD, len, src, ap->apsel);
uint8_t cmd[16] = { uint8_t cmd[16] = {
STLINK_DEBUG_COMMAND, STLINK_DEBUG_COMMAND,
type, type,
@ -904,34 +890,24 @@ static void stlink_readmem(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
(src >> 24) & 0xff, (src >> 24) & 0xff,
len & 0xff, len >> 8, ap->apsel}; len & 0xff, len >> 8, ap->apsel};
int res = read_retry(cmd, 16, dest, read_len); int res = read_retry(cmd, 16, dest, read_len);
if (res == STLINK_ERROR_OK) { if (res != STLINK_ERROR_OK) {
uint8_t *p = (uint8_t*)dest;
for (size_t i = 0; i < len ; i++) {
DEBUG_STLINK("%02x", *p++);
}
} else {
/* FIXME: What is the right measure when failing? /* FIXME: What is the right measure when failing?
* *
* E.g. TM4C129 gets here when NRF probe reads 0x10000010 * E.g. TM4C129 gets here when NRF probe reads 0x10000010
* Approach taken: * Approach taken:
* Fill the memory with some fixed pattern so hopefully * Fill the memory with some fixed pattern so hopefully
* the caller notices the error*/ * the caller notices the error*/
DEBUG("stlink_readmem failed\n"); DEBUG_WARN("stlink_readmem failed\n");
memset(dest, 0xff, len); memset(dest, 0xff, len);
} }
DEBUG_STLINK("\n"); DEBUG_PROBE("stlink_readmem from %" PRIx32 " to %" PRIx32 ", len %" PRIx32
"\n", src, dest, (uint32_t) len);
} }
static void stlink_writemem8(usb_link_t *link, ADIv5_AP_t *ap, uint32_t addr, static void stlink_writemem8(usb_link_t *link, ADIv5_AP_t *ap, uint32_t addr,
size_t len, uint8_t *buffer) size_t len, uint8_t *buffer)
{ {
(void)link; (void)link;
DEBUG_STLINK("Mem Write8 AP %d len %zu addr 0x%08" PRIx32 ": ",
ap->apsel, len, addr);
for (size_t t = 0; t < len; t++) {
DEBUG_STLINK("%02x", buffer[t]);
}
DEBUG_STLINK("\n");
while (len) { while (len) {
size_t length; size_t length;
/* OpenOCD has some note about writemem8*/ /* OpenOCD has some note about writemem8*/
@ -957,12 +933,6 @@ static void stlink_writemem16(usb_link_t *link, ADIv5_AP_t *ap, uint32_t addr,
size_t len, uint16_t *buffer) size_t len, uint16_t *buffer)
{ {
(void)link; (void)link;
DEBUG_STLINK("Mem Write16 AP %d len %zu addr 0x%08" PRIx32 ": ",
ap->apsel, len, addr);
for (size_t t = 0; t < len; t+=2) {
DEBUG_STLINK("%04x", buffer[t]);
}
DEBUG_STLINK("\n");
uint8_t cmd[16] = { uint8_t cmd[16] = {
STLINK_DEBUG_COMMAND, STLINK_DEBUG_COMMAND,
STLINK_DEBUG_APIV2_WRITEMEM_16BIT, STLINK_DEBUG_APIV2_WRITEMEM_16BIT,
@ -978,12 +948,6 @@ static void stlink_writemem32(usb_link_t * link, ADIv5_AP_t *ap, uint32_t addr,
size_t len, uint32_t *buffer) size_t len, uint32_t *buffer)
{ {
(void)link; (void)link;
DEBUG_STLINK("Mem Write32 AP %d len %zu addr 0x%08" PRIx32 ": ",
ap->apsel, len, addr);
for (size_t t = 0; t < len; t+=4) {
DEBUG_STLINK("%04x", buffer[t]);
}
DEBUG_STLINK("\n");
uint8_t cmd[16] = { uint8_t cmd[16] = {
STLINK_DEBUG_COMMAND, STLINK_DEBUG_COMMAND,
STLINK_DEBUG_WRITEMEM_32BIT, STLINK_DEBUG_WRITEMEM_32BIT,
@ -998,7 +962,7 @@ static void stlink_regs_read(ADIv5_AP_t *ap, void *data)
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND, STLINK_DEBUG_APIV2_READALLREGS, uint8_t cmd[16] = {STLINK_DEBUG_COMMAND, STLINK_DEBUG_APIV2_READALLREGS,
ap->apsel}; ap->apsel};
uint8_t res[88]; uint8_t res[88];
DEBUG_STLINK("AP %d: Read all core registers\n", ap->apsel); DEBUG_PROBE("AP %d: Read all core registers\n", ap->apsel);
send_recv(info.usb_link, cmd, 16, res, 88); send_recv(info.usb_link, cmd, 16, res, 88);
stlink_usb_error_check(res, true); stlink_usb_error_check(res, true);
memcpy(data, res + 4, 84); memcpy(data, res + 4, 84);
@ -1012,7 +976,7 @@ static uint32_t stlink_reg_read(ADIv5_AP_t *ap, int num)
send_recv(info.usb_link, cmd, 16, res, 8); send_recv(info.usb_link, cmd, 16, res, 8);
stlink_usb_error_check(res, true); stlink_usb_error_check(res, true);
uint32_t ret = res[0] | res[1] << 8 | res[2] << 16 | res[3] << 24; uint32_t ret = res[0] | res[1] << 8 | res[2] << 16 | res[3] << 24;
DEBUG_STLINK("AP %d: Read reg %02" PRId32 " val 0x%08" PRIx32 "\n", DEBUG_PROBE("AP %d: Read reg %02" PRId32 " val 0x%08" PRIx32 "\n",
ap->apsel, num, ret); ap->apsel, num, ret);
return ret; return ret;
} }
@ -1025,7 +989,7 @@ static void stlink_reg_write(ADIv5_AP_t *ap, int num, uint32_t val)
(val >> 24) & 0xff, ap->apsel}; (val >> 24) & 0xff, ap->apsel};
uint8_t res[2]; uint8_t res[2];
send_recv(info.usb_link, cmd, 16, res, 2); send_recv(info.usb_link, cmd, 16, res, 2);
DEBUG_STLINK("AP %d: Write reg %02" PRId32 " val 0x%08" PRIx32 "\n", DEBUG_PROBE("AP %d: Write reg %02" PRId32 " val 0x%08" PRIx32 "\n",
ap->apsel, num, val); ap->apsel, num, val);
stlink_usb_error_check(res, true); stlink_usb_error_check(res, true);
} }
@ -1129,7 +1093,7 @@ int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp)
STLINK_DEBUG_APIV2_ENTER, STLINK_DEBUG_APIV2_ENTER,
STLINK_DEBUG_ENTER_SWD_NO_RESET}; STLINK_DEBUG_ENTER_SWD_NO_RESET};
uint8_t data[2]; uint8_t data[2];
DEBUG("Enter SWD\n"); DEBUG_INFO("Enter SWD\n");
send_recv(info->usb_link, cmd, 16, data, 2); send_recv(info->usb_link, cmd, 16, data, 2);
if (stlink_usb_error_check(data, true)) if (stlink_usb_error_check(data, true))
return -1; return -1;

View File

@ -36,7 +36,4 @@ void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp);
int stlink_jtag_dp_init(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); int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens);
void stlink_exit_function(bmp_info_t *info); 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
#endif #endif

View File

@ -135,8 +135,6 @@
#define TRACE_IRQ NVIC_TIM3_IRQ #define TRACE_IRQ NVIC_TIM3_IRQ
#define TRACE_ISR tim3_isr #define TRACE_ISR tim3_isr
#define DEBUG(...)
#define gpio_set_val(port, pin, val) do { \ #define gpio_set_val(port, pin, val) do { \
if(val) \ if(val) \
gpio_set((port), (pin)); \ gpio_set((port), (pin)); \

View File

@ -98,8 +98,6 @@ extern const usbd_driver lm4f_usb_driver;
#define vasprintf vasiprintf #define vasprintf vasiprintf
#define snprintf sniprintf #define snprintf sniprintf
#define DEBUG(...)
#define SET_RUN_STATE(state) {running_status = (state);} #define SET_RUN_STATE(state) {running_status = (state);}
#define SET_IDLE_STATE(state) {} #define SET_IDLE_STATE(state) {}
#define SET_ERROR_STATE(state) SET_IDLE_STATE(state) #define SET_ERROR_STATE(state) SET_IDLE_STATE(state)

View File

@ -30,10 +30,14 @@
#define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_TRACESWO
#define PLATFORM_HAS_POWER_SWITCH #define PLATFORM_HAS_POWER_SWITCH
#ifdef ENABLE_DEBUG #ifdef ENABLE_DEBUG
# define PLATFORM_HAS_DEBUG # define PLATFORM_HAS_DEBUG
# define USBUART_DEBUG # define USBUART_DEBUG
extern bool debug_bmp;
int usbuart_debug_write(const char *buf, size_t len);
#endif #endif
#define BOARD_IDENT "Black Magic Probe" #define BOARD_IDENT "Black Magic Probe"
#define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)" #define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)"
#define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)" #define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)"
@ -165,15 +169,6 @@
#define TRACE_IRQ NVIC_TIM3_IRQ #define TRACE_IRQ NVIC_TIM3_IRQ
#define TRACE_ISR tim3_isr #define TRACE_ISR tim3_isr
#ifdef ENABLE_DEBUG
extern bool debug_bmp;
int usbuart_debug_write(const char *buf, size_t len);
#define DEBUG printf
#else
#define DEBUG(...)
#endif
#define SET_RUN_STATE(state) {running_status = (state);} #define SET_RUN_STATE(state) {running_status = (state);}
#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);}
#define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} #define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);}

View File

@ -1,8 +1,8 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2019 * Copyright (C) 2019 - 2020 Uwe Bonnes
* Written by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -63,7 +63,7 @@ static int bmp_mmap(char *file, struct mmap_data *map)
map->hFile = CreateFile(file, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, map->hFile = CreateFile(file, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, 0, NULL); NULL, OPEN_ALWAYS, 0, NULL);
if (map->hFile == INVALID_HANDLE_VALUE) { if (map->hFile == INVALID_HANDLE_VALUE) {
DEBUG("Open file %s failed: %s\n", file, strerror(errno)); DEBUG_WARN("Open file %s failed: %s\n", file, strerror(errno));
return -1; return -1;
} }
map->size = GetFileSize(map->hFile, NULL); map->size = GetFileSize(map->hFile, NULL);
@ -76,13 +76,13 @@ static int bmp_mmap(char *file, struct mmap_data *map)
NULL); /* name of mapping object */ NULL); /* name of mapping object */
if (map->hMapFile == NULL || map->hMapFile == INVALID_HANDLE_VALUE) { if (map->hMapFile == NULL || map->hMapFile == INVALID_HANDLE_VALUE) {
DEBUG("Map file %s failed: %s\n", file, strerror(errno)); DEBUG_WARN("Map file %s failed: %s\n", file, strerror(errno));
CloseHandle(map->hFile); CloseHandle(map->hFile);
return -1; return -1;
} }
map->data = MapViewOfFile(map->hMapFile, FILE_MAP_READ, 0, 0, 0); map->data = MapViewOfFile(map->hMapFile, FILE_MAP_READ, 0, 0, 0);
if (!map->data) { if (!map->data) {
printf("Could not create file mapping object (%s).\n", DEBUG_WARN("Could not create file mapping object (%s).\n",
strerror(errno)); strerror(errno));
CloseHandle(map->hMapFile); CloseHandle(map->hMapFile);
return -1; return -1;
@ -90,7 +90,7 @@ static int bmp_mmap(char *file, struct mmap_data *map)
#else #else
map->fd = open(file, O_RDONLY | O_BINARY); map->fd = open(file, O_RDONLY | O_BINARY);
if (map->fd < 0) { if (map->fd < 0) {
DEBUG("Open file %s failed: %s\n", file, strerror(errno)); DEBUG_WARN("Open file %s failed: %s\n", file, strerror(errno));
return -1; return -1;
} }
struct stat stat; struct stat stat;
@ -115,34 +115,37 @@ static void bmp_munmap(struct mmap_data *map)
static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt) static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
{ {
printf("%s\n\n", opt->opt_idstring); DEBUG_WARN("%s for: \n", opt->opt_idstring);
printf("Usage: %s [options]\n", argv[0]); DEBUG_WARN("\tBMP Firmware, ST-Link V2/3, CMSIS_DAP, JLINK and "
printf("\t-h\t\t: This help.\n"); "LIBFTDI/MPSSE\n\n");
printf("\t-v[1|2]\t\t: Increasing verbosity\n"); DEBUG_WARN("Usage: %s [options]\n", argv[0]);
printf("\t-d \"path\"\t: Use serial device at \"path\"\n"); DEBUG_WARN("\t-h\t\t: This help.\n");
printf("\t-P <num>\t: Use debugger found at position <num>\n"); DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n");
printf("\t-n <num>\t: Use target device found at position <num>\n"); DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n");
printf("\t-s \"string\"\t: Use dongle with (partial) " DEBUG_WARN("Probe selection arguments:\n");
"serial number \"string\"\n"); DEBUG_WARN("\t-d \"path\"\t: Use serial device at \"path\"\n");
printf("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n"); DEBUG_WARN("\t-P <pos>\t: Use debugger found at position <pos>\n");
printf("\tRun mode related options:\n"); DEBUG_WARN("\t-n <num>\t: Use target device found at position <num>\n");
printf("\tDefault mode is to start the debug server at :2000\n"); DEBUG_WARN("\t-s \"serial\"\t: Use dongle with (partial) "
printf("\t-j\t\t: Use JTAG. SWD is default.\n"); "serial number \"serial\"\n");
printf("\t-C\t\t: Connect under reset\n"); DEBUG_WARN("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n");
printf("\t-t\t\t: Scan SWD and display information about connected" DEBUG_WARN("Run mode related options:\n");
"devices\n"); DEBUG_WARN("\tDefault mode is to start the debug server at :2000\n");
printf("\t-E\t\t: Erase flash until flash end or for given size\n"); DEBUG_WARN("\t-j\t\t: Use JTAG. SWD is default.\n");
printf("\t-V\t\t: Verify flash against binary file\n"); DEBUG_WARN("\t-C\t\t: Connect under reset\n");
printf("\t-r\t\t: Read flash and write to binary file\n"); DEBUG_WARN("\t-t\t\t: Scan SWD or JTAG and display information about \n"
printf("\t-p\t\t: Supplies power to the target (where applicable)\n"); "\t\t\t connected devices\n");
printf("\t-R\t\t: Reset device\n"); DEBUG_WARN("\t-E\t\t: Erase flash until flash end or for given size\n");
printf("\tFlash operation modifiers options:\n"); DEBUG_WARN("\t-V\t\t: Verify flash against binary file\n");
printf("\t-a <num>\t: Start flash operation at flash address <num>\n" DEBUG_WARN("\t-r\t\t: Read flash and write to binary file\n");
"\t\t\t Default start is 0x08000000\n"); DEBUG_WARN("\t-p\t\t: Supplies power to the target (where applicable)\n");
printf("\t-S <num>\t: Read <num> bytes. Default is until read fails.\n"); DEBUG_WARN("\t-R\t\t: Reset device\n");
printf("\t <file>\t\t: Use (binary) file <file> for flash operation\n" DEBUG_WARN("Flash operation modifiers options:\n");
"\t\t\t Given <file> writes to flash if neither -r or -V is " DEBUG_WARN("\tDefault action with given file is to write to flash\n");
"given\n"); DEBUG_WARN("\t-a <addr>\t: Start flash operation at flash address <addr>\n"
"\t\t\t Default start is start of flash in memory map\n");
DEBUG_WARN("\t-S <num>\t: Read <num> bytes. Default is until read fails.\n");
DEBUG_WARN("\t <file>\t\t: Use (binary) file <file> for flash operation\n");
exit(0); exit(0);
} }
@ -150,9 +153,8 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
{ {
int c; int c;
opt->opt_target_dev = 1; opt->opt_target_dev = 1;
opt->opt_flash_start = 0x08000000;
opt->opt_flash_size = 16 * 1024 *1024; opt->opt_flash_size = 16 * 1024 *1024;
while((c = getopt(argc, argv, "Ehv::d:s:I:c:Cn:tVta:S:jpP:rR")) != -1) { while((c = getopt(argc, argv, "Ehv:d:s:I:c:CnltVta:S:jpP:rR")) != -1) {
switch(c) { switch(c) {
case 'c': case 'c':
if (optarg) if (optarg)
@ -163,13 +165,15 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
break; break;
case 'v': case 'v':
if (optarg) if (optarg)
cl_debuglevel = strtol(optarg, NULL, 0); cl_debuglevel = strtol(optarg, NULL, 0) & (BMP_DEBUG_MAX - 1);
else
cl_debuglevel = -1;
break; break;
case 'j': case 'j':
opt->opt_usejtag = true; opt->opt_usejtag = true;
break; break;
case 'l':
opt->opt_list_only = true;
cl_debuglevel |= BMP_DEBUG_STDOUT;
break;
case 'C': case 'C':
opt->opt_connect_under_reset = true; opt->opt_connect_under_reset = true;
break; break;
@ -190,6 +194,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
break; break;
case 't': case 't':
opt->opt_mode = BMP_MODE_TEST; opt->opt_mode = BMP_MODE_TEST;
cl_debuglevel |= BMP_DEBUG_INFO | BMP_DEBUG_STDOUT;
break; break;
case 'V': case 'V':
opt->opt_mode = BMP_MODE_FLASH_VERIFY; opt->opt_mode = BMP_MODE_FLASH_VERIFY;
@ -242,7 +247,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
/* Checks */ /* Checks */
if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) || if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) ||
(opt->opt_mode == BMP_MODE_RESET))) { (opt->opt_mode == BMP_MODE_RESET))) {
printf("Ignoring filename in reset/test mode\n"); DEBUG_WARN("Ignoring filename in reset/test mode\n");
opt->opt_flash_file = NULL; opt->opt_flash_file = NULL;
} }
} }
@ -250,7 +255,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
static void display_target(int i, target *t, void *context) static void display_target(int i, target *t, void *context)
{ {
(void)context; (void)context;
DEBUG("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ', DEBUG_INFO("*** %2d %c %s %s\n", i, target_attached(t)?'*':' ',
target_driver_name(t), target_driver_name(t),
(target_core_name(t)) ? target_core_name(t): ""); (target_core_name(t)) ? target_core_name(t): "");
} }
@ -261,42 +266,44 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
int num_targets; int num_targets;
#if defined(PLATFORM_HAS_POWER_SWITCH) #if defined(PLATFORM_HAS_POWER_SWITCH)
if (opt->opt_tpwr) { if (opt->opt_tpwr) {
printf("Powering up device"); DEBUG_INFO("Powering up device");
platform_target_set_power(true); platform_target_set_power(true);
platform_delay(500); platform_delay(500);
} }
#endif #endif
if (opt->opt_connect_under_reset) if (opt->opt_connect_under_reset)
printf("Connecting under reset\n"); DEBUG_INFO("Connecting under reset\n");
connect_assert_srst = opt->opt_connect_under_reset; connect_assert_srst = opt->opt_connect_under_reset;
platform_srst_set_val(opt->opt_connect_under_reset); platform_srst_set_val(opt->opt_connect_under_reset);
if (opt->opt_mode == BMP_MODE_TEST) if (opt->opt_mode == BMP_MODE_TEST)
printf("Running in Test Mode\n"); DEBUG_INFO("Running in Test Mode\n");
if (platform_target_voltage()) if (platform_target_voltage())
printf("Target voltage: %s Volt\n", platform_target_voltage()); DEBUG_INFO("Target voltage: %s Volt\n", platform_target_voltage());
if (opt->opt_usejtag) { if (opt->opt_usejtag) {
num_targets = platform_jtag_scan(NULL); num_targets = platform_jtag_scan(NULL);
} else { } else {
num_targets = platform_adiv5_swdp_scan(); num_targets = platform_adiv5_swdp_scan();
} }
if (!num_targets) { if (!num_targets) {
DEBUG("No target found\n"); DEBUG_WARN("No target found\n");
return res; return res;
} else { } else {
target_foreach(display_target, NULL); target_foreach(display_target, NULL);
} }
if (opt->opt_target_dev > num_targets) { if (opt->opt_target_dev > num_targets) {
DEBUG("Given target nummer %d not available\n", opt->opt_target_dev); DEBUG_WARN("Given target nummer %d not available\n",
opt->opt_target_dev);
return res; return res;
} }
target *t = target_attach_n(opt->opt_target_dev, NULL); target *t = target_attach_n(opt->opt_target_dev, NULL);
if (!t) { if (!t) {
DEBUG("Can not attach to target %d\n", opt->opt_target_dev); DEBUG_WARN("Can not attach to target %d\n", opt->opt_target_dev);
goto target_detach; goto target_detach;
} }
if (opt->opt_mode == BMP_MODE_TEST) { /* Always scan memory map to find lowest flash */
char map [1024], *p = map; char memory_map [1024], *p = memory_map;
if (target_mem_map(t, map, sizeof(map))) { uint32_t flash_start = 0xffffffff;
if (target_mem_map(t, memory_map, sizeof(memory_map))) {
while (*p && (*p == '<')) { while (*p && (*p == '<')) {
unsigned int start, size; unsigned int start, size;
char *res; char *res;
@ -311,9 +318,13 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
unsigned int blocksize; unsigned int blocksize;
if (sscanf(p, "<memory type=\"flash\" start=\"%x\" length=\"%x\">" if (sscanf(p, "<memory type=\"flash\" start=\"%x\" length=\"%x\">"
"<property name=\"blocksize\">%x</property></memory>", "<property name=\"blocksize\">%x</property></memory>",
&start, &size, &blocksize)) &start, &size, &blocksize)) {
printf("Flash Start: 0x%08x, length %#9x, blocksize %#8x\n", if (opt->opt_mode == BMP_MODE_TEST)
start, size, blocksize); DEBUG_INFO("Flash Start: 0x%08x, length %#9x, "
"blocksize %#8x\n", start, size, blocksize);
if (start < flash_start)
flash_start = start;
}
res = strstr(p, "</memory>"); res = strstr(p, "</memory>");
p = res + strlen("</memory>"); p = res + strlen("</memory>");
continue; continue;
@ -322,7 +333,9 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
if (!match) { if (!match) {
if (sscanf(p, "<memory type=\"ram\" start=\"%x\" length=\"%x\"/", if (sscanf(p, "<memory type=\"ram\" start=\"%x\" length=\"%x\"/",
&start, &size)) &start, &size))
printf("Ram Start: 0x%08x, length %#9x\n", start, size); if (opt->opt_mode == BMP_MODE_TEST)
DEBUG_INFO("Ram Start: 0x%08x, length %#9x\n",
start, size);
res = strstr(p, "/>"); res = strstr(p, "/>");
p = res + strlen("/>"); p = res + strlen("/>");
continue; continue;
@ -330,14 +343,16 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
break; break;
} }
} }
if (opt->opt_flash_start < flash_start)
opt->opt_flash_start = flash_start;
if (opt->opt_mode == BMP_MODE_TEST)
goto target_detach; goto target_detach;
}
int read_file = -1; int read_file = -1;
if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) || if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
(opt->opt_mode == BMP_MODE_FLASH_VERIFY)) { (opt->opt_mode == BMP_MODE_FLASH_VERIFY)) {
int mmap_res = bmp_mmap(opt->opt_flash_file, &map); int mmap_res = bmp_mmap(opt->opt_flash_file, &map);
if (mmap_res) { if (mmap_res) {
DEBUG("Can not map file: %s. Aborting!\n", strerror(errno)); DEBUG_WARN("Can not map file: %s. Aborting!\n", strerror(errno));
goto target_detach; goto target_detach;
} }
} else if (opt->opt_mode == BMP_MODE_FLASH_READ) { } else if (opt->opt_mode == BMP_MODE_FLASH_READ) {
@ -345,7 +360,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
read_file = open(opt->opt_flash_file, O_TRUNC | O_CREAT | O_RDWR | O_BINARY, read_file = open(opt->opt_flash_file, O_TRUNC | O_CREAT | O_RDWR | O_BINARY,
S_IRUSR | S_IWUSR); S_IRUSR | S_IWUSR);
if (read_file == -1) { if (read_file == -1) {
printf("Error opening flashfile %s for read: %s\n", DEBUG_WARN("Error opening flashfile %s for read: %s\n",
opt->opt_flash_file, strerror(errno)); opt->opt_flash_file, strerror(errno));
return res; return res;
} }
@ -356,51 +371,52 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
if (opt->opt_mode == BMP_MODE_RESET) { if (opt->opt_mode == BMP_MODE_RESET) {
target_reset(t); target_reset(t);
} else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) { } else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) {
DEBUG("Erase %zu bytes at 0x%08" PRIx32 "\n", opt->opt_flash_size, DEBUG_INFO("Erase %zu bytes at 0x%08" PRIx32 "\n", opt->opt_flash_size,
opt->opt_flash_start); opt->opt_flash_start);
unsigned int erased = target_flash_erase(t, opt->opt_flash_start, unsigned int erased = target_flash_erase(t, opt->opt_flash_start,
opt->opt_flash_size); opt->opt_flash_size);
if (erased) { if (erased) {
DEBUG("Erased failed!\n"); DEBUG_WARN("Erased failed!\n");
goto free_map; goto free_map;
} }
target_reset(t); target_reset(t);
} else if (opt->opt_mode == BMP_MODE_FLASH_WRITE) { } else if (opt->opt_mode == BMP_MODE_FLASH_WRITE) {
DEBUG("Erase %zu bytes at 0x%08" PRIx32 "\n", map.size, DEBUG_INFO("Erase %zu bytes at 0x%08" PRIx32 "\n", map.size,
opt->opt_flash_start); opt->opt_flash_start);
uint32_t start_time = platform_time_ms(); uint32_t start_time = platform_time_ms();
unsigned int erased = target_flash_erase(t, opt->opt_flash_start, unsigned int erased = target_flash_erase(t, opt->opt_flash_start,
map.size); map.size);
if (erased) { if (erased) {
DEBUG("Erased failed!\n"); DEBUG_WARN("Erased failed!\n");
goto free_map; goto free_map;
} else { } else {
DEBUG("Flashing %zu bytes at 0x%08" PRIx32 "\n", DEBUG_INFO("Flashing %zu bytes at 0x%08" PRIx32 "\n",
map.size, opt->opt_flash_start); map.size, opt->opt_flash_start);
unsigned int flashed = target_flash_write(t, opt->opt_flash_start, unsigned int flashed = target_flash_write(t, opt->opt_flash_start,
map.data, map.size); map.data, map.size);
/* Buffered write cares for padding*/ /* Buffered write cares for padding*/
if (flashed) { if (flashed) {
DEBUG("Flashing failed!\n"); DEBUG_WARN("Flashing failed!\n");
} else { } else {
DEBUG("Success!\n"); DEBUG_INFO("Success!\n");
res = 0; res = 0;
} }
} }
target_flash_done(t); target_flash_done(t);
target_reset(t); target_reset(t);
uint32_t end_time = platform_time_ms(); uint32_t end_time = platform_time_ms();
printf("Flash Write succeeded for %d bytes, %8.3f kiB/s\n", DEBUG_WARN("Flash Write succeeded for %d bytes, %8.3f kiB/s\n",
(int)map.size, (((map.size * 1.0)/(end_time - start_time)))); (int)map.size, (((map.size * 1.0)/(end_time - start_time))));
} else { } else {
#define WORKSIZE 1024 #define WORKSIZE 1024
uint8_t *data = alloca(WORKSIZE); uint8_t *data = alloca(WORKSIZE);
if (!data) { if (!data) {
printf("Can not malloc memory for flash read/verify operation\n"); DEBUG_WARN("Can not malloc memory for flash read/verify "
"operation\n");
return res; return res;
} }
if (opt->opt_mode == BMP_MODE_FLASH_READ) if (opt->opt_mode == BMP_MODE_FLASH_READ)
printf("Reading flash from 0x%08" PRIx32 " for %zu" DEBUG_INFO("Reading flash from 0x%08" PRIx32 " for %zu"
" bytes to %s\n", opt->opt_flash_start, opt->opt_flash_size, " bytes to %s\n", opt->opt_flash_start, opt->opt_flash_size,
opt->opt_flash_file); opt->opt_flash_file);
uint32_t flash_src = opt->opt_flash_start; uint32_t flash_src = opt->opt_flash_start;
@ -414,11 +430,11 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
int n_read = target_mem_read(t, data, flash_src, worksize); int n_read = target_mem_read(t, data, flash_src, worksize);
if (n_read) { if (n_read) {
if (opt->opt_flash_size == 0) {/* we reached end of flash */ if (opt->opt_flash_size == 0) {/* we reached end of flash */
printf("Reached end of flash at size %" PRId32 "\n", DEBUG_INFO("Reached end of flash at size %" PRId32 "\n",
flash_src - opt->opt_flash_start); flash_src - opt->opt_flash_start);
break; break;
} else { } else {
printf("Read failed at flash address 0x%08" PRIx32 "\n", DEBUG_WARN("Read failed at flash address 0x%08" PRIx32 "\n",
flash_src); flash_src);
break; break;
} }
@ -428,15 +444,15 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
if (opt->opt_mode == BMP_MODE_FLASH_VERIFY) { if (opt->opt_mode == BMP_MODE_FLASH_VERIFY) {
int difference = memcmp(data, flash, worksize); int difference = memcmp(data, flash, worksize);
if (difference){ if (difference){
printf("Verify failed at flash region 0x%08" PRIx32 "\n", DEBUG_WARN("Verify failed at flash region 0x%08"
flash_src); PRIx32 "\n", flash_src);
return -1; return -1;
} }
flash += worksize; flash += worksize;
} else if (read_file != -1) { } else if (read_file != -1) {
int written = write(read_file, data, worksize); int written = write(read_file, data, worksize);
if (written < worksize) { if (written < worksize) {
printf("Read failed at flash region 0x%08" PRIx32 "\n", DEBUG_WARN("Read failed at flash region 0x%08" PRIx32 "\n",
flash_src); flash_src);
return -1; return -1;
} }
@ -449,7 +465,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
uint32_t end_time = platform_time_ms(); uint32_t end_time = platform_time_ms();
if (read_file != -1) if (read_file != -1)
close(read_file); close(read_file);
printf("Read/Verified succeeded for %d bytes, %8.3f kiB/s\n", DEBUG_WARN("Read/Verify succeeded for %d bytes, %8.3f kiB/s\n",
bytes_read, (((bytes_read * 1.0)/(end_time - start_time)))); bytes_read, (((bytes_read * 1.0)/(end_time - start_time))));
} }
free_map: free_map:

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2019 Uwe Bonnes * Copyright (C) 2019 - 2020 Uwe Bonnes
* Written by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * Written by Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
@ -40,6 +40,7 @@ typedef struct BMP_CL_OPTIONS_s {
enum bmp_cl_mode opt_mode; enum bmp_cl_mode opt_mode;
bool opt_usejtag; bool opt_usejtag;
bool opt_tpwr; bool opt_tpwr;
bool opt_list_only;
bool opt_connect_under_reset; bool opt_connect_under_reset;
char *opt_flash_file; char *opt_flash_file;
char *opt_device; char *opt_device;
@ -54,7 +55,6 @@ typedef struct BMP_CL_OPTIONS_s {
char *opt_idstring; char *opt_idstring;
}BMP_CL_OPTIONS_t; }BMP_CL_OPTIONS_t;
extern int cl_debuglevel;
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv); void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
int cl_execute(BMP_CL_OPTIONS_t *opt); int cl_execute(BMP_CL_OPTIONS_t *opt);
int serial_open(BMP_CL_OPTIONS_t *opt, char *serial); int serial_open(BMP_CL_OPTIONS_t *opt, char *serial);

View File

@ -89,7 +89,7 @@ int gdb_if_init(void)
} }
break; break;
} while(1); } while(1);
DEBUG("Listening on TCP: %4d\n", port); DEBUG_WARN("Listening on TCP: %4d\n", port);
return 0; return 0;
} }
@ -125,9 +125,11 @@ unsigned char gdb_if_getchar(void)
platform_delay(100); platform_delay(100);
} else { } else {
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32) || defined(__CYGWIN__)
DEBUG("error when accepting connection: %d", WSAGetLastError()); DEBUG_WARN("error when accepting connection: %d",
WSAGetLastError());
#else #else
DEBUG("error when accepting connection: %s", strerror(errno)); DEBUG_WARN("error when accepting connection: %s",
strerror(errno));
#endif #endif
exit(1); exit(1);
} }
@ -141,7 +143,7 @@ unsigned char gdb_if_getchar(void)
break; break;
} }
} }
DEBUG("Got connection\n"); DEBUG_INFO("Got connection\n");
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32) || defined(__CYGWIN__)
opt = 0; opt = 0;
ioctlsocket(gdb_if_conn, FIONBIO, &opt); ioctlsocket(gdb_if_conn, FIONBIO, &opt);
@ -154,9 +156,9 @@ unsigned char gdb_if_getchar(void)
if(i <= 0) { if(i <= 0) {
gdb_if_conn = -1; gdb_if_conn = -1;
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32) || defined(__CYGWIN__)
DEBUG("Dropped broken connection: %d\n", WSAGetLastError()); DEBUG_INFO("Dropped broken connection: %d\n", WSAGetLastError());
#else #else
DEBUG("Dropped broken connection: %s\n", strerror(errno)); DEBUG_INFO("Dropped broken connection: %s\n", strerror(errno));
#endif #endif
/* Return '+' in case we were waiting for an ACK */ /* Return '+' in case we were waiting for an ACK */
return '+'; return '+';

View File

@ -25,15 +25,15 @@ static void LIBUSB_CALL on_trans_done(struct libusb_transfer *trans)
if (trans->status != LIBUSB_TRANSFER_COMPLETED) if (trans->status != LIBUSB_TRANSFER_COMPLETED)
{ {
fprintf(stderr, "on_trans_done: "); DEBUG_WARN("on_trans_done: ");
if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) { if(trans->status == LIBUSB_TRANSFER_TIMED_OUT) {
fprintf(stderr, " Timeout\n"); DEBUG_WARN(" Timeout\n");
} else if (trans->status == LIBUSB_TRANSFER_CANCELLED) { } else if (trans->status == LIBUSB_TRANSFER_CANCELLED) {
fprintf(stderr, " cancelled\n"); DEBUG_WARN(" cancelled\n");
} else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) { } else if (trans->status == LIBUSB_TRANSFER_NO_DEVICE) {
fprintf(stderr, " no device\n"); DEBUG_WARN(" no device\n");
} else { } else {
fprintf(stderr, " unknown\n"); DEBUG_WARN(" unknown\n");
} }
ctx->flags |= TRANS_FLAGS_HAS_ERROR; ctx->flags |= TRANS_FLAGS_HAS_ERROR;
} }
@ -51,7 +51,7 @@ static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) {
trans->user_data = &trans_ctx; trans->user_data = &trans_ctx;
if ((error = libusb_submit_transfer(trans))) { if ((error = libusb_submit_transfer(trans))) {
fprintf(stderr, "libusb_submit_transfer(%d): %s\n", error, DEBUG_WARN("libusb_submit_transfer(%d): %s\n", error,
libusb_strerror(error)); libusb_strerror(error));
exit(-1); exit(-1);
} }
@ -62,18 +62,18 @@ static int submit_wait(usb_link_t *link, struct libusb_transfer *trans) {
timeout.tv_sec = 1; timeout.tv_sec = 1;
timeout.tv_usec = 0; timeout.tv_usec = 0;
if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) { if (libusb_handle_events_timeout(link->ul_libusb_ctx, &timeout)) {
fprintf(stderr, "libusb_handle_events()\n"); DEBUG_WARN("libusb_handle_events()\n");
return -1; return -1;
} }
uint32_t now = platform_time_ms(); uint32_t now = platform_time_ms();
if (now - start_time > 1000) { if (now - start_time > 1000) {
libusb_cancel_transfer(trans); libusb_cancel_transfer(trans);
fprintf(stderr, "libusb_handle_events() timeout\n"); DEBUG_WARN("libusb_handle_events() timeout\n");
return -1; return -1;
} }
} }
if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) { if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR) {
fprintf(stderr, "libusb_handle_events() | has_error\n"); DEBUG_WARN("libusb_handle_events() | has_error\n");
return -1; return -1;
} }
@ -93,19 +93,17 @@ int send_recv(usb_link_t *link,
link->ep_tx | LIBUSB_ENDPOINT_OUT, link->ep_tx | LIBUSB_ENDPOINT_OUT,
txbuf, txlen, txbuf, txlen,
NULL, NULL, 0); NULL, NULL, 0);
if (cl_debuglevel > 0) {
int i = 0; int i = 0;
printf(" Send (%3d): ", txlen); DEBUG_WIRE(" Send (%3d): ", txlen);
for (; i < txlen; i++) { for (; i < txlen; i++) {
printf("%02x", txbuf[i]); DEBUG_WIRE("%02x", txbuf[i]);
if ((i & 7) == 7) if ((i & 7) == 7)
printf("."); DEBUG_WIRE(".");
if ((i & 31) == 31) if ((i & 31) == 31)
printf("\n "); DEBUG_WIRE("\n ");
} }
if (!(i & 31)) if (!(i & 31))
printf("\n"); DEBUG_WIRE("\n");
}
if (submit_wait(link, link->req_trans)) { if (submit_wait(link, link->req_trans)) {
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx); libusb_clear_halt(link->ul_libusb_device_handle, link->ep_tx);
return -1; return -1;
@ -119,7 +117,7 @@ int send_recv(usb_link_t *link,
rxbuf, rxsize, NULL, NULL, 0); rxbuf, rxsize, NULL, NULL, 0);
if (submit_wait(link, link->rep_trans)) { if (submit_wait(link, link->rep_trans)) {
DEBUG("clear 1\n"); DEBUG_WARN("clear 1\n");
libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx); libusb_clear_halt(link->ul_libusb_device_handle, link->ep_rx);
return -1; return -1;
} }
@ -127,17 +125,14 @@ int send_recv(usb_link_t *link,
if (res >0) { if (res >0) {
int i; int i;
uint8_t *p = rxbuf; uint8_t *p = rxbuf;
if (cl_debuglevel > 0) { DEBUG_WIRE(" Rec (%zu/%d)", rxsize, res);
printf(" Rec (%zu/%d)", rxsize, res);
for (i = 0; i < res && i < 32 ; i++) { for (i = 0; i < res && i < 32 ; i++) {
if ( i && ((i & 7) == 0)) if ( i && ((i & 7) == 0))
printf("."); DEBUG_WIRE(".");
printf("%02x", p[i]); DEBUG_WIRE("%02x", p[i]);
} }
} }
} }
} DEBUG_WIRE("\n");
if (cl_debuglevel > 0)
printf("\n");
return res; return res;
} }

View File

@ -2,7 +2,7 @@
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2019 Dave Marples <dave@marples.net> * Copyright (C) 2019 Dave Marples <dave@marples.net>
* with additions from Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de) * Modifications (C) 2020 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -40,7 +40,7 @@ static int set_interface_attribs(void)
struct termios tty; struct termios tty;
memset (&tty, 0, sizeof tty); memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0) { if (tcgetattr (fd, &tty) != 0) {
fprintf(stderr,"error %d from tcgetattr", errno); DEBUG_WARN("error %d from tcgetattr", errno);
return -1; return -1;
} }
@ -62,7 +62,7 @@ static int set_interface_attribs(void)
tty.c_cflag &= ~CRTSCTS; tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0) { if (tcsetattr (fd, TCSANOW, &tty) != 0) {
fprintf(stderr,"error %d from tcsetattr", errno); DEBUG_WARN("error %d from tcsetattr", errno);
return -1; return -1;
} }
return 0; return 0;
@ -77,7 +77,7 @@ int serial_open(BMP_CL_OPTIONS_t *cl_opts, char *serial)
struct dirent *dp; struct dirent *dp;
DIR *dir = opendir(DEVICE_BY_ID); DIR *dir = opendir(DEVICE_BY_ID);
if (!dir) { if (!dir) {
fprintf(stderr, "No serial device found\n"); DEBUG_WARN("No serial device found\n");
return -1; return -1;
} }
int num_devices = 0; int num_devices = 0;
@ -95,24 +95,25 @@ int serial_open(BMP_CL_OPTIONS_t *cl_opts, char *serial)
} }
closedir(dir); closedir(dir);
if ((num_devices == 0) && (num_total == 0)){ if ((num_devices == 0) && (num_total == 0)){
fprintf(stderr, "No BMP probe found\n"); DEBUG_WARN("No BMP probe found\n");
return -1; return -1;
} else if (num_devices != 1) { } else if (num_devices != 1) {
fprintf(stderr, "Available Probes:\n"); DEBUG_INFO("Available Probes:\n");
dir = opendir(DEVICE_BY_ID); dir = opendir(DEVICE_BY_ID);
if (dir) { if (dir) {
while ((dp = readdir(dir)) != NULL) { while ((dp = readdir(dir)) != NULL) {
if ((strstr(dp->d_name, BMP_IDSTRING)) && if ((strstr(dp->d_name, BMP_IDSTRING)) &&
(strstr(dp->d_name, "-if00"))) (strstr(dp->d_name, "-if00")))
fprintf(stderr, "%s\n", dp->d_name); DEBUG_WARN("%s\n", dp->d_name);
} }
closedir(dir); closedir(dir);
if (serial) if (serial)
fprintf(stderr, "Do no match given serial \"%s\"\n", serial); DEBUG_WARN("Do no match given serial \"%s\"\n", serial);
else else
fprintf(stderr, "Select Probe with -s <(Partial) Serial Number\n"); DEBUG_WARN("Select Probe with -s <(Partial) Serial "
"Number\n");
} else { } else {
fprintf(stderr, "Could not opendir %s: %s\n", name, strerror(errno)); DEBUG_WARN("Could not opendir %s: %s\n", name, strerror(errno));
} }
return -1; return -1;
} }
@ -121,7 +122,7 @@ int serial_open(BMP_CL_OPTIONS_t *cl_opts, char *serial)
} }
fd = open(name, O_RDWR | O_SYNC | O_NOCTTY); fd = open(name, O_RDWR | O_SYNC | O_NOCTTY);
if (fd < 0) { if (fd < 0) {
fprintf(stderr,"Couldn't open serial port %s\n", name); DEBUG_WARN("Couldn't open serial port %s\n", name);
return -1; return -1;
} }
/* BMP only offers an USB-Serial connection with no real serial /* BMP only offers an USB-Serial connection with no real serial
@ -139,12 +140,11 @@ int platform_buffer_write(const uint8_t *data, int size)
{ {
int s; int s;
if (cl_debuglevel) DEBUG_WIRE("%s\n", data);
printf("%s\n",data);
s = write(fd, data, size); s = write(fd, data, size);
if (s < 0) { if (s < 0) {
fprintf(stderr, "Failed to write\n"); DEBUG_WARN("Failed to write\n");
exit(-2); return(-2);
} }
return size; return size;
@ -170,12 +170,12 @@ int platform_buffer_read(uint8_t *data, int maxsize)
ret = select(fd + 1, &rset, NULL, NULL, &tv); ret = select(fd + 1, &rset, NULL, NULL, &tv);
if (ret < 0) { if (ret < 0) {
fprintf(stderr,"Failed on select\n"); DEBUG_WARN("Failed on select\n");
exit(-4); return(-3);
} }
if(ret == 0) { if(ret == 0) {
fprintf(stderr,"Timeout on read RESP\n"); DEBUG_WARN("Timeout on read RESP\n");
exit(-3); return(-4);
} }
s = read(fd, c, 1); s = read(fd, c, 1);
@ -187,25 +187,24 @@ int platform_buffer_read(uint8_t *data, int maxsize)
FD_SET(fd, &rset); FD_SET(fd, &rset);
ret = select(fd + 1, &rset, NULL, NULL, &tv); ret = select(fd + 1, &rset, NULL, NULL, &tv);
if (ret < 0) { if (ret < 0) {
fprintf(stderr,"Failed on select\n"); DEBUG_WARN("Failed on select\n");
exit(-4); exit(-4);
} }
if(ret == 0) { if(ret == 0) {
fprintf(stderr,"Timeout on read\n"); DEBUG_WARN("Timeout on read\n");
exit(-3); return(-5);
} }
s = read(fd, c, 1); s = read(fd, c, 1);
if (*c==REMOTE_EOM) { if (*c==REMOTE_EOM) {
*c = 0; *c = 0;
if (cl_debuglevel) DEBUG_WIRE(" %s\n",data);
printf(" %s\n",data);
return (c - data); return (c - data);
} else { } else {
c++; c++;
} }
}while ((s >= 0) && ((c - data) < maxsize)); }while ((s >= 0) && ((c - data) < maxsize));
fprintf(stderr,"Failed to read\n"); DEBUG_WARN("Failed to read\n");
exit(-3); return(-6);
return 0; return 0;
} }

View File

@ -29,7 +29,7 @@ int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial)
{ {
(void) serial; /* FIXME: Does Windows allow open with USB serial no? */ (void) serial; /* FIXME: Does Windows allow open with USB serial no? */
if (!cl_opts->opt_device) { if (!cl_opts->opt_device) {
fprintf(stderr,"Specify the serial device to use!\n"); DEBUG_WARN("Specify the serial device to use!\n");
return -1; return -1;
} }
char device[256]; char device[256];
@ -48,19 +48,19 @@ int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial)
0, // Non Overlapped I/O 0, // Non Overlapped I/O
NULL); // Null for Comm Devices} NULL); // Null for Comm Devices}
if (hComm == INVALID_HANDLE_VALUE) { if (hComm == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Could not open %s: %ld\n", device, DEBUG_WARN("Could not open %s: %ld\n", device,
GetLastError()); GetLastError());
return -1; return -1;
} }
DCB dcbSerialParams; DCB dcbSerialParams;
dcbSerialParams.DCBlength = sizeof(dcbSerialParams); dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (!GetCommState(hComm, &dcbSerialParams)) { if (!GetCommState(hComm, &dcbSerialParams)) {
fprintf(stderr, "GetCommState failed %ld\n", GetLastError()); DEBUG_WARN("GetCommState failed %ld\n", GetLastError());
return -1; return -1;
} }
dcbSerialParams.ByteSize = 8; dcbSerialParams.ByteSize = 8;
if (!SetCommState(hComm, &dcbSerialParams)) { if (!SetCommState(hComm, &dcbSerialParams)) {
fprintf(stderr, "SetCommState failed %ld\n", GetLastError()); DEBUG_WARN("SetCommState failed %ld\n", GetLastError());
return -1; return -1;
} }
COMMTIMEOUTS timeouts = {0}; COMMTIMEOUTS timeouts = {0};
@ -70,7 +70,7 @@ int serial_open(BMP_CL_OPTIONS_t *cl_opts, char * serial)
timeouts.WriteTotalTimeoutConstant = 10; timeouts.WriteTotalTimeoutConstant = 10;
timeouts.WriteTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hComm, &timeouts)) { if (!SetCommTimeouts(hComm, &timeouts)) {
fprintf(stderr, "SetCommTimeouts failed %ld\n", GetLastError()); DEBUG_WARN("SetCommTimeouts failed %ld\n", GetLastError());
return -1; return -1;
} }
return 0; return 0;
@ -83,14 +83,13 @@ void serial_close(void)
int platform_buffer_write(const uint8_t *data, int size) int platform_buffer_write(const uint8_t *data, int size)
{ {
if (cl_debuglevel) DEBUG_WIRE("%s\n",data);
printf("%s\n",data);
int s = 0; int s = 0;
do { do {
DWORD written; DWORD written;
if (!WriteFile(hComm, data + s, size - s, &written, NULL)) { if (!WriteFile(hComm, data + s, size - s, &written, NULL)) {
fprintf(stderr, "Serial write failed %ld, written %d\n", DEBUG_WARN("Serial write failed %ld, written %d\n",
GetLastError(), s); GetLastError(), s);
return -1; return -1;
} }
@ -106,34 +105,32 @@ int platform_buffer_read(uint8_t *data, int maxsize)
uint32_t endTime = platform_time_ms() + RESP_TIMEOUT; uint32_t endTime = platform_time_ms() + RESP_TIMEOUT;
do { do {
if (!ReadFile(hComm, &response, 1, &s, NULL)) { if (!ReadFile(hComm, &response, 1, &s, NULL)) {
fprintf(stderr,"ERROR on read RESP\n"); DEBUG_WARN("ERROR on read RESP\n");
exit(-3); exit(-3);
} }
if (platform_time_ms() > endTime) { if (platform_time_ms() > endTime) {
fprintf(stderr,"Timeout on read RESP\n"); DEBUG_WARN("Timeout on read RESP\n");
exit(-4); exit(-4);
} }
} while (response != REMOTE_RESP); } while (response != REMOTE_RESP);
uint8_t *c = data; uint8_t *c = data;
do { do {
if (!ReadFile(hComm, c, 1, &s, NULL)) { if (!ReadFile(hComm, c, 1, &s, NULL)) {
fprintf(stderr,"Error on read\n"); DEBUG_WARN("Error on read\n");
exit(-3); exit(-3);
} }
if (s > 0 ) { if (s > 0 ) {
if (cl_debuglevel) DEBUG_WIRE("%c", *c);
printf("%c", *c);
if (*c == REMOTE_EOM) { if (*c == REMOTE_EOM) {
*c = 0; *c = 0;
if (cl_debuglevel) DEBUG_WIRE("\n");
printf("\n");
return (c - data); return (c - data);
} else { } else {
c++; c++;
} }
} }
} while (((c - data) < maxsize) && (platform_time_ms() < endTime)); } while (((c - data) < maxsize) && (platform_time_ms() < endTime));
fprintf(stderr,"Failed to read EOM at %d\n", DEBUG_WARN("Failed to read EOM at %d\n",
platform_time_ms() - startTime); platform_time_ms() - startTime);
exit(-3); exit(-3);
return 0; return 0;

View File

@ -36,6 +36,8 @@
#ifdef ENABLE_DEBUG #ifdef ENABLE_DEBUG
# define PLATFORM_HAS_DEBUG # define PLATFORM_HAS_DEBUG
# define USBUART_DEBUG # define USBUART_DEBUG
extern bool debug_bmp;
int usbuart_debug_write(const char *buf, size_t len);
#endif #endif
#define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware " FIRMWARE_VERSION ")"
@ -118,14 +120,6 @@
#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ #define USBUSART_TIM_IRQ NVIC_TIM4_IRQ
#define USBUSART_TIM_ISR tim4_isr #define USBUSART_TIM_ISR tim4_isr
#ifdef ENABLE_DEBUG
extern bool debug_bmp;
int usbuart_debug_write(const char *buf, size_t len);
# define DEBUG printf
#else
# define DEBUG(...)
#endif
/* On F103, only USART1 is on AHB2 and can reach 4.5 MBaud at 72 MHz.*/ /* On F103, only USART1 is on AHB2 and can reach 4.5 MBaud at 72 MHz.*/
#define SWO_UART USART1 #define SWO_UART USART1
#define SWO_UART_DR USART1_DR #define SWO_UART_DR USART1_DR

View File

@ -33,6 +33,8 @@
#ifdef ENABLE_DEBUG #ifdef ENABLE_DEBUG
# define PLATFORM_HAS_DEBUG # define PLATFORM_HAS_DEBUG
# define USBUART_DEBUG # define USBUART_DEBUG
extern bool debug_bmp;
int usbuart_debug_write(const char *buf, size_t len);
#endif #endif
#define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware " FIRMWARE_VERSION ")"
@ -122,14 +124,6 @@
#define TRACE_IC_IN TIM_IC_IN_TI2 #define TRACE_IC_IN TIM_IC_IN_TI2
#define TRACE_TRIG_IN TIM_SMCR_TS_IT1FP2 #define TRACE_TRIG_IN TIM_SMCR_TS_IT1FP2
#ifdef ENABLE_DEBUG
extern bool debug_bmp;
int usbuart_debug_write(const char *buf, size_t len);
# define DEBUG printf
#else
# define DEBUG(...)
#endif
/* On F103, only USART1 is on AHB2 and can reach 4.5 MBaud at 72 MHz. /* On F103, only USART1 is on AHB2 and can reach 4.5 MBaud at 72 MHz.
* USART1 is already used. sp maximum speed is 2.25 MBaud. */ * USART1 is already used. sp maximum speed is 2.25 MBaud. */
#define SWO_UART USART2 #define SWO_UART USART2

View File

@ -25,7 +25,11 @@
#include "jtagtap.h" #include "jtagtap.h"
#include "gdb_if.h" #include "gdb_if.h"
#include "version.h" #include "version.h"
#include "exception.h"
#include <stdarg.h> #include <stdarg.h>
#include "target/adiv5.h"
#include "target.h"
#include "hex_utils.h"
#define NTOH(x) ((x<=9)?x+'0':'a'+x-10) #define NTOH(x) ((x<=9)?x+'0':'a'+x-10)
@ -57,6 +61,30 @@ uint64_t remotehston(uint32_t limit, char *s)
} }
#if PC_HOSTED == 0 #if PC_HOSTED == 0
static void _send_buf(uint8_t* buffer, size_t len)
{
uint8_t* p = buffer;
char hex[2];
do {
hexify(hex, (const void*)p++, 1);
gdb_if_putchar(hex[0], 0);
gdb_if_putchar(hex[1], 0);
} while (p<(buffer+len));
}
static void _respond_buf(char respCode, uint8_t* buffer, size_t len)
{
gdb_if_putchar(REMOTE_RESP, 0);
gdb_if_putchar(respCode, 0);
_send_buf(buffer, len);
gdb_if_putchar(REMOTE_EOM, 1);
}
static void _respond(char respCode, uint64_t param) static void _respond(char respCode, uint64_t param)
/* Send response to far end */ /* Send response to far end */
@ -97,6 +125,16 @@ static void _respondS(char respCode, const char *s)
gdb_if_putchar(REMOTE_EOM,1); gdb_if_putchar(REMOTE_EOM,1);
} }
static ADIv5_DP_t remote_dp = {
.dp_read = firmware_swdp_read,
.ap_read = firmware_ap_read,
.ap_write = firmware_ap_write,
.mem_read = firmware_mem_read,
.mem_write_sized = firmware_mem_write_sized,
.low_access = firmware_swdp_low_access,
};
void remotePacketProcessSWD(uint8_t i, char *packet) void remotePacketProcessSWD(uint8_t i, char *packet)
{ {
uint8_t ticks; uint8_t ticks;
@ -155,6 +193,8 @@ void remotePacketProcessJTAG(uint8_t i, char *packet)
switch (packet[1]) { switch (packet[1]) {
case REMOTE_INIT: /* = initialise ================================= */ case REMOTE_INIT: /* = initialise ================================= */
jtagtap_init(); jtagtap_init();
remote_dp.dp_read = fw_adiv5_jtagdp_read;
remote_dp.low_access = fw_adiv5_jtagdp_low_access;
_respond(REMOTE_RESP_OK, 0); _respond(REMOTE_RESP_OK, 0);
break; break;
@ -255,6 +295,104 @@ void remotePacketProcessGEN(uint8_t i, char *packet)
} }
} }
void remotePacketProcessHL(uint8_t i, char *packet)
{
(void)i;
SET_IDLE_STATE(0);
ADIv5_AP_t remote_ap;
/* Re-use packet buffer. Align to DWORD! */
void *src = (void *)(((uint32_t)packet + 7) & ~7);
char index = packet[1];
packet += 2;
remote_ap.apsel = remotehston(2, packet);
remote_ap.dp = &remote_dp;
switch (index) {
case REMOTE_DP_READ:
packet += 2;
uint16_t addr16 = remotehston(4, packet);
uint32_t data = adiv5_dp_read(&remote_dp, addr16);
_respond_buf(REMOTE_RESP_OK, (uint8_t*)&data, 4);
break;
case REMOTE_LOW_ACCESS:
packet += 2;
addr16 = remotehston(4, packet);
packet += 4;
uint32_t value = remotehston(8, packet);
data = remote_dp.low_access(&remote_dp, remote_ap.apsel, addr16, value);
_respond_buf(REMOTE_RESP_OK, (uint8_t*)&data, 4);
break;
case REMOTE_AP_READ:
packet += 2;
addr16 = remotehston(4, packet);
data = adiv5_ap_read(&remote_ap, addr16);
_respond_buf(REMOTE_RESP_OK, (uint8_t*)&data, 4);
break;
case REMOTE_AP_WRITE:
packet += 2;
addr16 = remotehston(4, packet);
packet += 4;
value = remotehston(8, packet);
adiv5_ap_write(&remote_ap, addr16, value);
_respond(REMOTE_RESP_OK, 0);
break;
case REMOTE_AP_MEM_READ:
packet += 2;
remote_ap.csw = remotehston(8, packet);
packet += 6;
/*fall through*/
case REMOTE_MEM_READ:
packet += 2;
uint32_t address = remotehston(8, packet);
packet += 8;
uint32_t count = remotehston(8, packet);
packet += 8;
adiv5_mem_read(&remote_ap, src, address, count);
if (remote_ap.dp->fault == 0) {
_respond_buf(REMOTE_RESP_OK, src, count);
break;
}
_respond(REMOTE_RESP_ERR, 0);
remote_ap.dp->fault = 0;
break;
case REMOTE_AP_MEM_WRITE_SIZED:
packet += 2;
remote_ap.csw = remotehston(8, packet);
packet += 6;
/*fall through*/
case REMOTE_MEM_WRITE_SIZED:
packet += 2;
enum align align = remotehston(2, packet);
packet += 2;
uint32_t dest = remotehston(8, packet);
packet+= 8;
size_t len = remotehston(8, packet);
packet += 8;
if (len & ((1 << align) - 1)) {
/* len and align do not fit*/
_respond(REMOTE_RESP_ERR, 0);
break;
}
/* Read as stream of hexified bytes*/
unhexify(src, packet, len);
adiv5_mem_write_sized(&remote_ap, dest, src, len, align);
if (remote_ap.dp->fault) {
/* Errors handles on hosted side.*/
_respond(REMOTE_RESP_ERR, 0);
remote_ap.dp->fault = 0;
break;
}
_respond_buf(REMOTE_RESP_OK, src, len);
break;
default:
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
break;
}
SET_IDLE_STATE(1);
}
void remotePacketProcess(uint8_t i, char *packet) void remotePacketProcess(uint8_t i, char *packet)
{ {
switch (packet[0]) { switch (packet[0]) {
@ -270,6 +408,10 @@ void remotePacketProcess(uint8_t i, char *packet)
remotePacketProcessGEN(i,packet); remotePacketProcessGEN(i,packet);
break; break;
case REMOTE_HL_PACKET:
remotePacketProcessHL(i, packet);
break;
default: /* Oh dear, unrecognised, return an error */ default: /* Oh dear, unrecognised, return an error */
_respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED); _respond(REMOTE_RESP_ERR,REMOTE_ERROR_UNRECOGNISED);
break; break;

View File

@ -83,6 +83,18 @@
#define REMOTE_RESP_ERR 'E' #define REMOTE_RESP_ERR 'E'
#define REMOTE_RESP_NOTSUP 'N' #define REMOTE_RESP_NOTSUP 'N'
/* High level protocol elements */
#define REMOTE_HL_PACKET 'H'
#define REMOTE_DP_READ 'd'
#define REMOTE_LOW_ACCESS 'L'
#define REMOTE_AP_READ 'a'
#define REMOTE_AP_WRITE 'A'
#define REMOTE_AP_MEM_READ 'M'
#define REMOTE_MEM_READ 'h'
#define REMOTE_MEM_WRITE_SIZED 'H'
#define REMOTE_AP_MEM_WRITE_SIZED 'm'
/* Generic protocol elements */ /* Generic protocol elements */
#define REMOTE_GEN_PACKET 'G' #define REMOTE_GEN_PACKET 'G'
@ -125,6 +137,28 @@
#define REMOTE_JTAG_NEXT (char []){ REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_NEXT, \ #define REMOTE_JTAG_NEXT (char []){ REMOTE_SOM, REMOTE_JTAG_PACKET, REMOTE_NEXT, \
'%','c','%','c',REMOTE_EOM, 0 } '%','c','%','c',REMOTE_EOM, 0 }
/* HL protocol elements */
#define HEX '%', '0', '2', 'x'
#define HEX_U32(x) '%', '0', '8', 'x'
#define CHR(x) '%', 'c'
#define REMOTE_MEM_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_MEM_READ, \
HEX_U32(address), HEX_U32(count), REMOTE_EOM, 0 }
#define REMOTE_DP_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_DP_READ, \
'f', 'f','%', '0', '4', 'x', REMOTE_EOM, 0 }
#define REMOTE_LOW_ACCESS_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_LOW_ACCESS, \
'%','0', '2', 'x', '%', '0', '4', 'x', HEX_U32(csw), REMOTE_EOM, 0 }
#define REMOTE_AP_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_READ, \
'%','0','2','x', '%', '0', '4', 'x', REMOTE_EOM, 0 }
#define REMOTE_AP_WRITE_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_WRITE, \
'%','0','2','x', '%', '0', '4', 'x', HEX_U32(csw), REMOTE_EOM, 0 }
#define REMOTE_AP_MEM_READ_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_MEM_READ, \
'%','0','2','x',HEX_U32(csw), HEX_U32(address), HEX_U32(count), REMOTE_EOM, 0 }
#define REMOTE_AP_MEM_WRITE_SIZED_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_MEM_WRITE_SIZED, \
'%', '0', '2', 'x', HEX_U32(csw), '%', '0', '2', 'x', HEX_U32(address), HEX_U32(count), 0}
#define REMOTE_MEM_WRITE_SIZED_STR (char []){ REMOTE_SOM, REMOTE_HL_PACKET, REMOTE_AP_MEM_WRITE_SIZED, \
'%','0','2','x', HEX_U32(address), HEX_U32(count), 0}
uint64_t remotehston(uint32_t limit, char *s); uint64_t remotehston(uint32_t limit, char *s);
void remotePacketProcess(uint8_t i, char *packet); void remotePacketProcess(uint8_t i, char *packet);

View File

@ -3,6 +3,8 @@
* *
* Copyright (C) 2015 Black Sphere Technologies Ltd. * Copyright (C) 2015 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz> * Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2018 - 2020 Uwe Bonnes
* (bon@elektron.ikp.physik.tu-darmstadt.de)
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -241,11 +243,6 @@ void adiv5_ap_unref(ADIv5_AP_t *ap)
} }
} }
void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
{
dp->low_access(dp, ADIV5_LOW_WRITE, addr, value);
}
static uint32_t adiv5_mem_read32(ADIv5_AP_t *ap, uint32_t addr) static uint32_t adiv5_mem_read32(ADIv5_AP_t *ap, uint32_t addr)
{ {
uint32_t ret; uint32_t ret;
@ -285,13 +282,13 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
#endif #endif
if (adiv5_dp_error(ap->dp)) { if (adiv5_dp_error(ap->dp)) {
DEBUG("%sFault reading ID registers\n", indent); DEBUG_WARN("%sFault reading ID registers\n", indent);
return false; return false;
} }
/* CIDR preamble sanity check */ /* CIDR preamble sanity check */
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) { if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) {
DEBUG("%s%d 0x%08" PRIx32": 0x%08" PRIx32 DEBUG_WARN("%s%d 0x%08" PRIx32": 0x%08" PRIx32
" <- does not match preamble (0x%X)\n", " <- does not match preamble (0x%X)\n",
indent + 1, num_entry, addr, cidr, CID_PREAMBLE); indent + 1, num_entry, addr, cidr, CID_PREAMBLE);
return false; return false;
@ -308,19 +305,19 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
ADIV5_ROM_MEMTYPE_SYSMEM; ADIV5_ROM_MEMTYPE_SYSMEM;
if (adiv5_dp_error(ap->dp)) { if (adiv5_dp_error(ap->dp)) {
DEBUG("Fault reading ROM table entry\n"); DEBUG_WARN("Fault reading ROM table entry\n");
} }
DEBUG("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%" PRIx32 ", PIDR 0x%02" DEBUG_INFO("ROM: Table BASE=0x%" PRIx32 " SYSMEM=0x%" PRIx32
PRIx32 "%08" PRIx32 "\n", addr, memtype, (uint32_t)(pidr >> 32), ", PIDR 0x%02" PRIx32 "%08" PRIx32 "\n", addr,
(uint32_t)pidr); memtype, (uint32_t)(pidr >> 32), (uint32_t)pidr);
#endif #endif
for (int i = 0; i < 960; i++) { for (int i = 0; i < 960; i++) {
adiv5_dp_error(ap->dp); adiv5_dp_error(ap->dp);
uint32_t entry = adiv5_mem_read32(ap, addr + i*4); uint32_t entry = adiv5_mem_read32(ap, addr + i*4);
if (adiv5_dp_error(ap->dp)) { if (adiv5_dp_error(ap->dp)) {
DEBUG("%sFault reading ROM table entry %d\n", indent, i); DEBUG_WARN("%sFault reading ROM table entry %d\n", indent, i);
break; break;
} }
@ -328,7 +325,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
break; break;
if (!(entry & ADIV5_ROM_ROMENTRY_PRESENT)) { if (!(entry & ADIV5_ROM_ROMENTRY_PRESENT)) {
DEBUG("%s%d Entry 0x%" PRIx32 " -> Not present\n", indent, DEBUG_INFO("%s%d Entry 0x%" PRIx32 " -> Not present\n", indent,
i, entry); i, entry);
continue; continue;
} }
@ -338,13 +335,13 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET), ap, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET),
recursion + 1, i); recursion + 1, i);
} }
DEBUG("%sROM: Table END\n", indent); DEBUG_INFO("%sROM: Table END\n", indent);
} else { } else {
/* Check if the component was designed by ARM, we currently do not support, /* Check if the component was designed by ARM, we currently do not support,
* any components by other designers. * any components by other designers.
*/ */
if ((pidr & ~(PIDR_REV_MASK | PIDR_PN_MASK)) != PIDR_ARM_BITS) { if ((pidr & ~(PIDR_REV_MASK | PIDR_PN_MASK)) != PIDR_ARM_BITS) {
DEBUG("%s0x%" PRIx32 ": 0x%02" PRIx32 "%08" PRIx32 DEBUG_WARN("%s0x%" PRIx32 ": 0x%02" PRIx32 "%08" PRIx32
" <- does not match ARM JEP-106\n", " <- does not match ARM JEP-106\n",
indent, addr, (uint32_t)(pidr >> 32), (uint32_t)pidr); indent, addr, (uint32_t)(pidr >> 32), (uint32_t)pidr);
return false; return false;
@ -358,7 +355,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
int i; int i;
for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) { for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) {
if (pidr_pn_bits[i].part_number == part_number) { if (pidr_pn_bits[i].part_number == part_number) {
DEBUG("%s%d 0x%" PRIx32 ": %s - %s %s (PIDR = 0x%02" PRIx32 DEBUG_INFO("%s%d 0x%" PRIx32 ": %s - %s %s (PIDR = 0x%02" PRIx32
"%08" PRIx32 ")", "%08" PRIx32 ")",
indent + 1, num_entry, addr, indent + 1, num_entry, addr,
cidc_debug_strings[cid_class], cidc_debug_strings[cid_class],
@ -369,29 +366,30 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
*/ */
if ((pidr_pn_bits[i].cidc != cidc_unknown) && if ((pidr_pn_bits[i].cidc != cidc_unknown) &&
(cid_class != pidr_pn_bits[i].cidc)) { (cid_class != pidr_pn_bits[i].cidc)) {
DEBUG("%sWARNING: \"%s\" !match expected \"%s\"\n", indent + 1, DEBUG_WARN("%sWARNING: \"%s\" !match expected \"%s\"\n",
indent + 1,
cidc_debug_strings[cid_class], cidc_debug_strings[cid_class],
cidc_debug_strings[pidr_pn_bits[i].cidc]); cidc_debug_strings[pidr_pn_bits[i].cidc]);
} }
res = true; res = true;
switch (pidr_pn_bits[i].arch) { switch (pidr_pn_bits[i].arch) {
case aa_cortexm: case aa_cortexm:
DEBUG("%s-> cortexm_probe\n", indent + 1); DEBUG_INFO("%s-> cortexm_probe\n", indent + 1);
cortexm_probe(ap, false); cortexm_probe(ap, false);
break; break;
case aa_cortexa: case aa_cortexa:
DEBUG("\n -> cortexa_probe\n"); DEBUG_INFO("\n -> cortexa_probe\n");
cortexa_probe(ap, addr); cortexa_probe(ap, addr);
break; break;
default: default:
DEBUG("\n"); DEBUG_INFO("\n");
break; break;
} }
break; break;
} }
} }
if (pidr_pn_bits[i].arch == aa_end) { if (pidr_pn_bits[i].arch == aa_end) {
DEBUG("%s0x%" PRIx32 ": %s - Unknown (PIDR = 0x%02" PRIx32 DEBUG_WARN("%s0x%" PRIx32 ": %s - Unknown (PIDR = 0x%02" PRIx32
"%08" PRIx32 ")\n", "%08" PRIx32 ")\n",
indent, addr, cidc_debug_strings[cid_class], indent, addr, cidc_debug_strings[cid_class],
(uint32_t)(pidr >> 32), (uint32_t)pidr); (uint32_t)(pidr >> 32), (uint32_t)pidr);
@ -415,7 +413,7 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
/* It's valid to so create a heap copy */ /* It's valid to so create a heap copy */
ap = malloc(sizeof(*ap)); ap = malloc(sizeof(*ap));
if (!ap) { /* malloc failed: heap exhaustion */ if (!ap) { /* malloc failed: heap exhaustion */
DEBUG("malloc: failed in %s\n", __func__); DEBUG_WARN("malloc: failed in %s\n", __func__);
return NULL; return NULL;
} }
@ -427,23 +425,18 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK);
if (ap->csw & ADIV5_AP_CSW_TRINPROG) { if (ap->csw & ADIV5_AP_CSW_TRINPROG) {
DEBUG("AP transaction in progress. Target may not be usable.\n"); DEBUG_WARN("AP transaction in progress. Target may not be usable.\n");
ap->csw &= ~ADIV5_AP_CSW_TRINPROG; ap->csw &= ~ADIV5_AP_CSW_TRINPROG;
} }
#if defined(ENABLE_DEBUG) #if defined(ENABLE_DEBUG)
uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG); uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG);
DEBUG("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08"PRIx32" CSW=%08"PRIx32"\n", DEBUG_INFO("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08" PRIx32
apsel, ap->idr, cfg, ap->base, ap->csw); " CSW=%08"PRIx32"\n", apsel, ap->idr, cfg, ap->base, ap->csw);
#endif #endif
return ap; 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) void adiv5_dp_init(ADIv5_DP_t *dp)
{ {
volatile bool probed = false; volatile bool probed = false;
@ -452,25 +445,25 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
#if PC_HOSTED == 1 #if PC_HOSTED == 1
platform_adiv5_dp_defaults(dp); platform_adiv5_dp_defaults(dp);
if (!dp->ap_write) if (!dp->ap_write)
dp->ap_write = ap_write; dp->ap_write = firmware_ap_write;
if (!dp->ap_read) if (!dp->ap_read)
dp->ap_read = ap_read; dp->ap_read = firmware_ap_read;
if (!dp->mem_read) if (!dp->mem_read)
dp->mem_read = mem_read; dp->mem_read = firmware_mem_read;
if (!dp->mem_write_sized) if (!dp->mem_write_sized)
dp->mem_write_sized = mem_write_sized; dp->mem_write_sized = firmware_mem_write_sized;
#else #else
dp->ap_write = ap_write; dp->ap_write = firmware_ap_write;
dp->ap_read = ap_read; dp->ap_read = firmware_ap_read;
dp->mem_read = mem_read; dp->mem_read = firmware_mem_read;
dp->mem_write_sized = mem_write_sized; dp->mem_write_sized = firmware_mem_write_sized;
#endif #endif
volatile struct exception e; volatile struct exception e;
TRY_CATCH (e, EXCEPTION_TIMEOUT) { TRY_CATCH (e, EXCEPTION_TIMEOUT) {
ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
} }
if (e.type) { if (e.type) {
DEBUG("DP not responding! Trying abort sequence...\n"); DEBUG_WARN("DP not responding! Trying abort sequence...\n");
adiv5_dp_abort(dp, ADIV5_DP_ABORT_DAPABORT); adiv5_dp_abort(dp, ADIV5_DP_ABORT_DAPABORT);
ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
} }
@ -488,29 +481,29 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
* correctly on STM32. CDBGRSTACK is never asserted, and we * correctly on STM32. CDBGRSTACK is never asserted, and we
* just wait forever. This scenario is described in B2.4.1 * just wait forever. This scenario is described in B2.4.1
* so we have a timeout mechanism in addition to the sensing one. * so we have a timeout mechanism in addition to the sensing one.
*/ *
* Write request for debug reset */
/* Write request for debug reset */
adiv5_dp_write(dp, ADIV5_DP_CTRLSTAT, adiv5_dp_write(dp, ADIV5_DP_CTRLSTAT,
ctrlstat |= ADIV5_DP_CTRLSTAT_CDBGRSTREQ); ctrlstat |= ADIV5_DP_CTRLSTAT_CDBGRSTREQ);
platform_timeout timeout; platform_timeout timeout;
platform_timeout_set(&timeout,200); platform_timeout_set(&timeout, 101);
/* Wait for acknowledge */
while ((!platform_timeout_is_expired(&timeout)) &&
(!((ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT)) & ADIV5_DP_CTRLSTAT_CDBGRSTACK))
);
/* Write request for debug reset release */ /* Write request for debug reset release */
adiv5_dp_write(dp, ADIV5_DP_CTRLSTAT, adiv5_dp_write(dp, ADIV5_DP_CTRLSTAT,
ctrlstat &= ~ADIV5_DP_CTRLSTAT_CDBGRSTREQ); ctrlstat &= ~ADIV5_DP_CTRLSTAT_CDBGRSTREQ);
platform_timeout_set(&timeout,200);
/* Wait for acknowledge */ /* Wait for acknowledge */
while ((!platform_timeout_is_expired(&timeout)) && while(1) {
(adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT) & ADIV5_DP_CTRLSTAT_CDBGRSTACK) platform_delay(20);
); ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
DEBUG("RESET_SEQ %s\n", (platform_timeout_is_expired(&timeout)) ? "failed": "succeeded"); if (ctrlstat & ADIV5_DP_CTRLSTAT_CDBGRSTACK) {
DEBUG_INFO("RESET_SEQ succeeded.\n");
break;
}
if (platform_timeout_is_expired(&timeout)) {
DEBUG_INFO("RESET_SEQ failed\n");
break;
}
}
uint32_t dp_idcode = adiv5_dp_read(dp, ADIV5_DP_IDCODE); uint32_t dp_idcode = adiv5_dp_read(dp, ADIV5_DP_IDCODE);
if ((dp_idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { if ((dp_idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) {
@ -518,7 +511,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
adiv5_dp_write(dp, ADIV5_DP_SELECT, ADIV5_DP_BANK2); adiv5_dp_write(dp, ADIV5_DP_SELECT, ADIV5_DP_BANK2);
dp->targetid = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); dp->targetid = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
adiv5_dp_write(dp, ADIV5_DP_SELECT, ADIV5_DP_BANK0); adiv5_dp_write(dp, ADIV5_DP_SELECT, ADIV5_DP_BANK0);
DEBUG("TARGETID %08" PRIx32 "\n", dp->targetid); DEBUG_INFO("TARGETID %08" PRIx32 "\n", dp->targetid);
} }
/* Probe for APs on this DP */ /* Probe for APs on this DP */
uint32_t last_base = 0; uint32_t last_base = 0;
@ -543,7 +536,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
continue; continue;
} }
if (ap->base == last_base) { if (ap->base == last_base) {
DEBUG("AP %d: Duplicate base\n", i); DEBUG_WARN("AP %d: Duplicate base\n", i);
#if PC_HOSTED == 1 #if PC_HOSTED == 1
if (dp->ap_cleanup) if (dp->ap_cleanup)
dp->ap_cleanup(i); dp->ap_cleanup(i);
@ -579,7 +572,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
/* The rest should only be added after checking ROM table */ /* The rest should only be added after checking ROM table */
probed |= adiv5_component_probe(ap, ap->base, 0, 0); probed |= adiv5_component_probe(ap, ap->base, 0, 0);
if (!probed && (dp->idcode & 0xfff) == 0x477) { if (!probed && (dp->idcode & 0xfff) == 0x477) {
DEBUG("-> cortexm_probe forced\n"); DEBUG_INFO("-> cortexm_probe forced\n");
cortexm_probe(ap, true); cortexm_probe(ap, true);
probed = true; probed = true;
} }
@ -629,7 +622,7 @@ void * extract(void *dest, uint32_t src, uint32_t val, enum align align)
return (uint8_t *)dest + (1 << align); return (uint8_t *)dest + (1 << align);
} }
static void mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len) void firmware_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
{ {
uint32_t tmp; uint32_t tmp;
uint32_t osrc = src; uint32_t osrc = src;
@ -659,7 +652,7 @@ static void mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len)
extract(dest, src, tmp, align); extract(dest, src, tmp, align);
} }
static void mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src, void firmware_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align) size_t len, enum align align)
{ {
uint32_t odest = dest; uint32_t odest = dest;
@ -694,14 +687,14 @@ static void mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
} }
} }
static void ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value) void firmware_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value)
{ {
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,
((uint32_t)ap->apsel << 24)|(addr & 0xF0)); ((uint32_t)ap->apsel << 24)|(addr & 0xF0));
adiv5_dp_write(ap->dp, addr, value); adiv5_dp_write(ap->dp, addr, value);
} }
static uint32_t ap_read(ADIv5_AP_t *ap, uint16_t addr) uint32_t firmware_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{ {
uint32_t ret; uint32_t ret;
adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, adiv5_dp_write(ap->dp, ADIV5_DP_SELECT,

View File

@ -172,6 +172,18 @@ typedef struct ADIv5_DP_s {
#endif #endif
} ADIv5_DP_t; } ADIv5_DP_t;
struct ADIv5_AP_s {
int refcnt;
ADIv5_DP_t *dp;
uint8_t apsel;
uint32_t idr;
uint32_t base;
uint32_t csw;
};
#if PC_HOSTED == 0
static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr) static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr)
{ {
return dp->dp_read(dp, addr); return dp->dp_read(dp, addr);
@ -193,17 +205,6 @@ static inline void adiv5_dp_abort(struct ADIv5_DP_s *dp, uint32_t abort)
return dp->abort(dp, abort); return dp->abort(dp, abort);
} }
struct ADIv5_AP_s {
int refcnt;
ADIv5_DP_t *dp;
uint8_t apsel;
uint32_t idr;
uint32_t base;
uint32_t csw;
};
static inline uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr) static inline uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr)
{ {
return ap->dp->ap_read(ap, addr); return ap->dp->ap_read(ap, addr);
@ -219,25 +220,60 @@ static inline void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src,
{ {
return ap->dp->mem_read(ap, dest, src, 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) 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); return ap->dp->mem_write_sized(ap, dest, src, len, align);
} }
static inline void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value)
{
dp->low_access(dp, ADIV5_LOW_WRITE, addr, value);
}
#else
uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr);
uint32_t adiv5_dp_error(ADIv5_DP_t *dp);
uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
void adiv5_dp_abort(struct ADIv5_DP_s *dp, uint32_t abort);
uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr);
void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t 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);
void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value); void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value);
#endif
void adiv5_dp_init(ADIv5_DP_t *dp); void adiv5_dp_init(ADIv5_DP_t *dp);
void platform_adiv5_dp_defaults(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); ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel);
void adiv5_ap_ref(ADIv5_AP_t *ap); void adiv5_ap_ref(ADIv5_AP_t *ap);
void adiv5_ap_unref(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);
void adiv5_jtag_dp_handler(jtag_dev_t *dev); void adiv5_jtag_dp_handler(jtag_dev_t *dev);
int platform_jtag_dp_init(ADIv5_DP_t *dp); int platform_jtag_dp_init(ADIv5_DP_t *dp);
void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len); void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len);
uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr); 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); void * extract(void *dest, uint32_t src, uint32_t val, enum align align);
void firmware_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align);
void firmware_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src,
size_t len);
void firmware_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value);
uint32_t firmware_ap_read(ADIv5_AP_t *ap, uint16_t addr);
uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr);
uint32_t fw_adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr);
uint32_t firmware_swdp_error(ADIv5_DP_t *dp);
void firmware_swdp_abort(ADIv5_DP_t *dp, uint32_t abort);
#endif #endif

View File

@ -37,49 +37,44 @@
#define IR_DPACC 0xA #define IR_DPACC 0xA
#define IR_APACC 0xB #define IR_APACC 0xB
static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr);
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp); static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp);
static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort); static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort);
void adiv5_jtag_dp_handler(jtag_dev_t *dev) void adiv5_jtag_dp_handler(jtag_dev_t *dev)
{ {
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dp) { /* calloc failed: heap exhaustion */ if (!dp) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
dp->dev = dev; dp->dev = dev;
if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) { if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) {
dp->idcode = dev->idcode; dp->idcode = dev->idcode;
dp->dp_read = adiv5_jtagdp_read; dp->dp_read = fw_adiv5_jtagdp_read;
dp->error = adiv5_jtagdp_error; dp->error = adiv5_jtagdp_error;
dp->low_access = adiv5_jtagdp_low_access; dp->low_access = fw_adiv5_jtagdp_low_access;
dp->abort = adiv5_jtagdp_abort; dp->abort = adiv5_jtagdp_abort;
} }
adiv5_dp_init(dp); adiv5_dp_init(dp);
} }
static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr) uint32_t fw_adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr)
{ {
adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, addr, 0); fw_adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, addr, 0);
return adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, return fw_adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ,
ADIV5_DP_RDBUFF, 0); ADIV5_DP_RDBUFF, 0);
} }
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp) static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp)
{ {
adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_CTRLSTAT, 0); fw_adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_CTRLSTAT, 0);
return adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE, return fw_adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE,
ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32; ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32;
} }
static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value) uint16_t addr, uint32_t value)
{ {
bool APnDP = addr & ADIV5_APnDP; bool APnDP = addr & ADIV5_APnDP;

View File

@ -33,15 +33,6 @@
#define SWDP_ACK_WAIT 0x02 #define SWDP_ACK_WAIT 0x02
#define SWDP_ACK_FAULT 0x04 #define SWDP_ACK_FAULT 0x04
static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr);
static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp);
static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value);
static void adiv5_swdp_abort(ADIv5_DP_t *dp, uint32_t abort);
int adiv5_swdp_scan(void) int adiv5_swdp_scan(void)
{ {
uint32_t ack; uint32_t ack;
@ -49,7 +40,7 @@ int adiv5_swdp_scan(void)
target_list_free(); target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (!dp) { /* calloc failed: heap exhaustion */ if (!dp) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return -1; return -1;
} }
@ -75,38 +66,38 @@ int adiv5_swdp_scan(void)
swd_proc.swdptap_seq_out(0xA5, 8); swd_proc.swdptap_seq_out(0xA5, 8);
ack = swd_proc.swdptap_seq_in(3); ack = swd_proc.swdptap_seq_in(3);
if((ack != SWDP_ACK_OK) || swd_proc.swdptap_seq_in_parity(&dp->idcode, 32)) { if((ack != SWDP_ACK_OK) || swd_proc.swdptap_seq_in_parity(&dp->idcode, 32)) {
DEBUG("\n"); DEBUG_WARN("Read SW-DP IDCODE failed %1" PRIx32 "\n", ack);
free(dp); free(dp);
return -1; return -1;
} }
dp->dp_read = adiv5_swdp_read; dp->dp_read = firmware_swdp_read;
dp->error = adiv5_swdp_error; dp->error = firmware_swdp_error;
dp->low_access = adiv5_swdp_low_access; dp->low_access = firmware_swdp_low_access;
dp->abort = adiv5_swdp_abort; dp->abort = firmware_swdp_abort;
adiv5_swdp_error(dp); firmware_swdp_error(dp);
adiv5_dp_init(dp); adiv5_dp_init(dp);
return target_list?1:0; return target_list?1:0;
} }
static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr) uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr)
{ {
if (addr & ADIV5_APnDP) { if (addr & ADIV5_APnDP) {
adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0); adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
return adiv5_dp_low_access(dp, ADIV5_LOW_READ, return adiv5_dp_low_access(dp, ADIV5_LOW_READ,
ADIV5_DP_RDBUFF, 0); ADIV5_DP_RDBUFF, 0);
} else { } else {
return adiv5_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0); return firmware_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0);
} }
} }
static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) uint32_t firmware_swdp_error(ADIv5_DP_t *dp)
{ {
uint32_t err, clr = 0; uint32_t err, clr = 0;
err = adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) & err = firmware_swdp_read(dp, ADIV5_DP_CTRLSTAT) &
(ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP | (ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP |
ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR); ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR);
@ -125,7 +116,7 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp)
return err; return err;
} }
static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint16_t addr, uint32_t value) uint16_t addr, uint32_t value)
{ {
bool APnDP = addr & ADIV5_APnDP; bool APnDP = addr & ADIV5_APnDP;
@ -183,7 +174,7 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
return response; return response;
} }
static void adiv5_swdp_abort(ADIv5_DP_t *dp, uint32_t abort) void firmware_swdp_abort(ADIv5_DP_t *dp, uint32_t abort)
{ {
adiv5_dp_write(dp, ADIV5_DP_ABORT, abort); adiv5_dp_write(dp, ADIV5_DP_ABORT, abort);
} }

View File

@ -214,7 +214,7 @@ static uint32_t va_to_pa(target *t, uint32_t va)
if (par & 1) if (par & 1)
priv->mmu_fault = true; priv->mmu_fault = true;
uint32_t pa = (par & ~0xfff) | (va & 0xfff); uint32_t pa = (par & ~0xfff) | (va & 0xfff);
DEBUG("%s: VA = 0x%08"PRIx32", PAR = 0x%08"PRIx32", PA = 0x%08"PRIX32"\n", DEBUG_INFO("%s: VA = 0x%08"PRIx32", PAR = 0x%08"PRIx32", PA = 0x%08"PRIX32"\n",
__func__, va, par, pa); __func__, va, par, pa);
return pa; return pa;
} }
@ -333,7 +333,7 @@ bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base)
adiv5_ap_ref(apb); adiv5_ap_ref(apb);
struct cortexa_priv *priv = calloc(1, sizeof(*priv)); struct cortexa_priv *priv = calloc(1, sizeof(*priv));
if (!priv) { /* calloc failed: heap exhaustion */ if (!priv) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return false; return false;
} }
@ -388,7 +388,7 @@ bool cortexa_attach(target *t)
dbgdscr |= DBGDSCR_HDBGEN | DBGDSCR_ITREN; dbgdscr |= DBGDSCR_HDBGEN | DBGDSCR_ITREN;
dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK) | DBGDSCR_EXTDCCMODE_STALL; dbgdscr = (dbgdscr & ~DBGDSCR_EXTDCCMODE_MASK) | DBGDSCR_EXTDCCMODE_STALL;
apb_write(t, DBGDSCR, dbgdscr); apb_write(t, DBGDSCR, dbgdscr);
DEBUG("DBGDSCR = 0x%08"PRIx32"\n", dbgdscr); DEBUG_INFO("DBGDSCR = 0x%08"PRIx32"\n", dbgdscr);
target_halt_request(t); target_halt_request(t);
tries = 10; tries = 10;
@ -630,7 +630,7 @@ static enum target_halt_reason cortexa_halt_poll(target *t, target_addr *watch)
if (!(dbgdscr & DBGDSCR_HALTED)) /* Not halted */ if (!(dbgdscr & DBGDSCR_HALTED)) /* Not halted */
return TARGET_HALT_RUNNING; return TARGET_HALT_RUNNING;
DEBUG("%s: DBGDSCR = 0x%08"PRIx32"\n", __func__, dbgdscr); DEBUG_INFO("%s: DBGDSCR = 0x%08"PRIx32"\n", __func__, dbgdscr);
/* Reenable DBGITR */ /* Reenable DBGITR */
dbgdscr |= DBGDSCR_ITREN; dbgdscr |= DBGDSCR_ITREN;
apb_write(t, DBGDSCR, dbgdscr); apb_write(t, DBGDSCR, dbgdscr);
@ -657,7 +657,7 @@ void cortexa_halt_resume(target *t, bool step)
if (step) { if (step) {
uint32_t addr = priv->reg_cache.r[15]; uint32_t addr = priv->reg_cache.r[15];
uint32_t bas = bp_bas(addr, (priv->reg_cache.cpsr & CPSR_THUMB) ? 2 : 4); uint32_t bas = bp_bas(addr, (priv->reg_cache.cpsr & CPSR_THUMB) ? 2 : 4);
DEBUG("step 0x%08"PRIx32" %"PRIx32"\n", addr, bas); DEBUG_INFO("step 0x%08"PRIx32" %"PRIx32"\n", addr, bas);
/* Set match any breakpoint */ /* Set match any breakpoint */
apb_write(t, DBGBVR(0), priv->reg_cache.r[15] & ~3); apb_write(t, DBGBVR(0), priv->reg_cache.r[15] & ~3);
apb_write(t, DBGBCR(0), DBGBCR_INST_MISMATCH | bas | apb_write(t, DBGBCR(0), DBGBCR_INST_MISMATCH | bas |
@ -693,7 +693,7 @@ void cortexa_halt_resume(target *t, bool step)
do { do {
apb_write(t, DBGDRCR, DBGDRCR_CSE | DBGDRCR_RRQ); apb_write(t, DBGDRCR, DBGDRCR_CSE | DBGDRCR_RRQ);
dbgdscr = apb_read(t, DBGDSCR); dbgdscr = apb_read(t, DBGDSCR);
DEBUG("%s: DBGDSCR = 0x%08"PRIx32"\n", __func__, dbgdscr); DEBUG_INFO("%s: DBGDSCR = 0x%08"PRIx32"\n", __func__, dbgdscr);
} while (!(dbgdscr & DBGDSCR_RESTARTED) && } while (!(dbgdscr & DBGDSCR_RESTARTED) &&
!platform_timeout_is_expired(&to)); !platform_timeout_is_expired(&to));
} }

View File

@ -2,8 +2,8 @@
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2012 Black Sphere Technologies Ltd. * Copyright (C) 2012 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz> * Written by Gareth McMullin <gareth@blacksphere.co.nz>,
* and Koen De Vleeschauwer. * Koen De Vleeschauwer and Uwe Bonne
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -296,7 +296,7 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced)
uint32_t identity = ap->idr & 0xff; uint32_t identity = ap->idr & 0xff;
struct cortexm_priv *priv = calloc(1, sizeof(*priv)); struct cortexm_priv *priv = calloc(1, sizeof(*priv));
if (!priv) { /* calloc failed: heap exhaustion */ if (!priv) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return false; return false;
} }
@ -657,7 +657,7 @@ static void cortexm_reset(target *t)
!platform_timeout_is_expired(&to)); !platform_timeout_is_expired(&to));
#if defined(PLATFORM_HAS_DEBUG) #if defined(PLATFORM_HAS_DEBUG)
if (platform_timeout_is_expired(&to)) if (platform_timeout_is_expired(&to))
DEBUG("Reset seem to be stuck low!\n"); DEBUG_WARN("Reset seem to be stuck low!\n");
#endif #endif
/* 10 ms delay to ensure that things such as the STM32 HSI clock /* 10 ms delay to ensure that things such as the STM32 HSI clock
* have started up fully. */ * have started up fully. */
@ -1084,7 +1084,7 @@ static void probe_mem_read(target *t __attribute__((unused)), void *probe_dest,
uint8_t *dst = (uint8_t *)probe_dest; uint8_t *dst = (uint8_t *)probe_dest;
uint8_t *src = (uint8_t *)target_src; uint8_t *src = (uint8_t *)target_src;
DEBUG("probe_mem_read\n"); DEBUG_INFO("probe_mem_read\n");
while (len--) *dst++=*src++; while (len--) *dst++=*src++;
return; return;
} }
@ -1094,7 +1094,7 @@ static void probe_mem_write(target *t __attribute__((unused)), target_addr targe
uint8_t *dst = (uint8_t *)target_dest; uint8_t *dst = (uint8_t *)target_dest;
uint8_t *src = (uint8_t *)probe_src; uint8_t *src = (uint8_t *)probe_src;
DEBUG("probe_mem_write\n"); DEBUG_INFO("probe_mem_write\n");
while (len--) *dst++=*src++; while (len--) *dst++=*src++;
return; return;
} }
@ -1111,7 +1111,7 @@ static int cortexm_hostio_request(target *t)
uint32_t syscall = arm_regs[0]; uint32_t syscall = arm_regs[0];
int32_t ret = 0; int32_t ret = 0;
DEBUG("syscall 0"PRIx32"%"PRIx32" (%"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32")\n", DEBUG_INFO("syscall 0"PRIx32"%"PRIx32" (%"PRIx32" %"PRIx32" %"PRIx32" %"PRIx32")\n",
syscall, params[0], params[1], params[2], params[3]); syscall, params[0], params[1], params[2], params[3]);
switch (syscall) { switch (syscall) {
#if PC_HOSTED == 1 #if PC_HOSTED == 1

View File

@ -543,7 +543,7 @@ static void efm32_add_flash(target *t, target_addr addr, size_t length,
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -724,7 +724,7 @@ static int efm32_flash_write(struct target_flash *f,
/* Check the MSC_IF */ /* Check the MSC_IF */
uint32_t msc = device->msc_addr; uint32_t msc = device->msc_addr;
uint32_t msc_if = target_mem_read32(t, EFM32_MSC_IF(msc)); uint32_t msc_if = target_mem_read32(t, EFM32_MSC_IF(msc));
DEBUG("EFM32: Flash write done MSC_IF=%08"PRIx32"\n", msc_if); DEBUG_INFO("EFM32: Flash write done MSC_IF=%08"PRIx32"\n", msc_if);
#endif #endif
return ret; return ret;
} }
@ -985,7 +985,7 @@ void efm32_aap_probe(ADIv5_AP_t *ap)
{ {
if ((ap->idr & EFM32_APP_IDR_MASK) == EFM32_AAP_IDR) { if ((ap->idr & EFM32_APP_IDR_MASK) == EFM32_AAP_IDR) {
/* It's an EFM32 AAP! */ /* It's an EFM32 AAP! */
DEBUG("EFM32: Found EFM32 AAP\n"); DEBUG_INFO("EFM32: Found EFM32 AAP\n");
} else { } else {
return; return;
} }
@ -1002,7 +1002,7 @@ void efm32_aap_probe(ADIv5_AP_t *ap)
//efm32_aap_cmd_device_erase(t); //efm32_aap_cmd_device_erase(t);
/* Read status */ /* Read status */
DEBUG("EFM32: AAP STATUS=%08"PRIx32"\n", adiv5_ap_read(ap, AAP_STATUS)); DEBUG_INFO("EFM32: AAP STATUS=%08"PRIx32"\n", adiv5_ap_read(ap, AAP_STATUS));
sprintf(aap_driver_string, sprintf(aap_driver_string,
"EFM32 Authentication Access Port rev.%d", "EFM32 Authentication Access Port rev.%d",
@ -1032,15 +1032,15 @@ static bool efm32_aap_cmd_device_erase(target *t, int argc, const char **argv)
/* Read status */ /* Read status */
status = adiv5_ap_read(ap, AAP_STATUS); status = adiv5_ap_read(ap, AAP_STATUS);
DEBUG("EFM32: AAP STATUS=%08"PRIx32"\n", status); DEBUG_INFO("EFM32: AAP STATUS=%08"PRIx32"\n", status);
if (status & AAP_STATUS_ERASEBUSY) { if (status & AAP_STATUS_ERASEBUSY) {
DEBUG("EFM32: AAP Erase in progress\n"); DEBUG_WARN("EFM32: AAP Erase in progress\n");
DEBUG("EFM32: -> ABORT\n"); DEBUG_WARN("EFM32: -> ABORT\n");
return false; return false;
} }
DEBUG("EFM32: Issuing DEVICEERASE...\n"); DEBUG_INFO("EFM32: Issuing DEVICEERASE...\n");
adiv5_ap_write(ap, AAP_CMDKEY, CMDKEY); adiv5_ap_write(ap, AAP_CMDKEY, CMDKEY);
adiv5_ap_write(ap, AAP_CMD, 1); adiv5_ap_write(ap, AAP_CMD, 1);
@ -1051,7 +1051,7 @@ static bool efm32_aap_cmd_device_erase(target *t, int argc, const char **argv)
/* Read status */ /* Read status */
status = adiv5_ap_read(ap, AAP_STATUS); status = adiv5_ap_read(ap, AAP_STATUS);
DEBUG("EFM32: AAP STATUS=%08"PRIx32"\n", status); DEBUG_INFO("EFM32: AAP STATUS=%08"PRIx32"\n", status);
return true; return true;
} }

View File

@ -66,10 +66,10 @@ int jtag_scan(const uint8_t *irlens)
/* Run throught the SWD to JTAG sequence for the case where an attached SWJ-DP is /* Run throught the SWD to JTAG sequence for the case where an attached SWJ-DP is
* in SW-DP mode. * in SW-DP mode.
*/ */
DEBUG("Resetting TAP\n"); DEBUG_INFO("Resetting TAP\n");
#if PC_HOSTED == 1 #if PC_HOSTED == 1
if (platform_jtagtap_init()) { if (platform_jtagtap_init()) {
DEBUG("JTAG not available\n"); DEBUG_WARN("JTAG not available\n");
return 0; return 0;
} }
#else #else
@ -78,8 +78,8 @@ int jtag_scan(const uint8_t *irlens)
jtag_proc.jtagtap_reset(); jtag_proc.jtagtap_reset();
if (irlens) { if (irlens) {
DEBUG("Given list of IR lengths, skipping probe\n"); DEBUG_WARN("Given list of IR lengths, skipping probe\n");
DEBUG("Change state to Shift-IR\n"); DEBUG_INFO("Change state to Shift-IR\n");
jtagtap_shift_ir(); jtagtap_shift_ir();
j = 0; j = 0;
while((jtag_dev_count <= JTAG_MAX_DEVS) && while((jtag_dev_count <= JTAG_MAX_DEVS) &&
@ -89,7 +89,7 @@ int jtag_scan(const uint8_t *irlens)
break; break;
jtag_proc.jtagtap_tdi_tdo_seq((uint8_t*)&irout, 0, ones, *irlens); jtag_proc.jtagtap_tdi_tdo_seq((uint8_t*)&irout, 0, ones, *irlens);
if (!(irout & 1)) { if (!(irout & 1)) {
DEBUG("check failed: IR[0] != 1\n"); DEBUG_WARN("check failed: IR[0] != 1\n");
return -1; return -1;
} }
jtag_devs[jtag_dev_count].ir_len = *irlens; jtag_devs[jtag_dev_count].ir_len = *irlens;
@ -100,12 +100,13 @@ int jtag_scan(const uint8_t *irlens)
jtag_dev_count++; jtag_dev_count++;
} }
} else { } else {
DEBUG("Change state to Shift-IR\n"); DEBUG_INFO("Change state to Shift-IR\n");
jtagtap_shift_ir(); jtagtap_shift_ir();
DEBUG("Scanning out IRs\n"); DEBUG_INFO("Scanning out IRs\n");
if(!jtag_proc.jtagtap_next(0, 1)) { if(!jtag_proc.jtagtap_next(0, 1)) {
DEBUG("jtag_scan: Sanity check failed: IR[0] shifted out as 0\n"); DEBUG_WARN("jtag_scan: Sanity check failed: IR[0] shifted out "
"as 0\n");
jtag_dev_count = -1; jtag_dev_count = -1;
return -1; /* must be 1 */ return -1; /* must be 1 */
} }
@ -121,37 +122,37 @@ int jtag_scan(const uint8_t *irlens)
j++; j++;
} }
if(jtag_dev_count > JTAG_MAX_DEVS) { if(jtag_dev_count > JTAG_MAX_DEVS) {
DEBUG("jtag_scan: Maximum device count exceeded\n"); DEBUG_WARN("jtag_scan: Maximum device count exceeded\n");
jtag_dev_count = -1; jtag_dev_count = -1;
return -1; return -1;
} }
if(jtag_devs[jtag_dev_count].ir_len > JTAG_MAX_IR_LEN) { if(jtag_devs[jtag_dev_count].ir_len > JTAG_MAX_IR_LEN) {
DEBUG("jtag_scan: Maximum IR length exceeded\n"); DEBUG_WARN("jtag_scan: Maximum IR length exceeded\n");
jtag_dev_count = -1; jtag_dev_count = -1;
return -1; return -1;
} }
} }
DEBUG("Return to Run-Test/Idle\n"); DEBUG_INFO("Return to Run-Test/Idle\n");
jtag_proc.jtagtap_next(1, 1); jtag_proc.jtagtap_next(1, 1);
jtagtap_return_idle(); jtagtap_return_idle();
/* All devices should be in BYPASS now */ /* All devices should be in BYPASS now */
/* Count device on chain */ /* Count device on chain */
DEBUG("Change state to Shift-DR\n"); DEBUG_INFO("Change state to Shift-DR\n");
jtagtap_shift_dr(); jtagtap_shift_dr();
for(i = 0; (jtag_proc.jtagtap_next(0, 1) == 0) && (i <= jtag_dev_count); i++) for(i = 0; (jtag_proc.jtagtap_next(0, 1) == 0) && (i <= jtag_dev_count); i++)
jtag_devs[i].dr_postscan = jtag_dev_count - i - 1; jtag_devs[i].dr_postscan = jtag_dev_count - i - 1;
if(i != jtag_dev_count) { if(i != jtag_dev_count) {
DEBUG("jtag_scan: Sanity check failed: " DEBUG_WARN("jtag_scan: Sanity check failed: "
"BYPASS dev count doesn't match IR scan\n"); "BYPASS dev count doesn't match IR scan\n");
jtag_dev_count = -1; jtag_dev_count = -1;
return -1; return -1;
} }
DEBUG("Return to Run-Test/Idle\n"); DEBUG_INFO("Return to Run-Test/Idle\n");
jtag_proc.jtagtap_next(1, 1); jtag_proc.jtagtap_next(1, 1);
jtagtap_return_idle(); jtagtap_return_idle();
if(!jtag_dev_count) { if(!jtag_dev_count) {
@ -173,7 +174,7 @@ int jtag_scan(const uint8_t *irlens)
if(jtag_proc.jtagtap_next(0, 1)) jtag_devs[i].idcode |= j; if(jtag_proc.jtagtap_next(0, 1)) jtag_devs[i].idcode |= j;
} }
DEBUG("Return to Run-Test/Idle\n"); DEBUG_INFO("Return to Run-Test/Idle\n");
jtag_proc.jtagtap_next(1, 1); jtag_proc.jtagtap_next(1, 1);
jtagtap_return_idle(); jtagtap_return_idle();

View File

@ -109,7 +109,7 @@ static void kl_gen_add_flash(target *t, uint32_t addr, size_t length,
struct target_flash *f; struct target_flash *f;
if (!kf) { /* calloc failed: heap exhaustion */ if (!kf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }

View File

@ -61,7 +61,7 @@ static void lmi_add_flash(target *t, size_t length)
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }

View File

@ -137,7 +137,7 @@ lpc11xx_probe(target *t)
return true; return true;
} }
if (idcode) { if (idcode) {
DEBUG("LPC11xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode); DEBUG_INFO("LPC11xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode);
} }
idcode = target_mem_read32(t, LPC8XX_DEVICE_ID); idcode = target_mem_read32(t, LPC8XX_DEVICE_ID);
switch (idcode) { switch (idcode) {
@ -196,7 +196,7 @@ lpc11xx_probe(target *t)
return true; return true;
} }
if (idcode) { if (idcode) {
DEBUG("LPC8xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode); DEBUG_INFO("LPC8xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode);
} }
return false; return false;

View File

@ -138,17 +138,20 @@ lpc17xx_cmd_erase(target *t, int argc, const char *argv[])
struct flash_param param; struct flash_param param;
if (lpc17xx_iap_call(t, &param, IAP_CMD_PREPARE, 0, FLASH_NUM_SECTOR-1)) { if (lpc17xx_iap_call(t, &param, IAP_CMD_PREPARE, 0, FLASH_NUM_SECTOR-1)) {
DEBUG("lpc17xx_cmd_erase: prepare failed %d\n", (unsigned int)param.result[0]); DEBUG_WARN("lpc17xx_cmd_erase: prepare failed %d\n",
(unsigned int)param.result[0]);
return false; return false;
} }
if (lpc17xx_iap_call(t, &param, IAP_CMD_ERASE, 0, FLASH_NUM_SECTOR-1, CPU_CLK_KHZ)) { if (lpc17xx_iap_call(t, &param, IAP_CMD_ERASE, 0, FLASH_NUM_SECTOR-1, CPU_CLK_KHZ)) {
DEBUG("lpc17xx_cmd_erase: erase failed %d\n", (unsigned int)param.result[0]); DEBUG_WARN("lpc17xx_cmd_erase: erase failed %d\n",
(unsigned int)param.result[0]);
return false; return false;
} }
if (lpc17xx_iap_call(t, &param, IAP_CMD_BLANKCHECK, 0, FLASH_NUM_SECTOR-1)) { if (lpc17xx_iap_call(t, &param, IAP_CMD_BLANKCHECK, 0, FLASH_NUM_SECTOR-1)) {
DEBUG("lpc17xx_cmd_erase: blankcheck failed %d\n", (unsigned int)param.result[0]); DEBUG_WARN("lpc17xx_cmd_erase: blankcheck failed %d\n",
(unsigned int)param.result[0]);
return false; return false;
} }
tc_printf(t, "Erase OK.\n"); tc_printf(t, "Erase OK.\n");

View File

@ -40,7 +40,7 @@ struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length)
struct target_flash *f; struct target_flash *f;
if (!lf) { /* calloc failed: heap exhaustion */ if (!lf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return NULL; return NULL;
} }

View File

@ -150,7 +150,7 @@ static void msp432_add_flash(target *t, uint32_t addr, size_t length, target_add
struct msp432_flash *mf = calloc(1, sizeof(*mf)); struct msp432_flash *mf = calloc(1, sizeof(*mf));
struct target_flash *f; struct target_flash *f;
if (!mf) { /* calloc failed: heap exhaustion */ if (!mf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -185,7 +185,7 @@ bool msp432_probe(target *t)
/* Check for the right HW revision: at least C, as no flash support for B */ /* Check for the right HW revision: at least C, as no flash support for B */
if (target_mem_read32(t, HWREV_ADDR) < HWREV_MIN_VALUE) { if (target_mem_read32(t, HWREV_ADDR) < HWREV_MIN_VALUE) {
DEBUG("MSP432 Version not handled\n"); DEBUG_INFO("MSP432 Version not handled\n");
return false; return false;
} }
@ -239,20 +239,21 @@ static bool msp432_sector_erase(struct target_flash *f, target_addr addr)
/* Unprotect sector */ /* Unprotect sector */
uint32_t old_prot = msp432_sector_unprotect(mf, addr); uint32_t old_prot = msp432_sector_unprotect(mf, addr);
DEBUG("Flash protect: 0x%08"PRIX32"\n", target_mem_read32(t, mf->flash_protect_register)); DEBUG_WARN("Flash protect: 0x%08"PRIX32"\n",
target_mem_read32(t, mf->flash_protect_register));
/* Prepare input data */ /* Prepare input data */
uint32_t regs[t->regs_size / sizeof(uint32_t)]; // Use of VLA uint32_t regs[t->regs_size / sizeof(uint32_t)]; // Use of VLA
target_regs_read(t, regs); target_regs_read(t, regs);
regs[0] = addr; // Address of sector to erase in R0 regs[0] = addr; // Address of sector to erase in R0
DEBUG("Erasing sector at 0x%08"PRIX32"\n", addr); DEBUG_INFO("Erasing sector at 0x%08"PRIX32"\n", addr);
/* Call ROM */ /* Call ROM */
msp432_call_ROM(t, mf->FlashCtl_eraseSector, regs); msp432_call_ROM(t, mf->FlashCtl_eraseSector, regs);
// Result value in R0 is true for success // Result value in R0 is true for success
DEBUG("ROM return value: %"PRIu32"\n", regs[0]); DEBUG_INFO("ROM return value: %"PRIu32"\n", regs[0]);
/* Restore original protection */ /* Restore original protection */
target_mem_write32(t, mf->flash_protect_register, old_prot); target_mem_write32(t, mf->flash_protect_register, old_prot);
@ -291,7 +292,8 @@ static int msp432_flash_write(struct target_flash *f, target_addr dest,
/* Unprotect sector, len is always < SECTOR_SIZE */ /* Unprotect sector, len is always < SECTOR_SIZE */
uint32_t old_prot = msp432_sector_unprotect(mf, dest); uint32_t old_prot = msp432_sector_unprotect(mf, dest);
DEBUG("Flash protect: 0x%08"PRIX32"\n", target_mem_read32(t, mf->flash_protect_register)); DEBUG_WARN("Flash protect: 0x%08"PRIX32"\n",
target_mem_read32(t, mf->flash_protect_register));
/* Prepare input data */ /* Prepare input data */
uint32_t regs[t->regs_size / sizeof(uint32_t)]; // Use of VLA uint32_t regs[t->regs_size / sizeof(uint32_t)]; // Use of VLA
@ -300,14 +302,14 @@ static int msp432_flash_write(struct target_flash *f, target_addr dest,
regs[1] = dest; // Flash address to be write to in R1 regs[1] = dest; // Flash address to be write to in R1
regs[2] = len; // Size of buffer to be flashed in R2 regs[2] = len; // Size of buffer to be flashed in R2
DEBUG("Writing 0x%04" PRIX32 " bytes at 0x%08zu\n", dest, len); DEBUG_INFO("Writing 0x%04" PRIX32 " bytes at 0x%08zu\n", dest, len);
/* Call ROM */ /* Call ROM */
msp432_call_ROM(t, mf->FlashCtl_programMemory, regs); msp432_call_ROM(t, mf->FlashCtl_programMemory, regs);
/* Restore original protection */ /* Restore original protection */
target_mem_write32(t, mf->flash_protect_register, old_prot); target_mem_write32(t, mf->flash_protect_register, old_prot);
DEBUG("ROM return value: %"PRIu32"\n", regs[0]); DEBUG_INFO("ROM return value: %"PRIu32"\n", regs[0]);
// Result value in R0 is true for success // Result value in R0 is true for success
return !regs[0]; return !regs[0];
} }
@ -321,7 +323,7 @@ static bool msp432_cmd_erase_main(target *t, int argc, const char **argv)
/* Usually, this is not wanted, so go sector by sector... */ /* Usually, this is not wanted, so go sector by sector... */
uint32_t banksize = target_mem_read32(t, SYS_FLASH_SIZE) / 2; uint32_t banksize = target_mem_read32(t, SYS_FLASH_SIZE) / 2;
DEBUG("Bank Size: 0x%08"PRIX32"\n", banksize); DEBUG_INFO("Bank Size: 0x%08"PRIX32"\n", banksize);
/* Erase first bank */ /* Erase first bank */
struct target_flash *f = get_target_flash(t, MAIN_FLASH_BASE); struct target_flash *f = get_target_flash(t, MAIN_FLASH_BASE);

View File

@ -99,7 +99,7 @@ static void nrf51_add_flash(target *t,
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }

View File

@ -239,7 +239,7 @@ bool ke04_probe(target *t)
/* Add flash, all KE04 have same write and erase size */ /* Add flash, all KE04 have same write and erase size */
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return false; return false;
} }

View File

@ -129,7 +129,7 @@ static void sam3_add_flash(target *t,
struct target_flash *f; struct target_flash *f;
if (!sf) { /* calloc failed: heap exhaustion */ if (!sf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -152,7 +152,7 @@ static void sam4_add_flash(target *t,
struct target_flash *f; struct target_flash *f;
if (!sf) { /* calloc failed: heap exhaustion */ if (!sf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -264,7 +264,7 @@ bool sam3x_probe(target *t)
static int static int
sam3x_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg) sam3x_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg)
{ {
DEBUG("%s: base = 0x%08"PRIx32" cmd = 0x%02X, arg = 0x%06X\n", DEBUG_INFO("%s: base = 0x%08"PRIx32" cmd = 0x%02X, arg = 0x%06X\n",
__func__, base, cmd, arg); __func__, base, cmd, arg);
target_mem_write32(t, EEFC_FCR(base), target_mem_write32(t, EEFC_FCR(base),
EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8));

View File

@ -170,7 +170,7 @@ static void sam4l_add_flash(target *t, uint32_t addr, size_t length)
{ {
struct target_flash *f = calloc(1, sizeof(struct target_flash)); struct target_flash *f = calloc(1, sizeof(struct target_flash));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -237,15 +237,15 @@ bool sam4l_probe(target *t)
target_add_ram(t, 0x20000000, ram_size); target_add_ram(t, 0x20000000, ram_size);
flash_size = sam_nvp_size(t->idcode); flash_size = sam_nvp_size(t->idcode);
sam4l_add_flash(t, 0x0, flash_size); sam4l_add_flash(t, 0x0, flash_size);
DEBUG("\nSAM4L: RAM = 0x%x (%dK), FLASH = 0x%x (%dK)\n", DEBUG_INFO("\nSAM4L: RAM = 0x%x (%dK), FLASH = 0x%x (%dK)\n",
(unsigned int) ram_size, (unsigned int) (ram_size / 1024), (unsigned int) ram_size, (unsigned int) (ram_size / 1024),
(unsigned int) flash_size, (unsigned int)(flash_size / 1024)); (unsigned int) flash_size, (unsigned int)(flash_size / 1024));
/* enable SMAP if not, check for HCR and reset if set */ /* enable SMAP if not, check for HCR and reset if set */
sam4l_extended_reset(t); sam4l_extended_reset(t);
DEBUG("\nSAM4L: SAM4L Selected.\n"); DEBUG_INFO("\nSAM4L: SAM4L Selected.\n");
if (target_check_error(t)) { if (target_check_error(t)) {
DEBUG("SAM4L: target_check_error returned true\n"); DEBUG_WARN("SAM4L: target_check_error returned true\n");
} }
return true; return true;
} }
@ -261,11 +261,11 @@ sam4l_extended_reset(target *t)
uint32_t reg; uint32_t reg;
int i; int i;
DEBUG("SAM4L: Extended Reset\n"); DEBUG_INFO("SAM4L: Extended Reset\n");
/* enable SMAP in case we're dealing with a non-TCK SRST */ /* enable SMAP in case we're dealing with a non-TCK SRST */
target_mem_write32(t, SMAP_CR, 0x1); /* enable SMAP */ target_mem_write32(t, SMAP_CR, 0x1); /* enable SMAP */
reg = target_mem_read32(t, SMAP_SR); reg = target_mem_read32(t, SMAP_SR);
DEBUG("\nSAM4L: SMAP_SR has 0x%08lx\n", (long unsigned int) reg); DEBUG_INFO("\nSAM4L: SMAP_SR has 0x%08lx\n", (long unsigned int) reg);
if ((reg & SMAP_SR_HCR) != 0) { if ((reg & SMAP_SR_HCR) != 0) {
/* write '1' bit to the status clear register */ /* write '1' bit to the status clear register */
target_mem_write32(t, SMAP_SCR, SMAP_SR_HCR); target_mem_write32(t, SMAP_SCR, SMAP_SR_HCR);
@ -275,7 +275,8 @@ sam4l_extended_reset(target *t)
} }
/* not sure what to do if we can't reset that bit */ /* not sure what to do if we can't reset that bit */
if (i > 249) { if (i > 249) {
DEBUG("\nSAM4L: Reset failed. SMAP_SR has 0x%08lx\n", (long unsigned int) reg); DEBUG_INFO("\nSAM4L: Reset failed. SMAP_SR has 0x%08lx\n",
(long unsigned int) reg);
} }
} }
/* reset bus error if for some reason SMAP was disabled */ /* reset bus error if for some reason SMAP was disabled */
@ -298,8 +299,9 @@ sam4l_flash_command(target *t, uint32_t page, uint32_t cmd)
uint32_t cmd_reg; uint32_t cmd_reg;
uint32_t status; uint32_t status;
int timeout; int timeout;
DEBUG("\nSAM4L: sam4l_flash_command: FSR: 0x%08x, page = %d, command = %d\n", DEBUG_INFO("\nSAM4L: sam4l_flash_command: FSR: 0x%08x, page = %d, "
(unsigned int)(FLASHCALW_FSR), (int) page, (int) cmd); "command = %d\n", (unsigned int)(FLASHCALW_FSR),
(int) page, (int) cmd);
/* wait for Flash controller ready */ /* wait for Flash controller ready */
for (timeout = 0; timeout < FLASH_TIMEOUT; timeout++) { for (timeout = 0; timeout < FLASH_TIMEOUT; timeout++) {
status = target_mem_read32(t, FLASHCALW_FSR); status = target_mem_read32(t, FLASHCALW_FSR);
@ -308,14 +310,16 @@ sam4l_flash_command(target *t, uint32_t page, uint32_t cmd)
} }
} }
if (timeout == FLASH_TIMEOUT) { if (timeout == FLASH_TIMEOUT) {
DEBUG("\nSAM4L: sam4l_flash_command: Not ready! Status = 0x%08x\n", (unsigned int) status); DEBUG_WARN("\nSAM4L: sam4l_flash_command: Not ready! "
"Status = 0x%08x\n", (unsigned int) status);
return -1; /* Failed */ return -1; /* Failed */
} }
/* load up the new command */ /* load up the new command */
cmd_reg = (cmd & FLASHCALW_FCMD_CMD_MASK) | cmd_reg = (cmd & FLASHCALW_FCMD_CMD_MASK) |
((page & FLASHCALW_FCMD_PAGEN_MASK) << FLASHCALW_FCMD_PAGEN_SHIFT) | ((page & FLASHCALW_FCMD_PAGEN_MASK) << FLASHCALW_FCMD_PAGEN_SHIFT) |
(0xA5 << FLASHCALW_FCMD_KEY_SHIFT); (0xA5 << FLASHCALW_FCMD_KEY_SHIFT);
DEBUG("\nSAM4L: sam4l_flash_command: Wrting command word 0x%08x\n", (unsigned int) cmd_reg); DEBUG_INFO("\nSAM4L: sam4l_flash_command: Wrting command word 0x%08x\n",
(unsigned int) cmd_reg);
/* and kick it off */ /* and kick it off */
target_mem_write32(t, FLASHCALW_FCMD, cmd_reg); target_mem_write32(t, FLASHCALW_FCMD, cmd_reg);
/* don't actually wait for it to finish, the next command will stall if it is not done */ /* don't actually wait for it to finish, the next command will stall if it is not done */
@ -334,7 +338,8 @@ sam4l_flash_write_buf(struct target_flash *f, target_addr addr, const void *src,
uint32_t ndx; uint32_t ndx;
uint16_t page; uint16_t page;
DEBUG("\nSAM4L: sam4l_flash_write_buf: addr = 0x%08lx, len %d\n", (long unsigned int) addr, (int) len); DEBUG_INFO("\nSAM4L: sam4l_flash_write_buf: addr = 0x%08lx, len %d\n",
(long unsigned int) addr, (int) len);
/* This will fail with unaligned writes, the write_buf version */ /* This will fail with unaligned writes, the write_buf version */
page = addr / SAM4L_PAGE_SIZE; page = addr / SAM4L_PAGE_SIZE;
@ -380,7 +385,7 @@ sam4l_flash_erase(struct target_flash *f, target_addr addr, size_t len)
target *t = f->t; target *t = f->t;
uint16_t page; uint16_t page;
DEBUG("SAM4L: flash erase address 0x%08x for %d bytes\n", DEBUG_INFO("SAM4L: flash erase address 0x%08x for %d bytes\n",
(unsigned int) addr, (unsigned int) len); (unsigned int) addr, (unsigned int) len);
/* /*
* NB: if addr isn't aligned to a page boundary, or length * NB: if addr isn't aligned to a page boundary, or length

View File

@ -428,7 +428,7 @@ static void samd_add_flash(target *t, uint32_t addr, size_t length)
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }

View File

@ -331,7 +331,7 @@ static void samx5x_add_flash(target *t, uint32_t addr, size_t length,
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_INFO("calloc: failed in %s\n", __func__);
return; return;
} }
@ -462,19 +462,19 @@ static void samx5x_unlock_current_address(target *t)
static void samx5x_print_nvm_error(uint16_t errs) static void samx5x_print_nvm_error(uint16_t errs)
{ {
if (errs & SAMX5X_INTFLAG_ADDRE) { if (errs & SAMX5X_INTFLAG_ADDRE) {
DEBUG(" ADDRE"); DEBUG_WARN(" ADDRE");
} }
if (errs & SAMX5X_INTFLAG_PROGE) { if (errs & SAMX5X_INTFLAG_PROGE) {
DEBUG(" PROGE"); DEBUG_WARN(" PROGE");
} }
if (errs & SAMX5X_INTFLAG_LOCKE) { if (errs & SAMX5X_INTFLAG_LOCKE) {
DEBUG(" LOCKE"); DEBUG_WARN(" LOCKE");
} }
if (errs & SAMX5X_INTFLAG_NVME) { if (errs & SAMX5X_INTFLAG_NVME) {
DEBUG(" NVME"); DEBUG_WARN(" NVME");
} }
DEBUG("\n"); DEBUG_WARN("\n");
} }
static int samx5x_read_nvm_error(target *t) static int samx5x_read_nvm_error(target *t)
@ -499,7 +499,7 @@ static int samx5x_check_nvm_error(target *t)
if (!errs) if (!errs)
return 0; return 0;
DEBUG("NVM error(s) detected:"); DEBUG_WARN("NVM error(s) detected:");
samx5x_print_nvm_error(errs); samx5x_print_nvm_error(errs);
return -1; return -1;
} }
@ -519,7 +519,7 @@ static int samx5x_flash_erase(struct target_flash *f, target_addr addr,
target *t = f->t; target *t = f->t;
uint16_t errs = samx5x_read_nvm_error(t); uint16_t errs = samx5x_read_nvm_error(t);
if (errs) { if (errs) {
DEBUG(NVM_ERROR_BITS_MSG, "erase", addr, len); DEBUG_INFO(NVM_ERROR_BITS_MSG, "erase", addr, len);
samx5x_print_nvm_error(errs); samx5x_print_nvm_error(errs);
samx5x_clear_nvm_error(t); samx5x_clear_nvm_error(t);
} }
@ -579,7 +579,7 @@ static int samx5x_flash_write(struct target_flash *f,
bool error = false; bool error = false;
uint16_t errs = samx5x_read_nvm_error(t); uint16_t errs = samx5x_read_nvm_error(t);
if (errs) { if (errs) {
DEBUG(NVM_ERROR_BITS_MSG, "write", dest, len); DEBUG_INFO(NVM_ERROR_BITS_MSG, "write", dest, len);
samx5x_print_nvm_error(errs); samx5x_print_nvm_error(errs);
samx5x_clear_nvm_error(t); samx5x_clear_nvm_error(t);
} }
@ -604,9 +604,8 @@ static int samx5x_flash_write(struct target_flash *f,
} }
if (error || target_check_error(t) || samx5x_check_nvm_error(t)) { if (error || target_check_error(t) || samx5x_check_nvm_error(t)) {
DEBUG("Error writing flash page at 0x%08"PRIx32 DEBUG_WARN("Error writing flash page at 0x%08"PRIx32
" (len 0x%08zx)\n", " (len 0x%08zx)\n", dest, len);
dest, len);
return -1; return -1;
} }
@ -623,7 +622,7 @@ static int samx5x_write_user_page(target *t, uint8_t *buffer)
{ {
uint16_t errs = samx5x_read_nvm_error(t); uint16_t errs = samx5x_read_nvm_error(t);
if (errs) { if (errs) {
DEBUG(NVM_ERROR_BITS_MSG, "erase and write", DEBUG_INFO(NVM_ERROR_BITS_MSG, "erase and write",
(uint32_t)SAMX5X_NVM_USER_PAGE, (uint32_t)SAMX5X_NVM_USER_PAGE,
(size_t)SAMX5X_PAGE_SIZE); (size_t)SAMX5X_PAGE_SIZE);
samx5x_print_nvm_error(errs); samx5x_print_nvm_error(errs);
@ -692,13 +691,13 @@ static int samx5x_update_user_word(target *t, uint32_t addr, uint32_t value,
*value_written = new_word; *value_written = new_word;
if (new_word != current_word) { if (new_word != current_word) {
DEBUG("Writing user page word 0x%08"PRIx32 DEBUG_INFO("Writing user page word 0x%08"PRIx32
" at offset 0x%03"PRIx32"\n", new_word, addr); " at offset 0x%03"PRIx32"\n", new_word, addr);
memcpy(buffer + addr, &new_word, 4); memcpy(buffer + addr, &new_word, 4);
return samx5x_write_user_page(t, buffer); return samx5x_write_user_page(t, buffer);
} }
else { else {
DEBUG("Skipping user page write as no change would be made"); DEBUG_INFO("Skipping user page write as no change would be made");
} }
return 0; return 0;
@ -947,7 +946,7 @@ static bool samx5x_cmd_mbist(target *t, int argc, const char **argv)
(void)argc; (void)argc;
(void)argv; (void)argv;
DEBUG("Running MBIST for memory range 0x%08x-%08"PRIx32"\n", DEBUG_INFO("Running MBIST for memory range 0x%08x-%08"PRIx32"\n",
SAMX5X_RAM_START, samx5x_ram_size(t)); SAMX5X_RAM_START, samx5x_ram_size(t));
/* Write the memory parameters to the DSU /* Write the memory parameters to the DSU
@ -1019,7 +1018,7 @@ static bool samx5x_cmd_write8(target *t, int argc, const char **argv)
return false; return false;
} }
DEBUG("Writing 8-bit value 0x%02"PRIx32" at address 0x%08"PRIx32"\n", DEBUG_INFO("Writing 8-bit value 0x%02"PRIx32" at address 0x%08"PRIx32"\n",
value, addr); value, addr);
target_mem_write8(t, addr, (uint8_t)value); target_mem_write8(t, addr, (uint8_t)value);
@ -1051,7 +1050,7 @@ static bool samx5x_cmd_write16(target *t, int argc, const char **argv)
return false; return false;
} }
DEBUG("Writing 16-bit value 0x%04"PRIx32" at address 0x%08"PRIx32"\n", DEBUG_INFO("Writing 16-bit value 0x%04"PRIx32" at address 0x%08"PRIx32"\n",
value, addr); value, addr);
target_mem_write16(t, addr, (uint16_t)value); target_mem_write16(t, addr, (uint16_t)value);
@ -1078,7 +1077,7 @@ static bool samx5x_cmd_write32(target *t, int argc, const char **argv)
return false; return false;
} }
DEBUG("Writing 32-bit value 0x%08"PRIx32" at address 0x%08"PRIx32"\n", DEBUG_INFO("Writing 32-bit value 0x%08"PRIx32" at address 0x%08"PRIx32"\n",
value, addr); value, addr);
target_mem_write32(t, addr, value); target_mem_write32(t, addr, value);

View File

@ -99,7 +99,7 @@ static void stm32f1_add_flash(target *t,
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -130,7 +130,7 @@ bool stm32f1_probe(target *t)
if ((ap->idr >> 28) > 1) { if ((ap->idr >> 28) > 1) {
t->driver = "STM32F1 (clone) medium density"; t->driver = "STM32F1 (clone) medium density";
#if defined(PLATFORM_HAS_DEBUG) #if defined(PLATFORM_HAS_DEBUG)
DEBUG("Non-genuine STM32F1\n"); DEBUG_WARN("Non-genuine STM32F1\n");
#endif #endif
} else { } else {
t->driver = "STM32F1 medium density"; t->driver = "STM32F1 medium density";
@ -216,7 +216,7 @@ static int stm32f1_flash_erase(struct target_flash *f,
/* Read FLASH_SR to poll for BSY bit */ /* Read FLASH_SR to poll for BSY bit */
while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("stm32f1 flash erase: comm error\n"); DEBUG_WARN("stm32f1 flash erase: comm error\n");
return -1; return -1;
} }
if (len > f->blocksize) if (len > f->blocksize)
@ -229,7 +229,7 @@ static int stm32f1_flash_erase(struct target_flash *f,
/* Check for error */ /* Check for error */
uint32_t sr = target_mem_read32(t, FLASH_SR); uint32_t sr = target_mem_read32(t, FLASH_SR);
if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) { if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) {
DEBUG("stm32f1 flash erase error 0x%" PRIx32 "\n", sr); DEBUG_INFO("stm32f1 flash erase error 0x%" PRIx32 "\n", sr);
return -1; return -1;
} }
@ -248,13 +248,13 @@ static int stm32f1_flash_write(struct target_flash *f,
do { do {
sr = target_mem_read32(t, FLASH_SR); sr = target_mem_read32(t, FLASH_SR);
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("stm32f1 flash write: comm error\n"); DEBUG_WARN("stm32f1 flash write: comm error\n");
return -1; return -1;
} }
} while (sr & FLASH_SR_BSY); } while (sr & FLASH_SR_BSY);
if (sr & SR_ERROR_MASK) { if (sr & SR_ERROR_MASK) {
DEBUG("stm32f1 flash write error 0x%" PRIx32 "\n", sr); DEBUG_WARN("stm32f1 flash write error 0x%" PRIx32 "\n", sr);
return -1; return -1;
} }
return 0; return 0;

View File

@ -143,7 +143,7 @@ static void stm32f4_add_flash(target *t,
struct stm32f4_flash *sf = calloc(1, sizeof(*sf)); struct stm32f4_flash *sf = calloc(1, sizeof(*sf));
struct target_flash *f; struct target_flash *f;
if (!sf) { /* calloc failed: heap exhaustion */ if (!sf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -411,7 +411,7 @@ static int stm32f4_flash_erase(struct target_flash *f, target_addr addr,
/* Read FLASH_SR to poll for BSY bit */ /* Read FLASH_SR to poll for BSY bit */
while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY)
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("stm32f4 flash erase: comm error\n"); DEBUG_WARN("stm32f4 flash erase: comm error\n");
return -1; return -1;
} }
if (len > f->blocksize) if (len > f->blocksize)
@ -426,7 +426,7 @@ static int stm32f4_flash_erase(struct target_flash *f, target_addr addr,
/* Check for error */ /* Check for error */
sr = target_mem_read32(t, FLASH_SR); sr = target_mem_read32(t, FLASH_SR);
if(sr & SR_ERROR_MASK) { if(sr & SR_ERROR_MASK) {
DEBUG("stm32f4 flash erase: sr error: 0x%" PRIu32 "\n", sr); DEBUG_WARN("stm32f4 flash erase: sr error: 0x%" PRIu32 "\n", sr);
return -1; return -1;
} }
return 0; return 0;
@ -450,13 +450,13 @@ static int stm32f4_flash_write(struct target_flash *f,
do { do {
sr = target_mem_read32(t, FLASH_SR); sr = target_mem_read32(t, FLASH_SR);
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("stm32f4 flash write: comm error\n"); DEBUG_WARN("stm32f4 flash write: comm error\n");
return -1; return -1;
} }
} while (sr & FLASH_SR_BSY); } while (sr & FLASH_SR_BSY);
if (sr & SR_ERROR_MASK) { if (sr & SR_ERROR_MASK) {
DEBUG("stm32f4 flash write error 0x%" PRIx32 "\n", sr); DEBUG_WARN("stm32f4 flash write error 0x%" PRIx32 "\n", sr);
return -1; return -1;
} }
return 0; return 0;

View File

@ -1,7 +1,7 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2017-2018 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de * Copyright (C) 2017-2020 Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -165,7 +165,7 @@ static void stm32h7_add_flash(target *t,
struct target_flash *f; struct target_flash *f;
if (!sf) { /* calloc failed: heap exhaustion */ if (!sf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -288,19 +288,19 @@ static int stm32h7_flash_erase(struct target_flash *f, target_addr addr,
target_mem_write32(t, sf->regbase + FLASH_CR, cr); target_mem_write32(t, sf->regbase + FLASH_CR, cr);
cr |= FLASH_CR_START; cr |= FLASH_CR_START;
target_mem_write32(t, sf->regbase + FLASH_CR, cr); target_mem_write32(t, sf->regbase + FLASH_CR, cr);
DEBUG(" started cr %08" PRIx32 " sr %08" PRIx32 "\n", DEBUG_INFO(" started cr %08" PRIx32 " sr %08" PRIx32 "\n",
target_mem_read32(t, sf->regbase + FLASH_CR), target_mem_read32(t, sf->regbase + FLASH_CR),
target_mem_read32(t, sf->regbase + FLASH_SR)); target_mem_read32(t, sf->regbase + FLASH_SR));
do { do {
sr = target_mem_read32(t, sf->regbase + FLASH_SR); sr = target_mem_read32(t, sf->regbase + FLASH_SR);
if (target_check_error(t)) { if (target_check_error(t)) {
DEBUG("stm32h7_flash_erase: comm failed\n"); DEBUG_WARN("stm32h7_flash_erase: comm failed\n");
return -1; return -1;
} }
// target_mem_write32(t, H7_IWDG_BASE, 0x0000aaaa); // target_mem_write32(t, H7_IWDG_BASE, 0x0000aaaa);
}while (sr & (FLASH_SR_QW | FLASH_SR_BSY)); }while (sr & (FLASH_SR_QW | FLASH_SR_BSY));
if (sr & FLASH_SR_ERROR_MASK) { if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("stm32h7_flash_erase: error, sr: %08" PRIx32 "\n", sr); DEBUG_WARN("stm32h7_flash_erase: error, sr: %08" PRIx32 "\n", sr);
return -1; return -1;
} }
start_sector++; start_sector++;
@ -326,12 +326,12 @@ static int stm32h7_flash_write(struct target_flash *f, target_addr dest,
target_mem_write(t, dest, src, len); target_mem_write(t, dest, src, len);
while ((sr = target_mem_read32(t, sr_reg)) & FLASH_SR_BSY) { while ((sr = target_mem_read32(t, sr_reg)) & FLASH_SR_BSY) {
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("stm32h7_flash_write: BSY comm failed\n"); DEBUG_WARN("stm32h7_flash_write: BSY comm failed\n");
return -1; return -1;
} }
} }
if (sr & FLASH_SR_ERROR_MASK) { if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("stm32h7_flash_write: error sr %08" PRIx32 "\n", sr); DEBUG_WARN("stm32h7_flash_write: error sr %08" PRIx32 "\n", sr);
return -1; return -1;
} }
/* Close write windows.*/ /* Close write windows.*/
@ -357,23 +357,23 @@ static bool stm32h7_cmd_erase(target *t, int bank_mask)
/* Flash mass erase start instruction */ /* Flash mass erase start instruction */
if (do_bank1) { if (do_bank1) {
if (stm32h7_flash_unlock(t, BANK1_START) == false) { if (stm32h7_flash_unlock(t, BANK1_START) == false) {
DEBUG("ME: Unlock bank1 failed\n"); DEBUG_WARN("ME: Unlock bank1 failed\n");
goto done; goto done;
} }
uint32_t regbase = FPEC1_BASE; uint32_t regbase = FPEC1_BASE;
/* BER and start can be merged (3.3.10).*/ /* BER and start can be merged (3.3.10).*/
target_mem_write32(t, regbase + FLASH_CR, cr); target_mem_write32(t, regbase + FLASH_CR, cr);
DEBUG("ME bank1 started\n"); DEBUG_INFO("ME bank1 started\n");
} }
if (do_bank2) { if (do_bank2) {
if (stm32h7_flash_unlock(t, BANK2_START) == false) { if (stm32h7_flash_unlock(t, BANK2_START) == false) {
DEBUG("ME: Unlock bank2 failed\n"); DEBUG_WARN("ME: Unlock bank2 failed\n");
goto done; goto done;
} }
uint32_t regbase = FPEC2_BASE; uint32_t regbase = FPEC2_BASE;
/* BER and start can be merged (3.3.10).*/ /* BER and start can be merged (3.3.10).*/
target_mem_write32(t, regbase + FLASH_CR, cr); target_mem_write32(t, regbase + FLASH_CR, cr);
DEBUG("ME bank2 started\n"); DEBUG_INFO("ME bank2 started\n");
} }
/* Read FLASH_SR to poll for QW bit */ /* Read FLASH_SR to poll for QW bit */
@ -383,7 +383,7 @@ static bool stm32h7_cmd_erase(target *t, int bank_mask)
// target_mem_write32(t, H7_IWDG_BASE, 0x0000aaaa); // target_mem_write32(t, H7_IWDG_BASE, 0x0000aaaa);
tc_printf(t, "\b%c", spinner[spinindex++ % 4]); tc_printf(t, "\b%c", spinner[spinindex++ % 4]);
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("ME bank1: comm failed\n"); DEBUG_WARN("ME bank1: comm failed\n");
goto done; goto done;
} }
} }
@ -394,7 +394,7 @@ static bool stm32h7_cmd_erase(target *t, int bank_mask)
// target_mem_write32(t, H7_IWDG_BASE 0x0000aaaa); // target_mem_write32(t, H7_IWDG_BASE 0x0000aaaa);
tc_printf(t, "\b%c", spinner[spinindex++ % 4]); tc_printf(t, "\b%c", spinner[spinindex++ % 4]);
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("ME bank2: comm failed\n"); DEBUG_WARN("ME bank2: comm failed\n");
goto done; goto done;
} }
} }
@ -405,7 +405,7 @@ static bool stm32h7_cmd_erase(target *t, int bank_mask)
uint32_t regbase = FPEC1_BASE; uint32_t regbase = FPEC1_BASE;
uint32_t sr = target_mem_read32(t, regbase + FLASH_SR); uint32_t sr = target_mem_read32(t, regbase + FLASH_SR);
if (sr & FLASH_SR_ERROR_MASK) { if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("ME bank1: sr %" PRIx32 "\n", sr); DEBUG_WARN("ME bank1, error sr %" PRIx32 "\n", sr);
goto done; goto done;
} }
} }
@ -414,7 +414,7 @@ static bool stm32h7_cmd_erase(target *t, int bank_mask)
uint32_t regbase = FPEC2_BASE; uint32_t regbase = FPEC2_BASE;
uint32_t sr = target_mem_read32(t, regbase + FLASH_SR); uint32_t sr = target_mem_read32(t, regbase + FLASH_SR);
if (sr & FLASH_SR_ERROR_MASK) { if (sr & FLASH_SR_ERROR_MASK) {
DEBUG("ME bank2: sr %" PRIx32 "\n", sr); DEBUG_WARN("ME bank2, error: sr %" PRIx32 "\n", sr);
goto done; goto done;
} }
} }
@ -467,13 +467,15 @@ static int stm32h7_crc_bank(target *t, uint32_t bank)
target_mem_write32(t, regbase + FLASH_CRCCR, crccr); target_mem_write32(t, regbase + FLASH_CRCCR, crccr);
target_mem_write32(t, regbase + FLASH_CRCCR, crccr | FLASH_CRCCR_START_CRC); target_mem_write32(t, regbase + FLASH_CRCCR, crccr | FLASH_CRCCR_START_CRC);
uint32_t sr; uint32_t sr;
while ((sr = target_mem_read32(t, regbase + FLASH_SR)) & FLASH_SR_CRC_BUSY) { while ((sr = target_mem_read32(t, regbase + FLASH_SR)) &
FLASH_SR_CRC_BUSY) {
if(target_check_error(t)) { if(target_check_error(t)) {
DEBUG("CRC bank %d: comm failed\n", (bank < BANK2_START) ? 1 : 2); DEBUG_WARN("CRC bank %d: comm failed\n",
(bank < BANK2_START) ? 1 : 2);
return -1; return -1;
} }
if (sr & FLASH_SR_ERROR_READ) { if (sr & FLASH_SR_ERROR_READ) {
DEBUG("CRC bank %d: error sr %08" PRIx32 "\n", DEBUG_WARN("CRC bank %d: error sr %08" PRIx32 "\n",
(bank < BANK2_START) ? 1 : 2, sr); (bank < BANK2_START) ? 1 : 2, sr);
return -1; return -1;
} }

View File

@ -234,7 +234,7 @@ static void stm32l_add_flash(target *t,
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -251,7 +251,7 @@ static void stm32l_add_eeprom(target *t, uint32_t addr, size_t length)
{ {
struct target_flash *f = calloc(1, sizeof(*f)); struct target_flash *f = calloc(1, sizeof(*f));
if (!f) { /* calloc failed: heap exhaustion */ if (!f) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }

View File

@ -1,8 +1,8 @@
/* /*
* This file is part of the Black Magic Debug project. * This file is part of the Black Magic Debug project.
* *
* Copyright (C) 2015, 2017, 2018 Uwe Bonnes * Copyright (C) 2015, 2017 - 2020 Uwe Bonnes
* Written by Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de> * <bon@elektron.ikp.physik.tu-darmstadt.de>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -262,7 +262,7 @@ static void stm32l4_add_flash(target *t,
struct target_flash *f; struct target_flash *f;
if (!sf) { /* calloc failed: heap exhaustion */ if (!sf) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return; return;
} }
@ -461,13 +461,13 @@ static int stm32l4_flash_write(struct target_flash *f,
do { do {
sr = target_mem_read32(t, FLASH_SR); sr = target_mem_read32(t, FLASH_SR);
if (target_check_error(t)) { if (target_check_error(t)) {
DEBUG("stm32l4 flash write: comm error\n"); DEBUG_WARN("stm32l4 flash write: comm error\n");
return -1; return -1;
} }
} while (sr & FLASH_SR_BSY); } while (sr & FLASH_SR_BSY);
if(sr & FLASH_SR_ERROR_MASK) { if(sr & FLASH_SR_ERROR_MASK) {
DEBUG("stm32l4 flash write error: sr 0x%" PRIu32 "\n", sr); DEBUG_WARN("stm32l4 flash write error: sr 0x%" PRIu32 "\n", sr);
return -1; return -1;
} }
return 0; return 0;

View File

@ -39,7 +39,7 @@ target *target_new(void)
{ {
target *t = (void*)calloc(1, sizeof(*t)); target *t = (void*)calloc(1, sizeof(*t));
if (!t) { /* calloc failed: heap exhaustion */ if (!t) { /* calloc failed: heap exhaustion */
DEBUG("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
return NULL; return NULL;
} }
@ -124,7 +124,7 @@ void target_add_commands(target *t, const struct command_s *cmds, const char *na
{ {
struct target_command_s *tc = malloc(sizeof(*tc)); struct target_command_s *tc = malloc(sizeof(*tc));
if (!tc) { /* malloc failed: heap exhaustion */ if (!tc) { /* malloc failed: heap exhaustion */
DEBUG("malloc: failed in %s\n", __func__); DEBUG_WARN("malloc: failed in %s\n", __func__);
return; return;
} }
@ -168,7 +168,7 @@ void target_add_ram(target *t, target_addr start, uint32_t len)
{ {
struct target_ram *ram = malloc(sizeof(*ram)); struct target_ram *ram = malloc(sizeof(*ram));
if (!ram) { /* malloc failed: heap exhaustion */ if (!ram) { /* malloc failed: heap exhaustion */
DEBUG("malloc: failed in %s\n", __func__); DEBUG_WARN("malloc: failed in %s\n", __func__);
return; return;
} }
@ -238,7 +238,7 @@ int target_flash_erase(target *t, target_addr addr, size_t len)
while (len) { while (len) {
struct target_flash *f = flash_for_addr(t, addr); struct target_flash *f = flash_for_addr(t, addr);
if (!f) { if (!f) {
DEBUG("Erase stopped at 0x%06" PRIx32 "\n", addr); DEBUG_WARN("Erase stopped at 0x%06" PRIx32 "\n", addr);
return ret; return ret;
} }
size_t tmptarget = MIN(addr + len, f->start + f->length); size_t tmptarget = MIN(addr + len, f->start + f->length);
@ -292,7 +292,7 @@ int target_flash_write_buffered(struct target_flash *f,
/* Allocate flash sector buffer */ /* Allocate flash sector buffer */
f->buf = malloc(f->buf_size); f->buf = malloc(f->buf_size);
if (!f->buf) { /* malloc failed: heap exhaustion */ if (!f->buf) { /* malloc failed: heap exhaustion */
DEBUG("malloc: failed in %s\n", __func__); DEBUG_WARN("malloc: failed in %s\n", __func__);
return 1; return 1;
} }
f->buf_addr = -1; f->buf_addr = -1;
@ -409,7 +409,7 @@ void target_set_cmdline(target *t, char *cmdline) {
len_dst = sizeof(t->cmdline)-1; len_dst = sizeof(t->cmdline)-1;
strncpy(t->cmdline, cmdline, len_dst -1); strncpy(t->cmdline, cmdline, len_dst -1);
t->cmdline[strlen(t->cmdline)]='\0'; t->cmdline[strlen(t->cmdline)]='\0';
DEBUG("cmdline: >%s<\n", t->cmdline); DEBUG_INFO("cmdline: >%s<\n", t->cmdline);
} }
/* Set heapinfo for semihosting */ /* Set heapinfo for semihosting */
@ -440,7 +440,7 @@ int target_breakwatch_set(target *t,
/* Success, make a heap copy */ /* Success, make a heap copy */
struct breakwatch *bwm = malloc(sizeof bw); struct breakwatch *bwm = malloc(sizeof bw);
if (!bwm) { /* malloc failed: heap exhaustion */ if (!bwm) { /* malloc failed: heap exhaustion */
DEBUG("malloc: failed in %s\n", __func__); DEBUG_WARN("malloc: failed in %s\n", __func__);
return 1; return 1;
} }
memcpy(bwm, &bw, sizeof(bw)); memcpy(bwm, &bw, sizeof(bw));