Merge commit 'dd6aadc54d00cee92e14bf7538d3ece3d3ab298f' into sam-update

This commit is contained in:
Jason Kotzin 2022-08-10 18:37:14 -07:00
commit 046cc359ba
42 changed files with 300 additions and 301 deletions

View File

@ -5,14 +5,6 @@ endif
PC_HOSTED = PC_HOSTED =
NO_LIBOPENCM3 = NO_LIBOPENCM3 =
ifeq ($(PROBE_HOST), libftdi)
PC_HOSTED = true
NO_LIBOPENCM3 = true
endif
ifeq ($(PROBE_HOST), pc-stlinkv2)
PC_HOSTED = true
NO_LIBOPENCM3 = true
endif
ifeq ($(PROBE_HOST), hosted) ifeq ($(PROBE_HOST), hosted)
PC_HOSTED = true PC_HOSTED = true
NO_LIBOPENCM3 = true NO_LIBOPENCM3 = true

61
scripts/dfu-convert.py Normal file → Executable file
View File

@ -1,13 +1,19 @@
#!/usr/bin/python2 #!/usr/bin/env python
# Written by Antonio Galea - 2010/11/18 # Written by Antonio Galea - 2010/11/18
# Distributed under Gnu LGPL 3.0 # Distributed under Gnu LGPL 3.0
# see http://www.gnu.org/licenses/lgpl-3.0.txt # see http://www.gnu.org/licenses/lgpl-3.0.txt
#
# Add support for Python 3 inspired by script found in Bitcraze repository
import sys,struct,zlib,os import sys,struct,zlib,os
from optparse import OptionParser from optparse import OptionParser
from intelhex import IntelHex from intelhex import IntelHex
python3 = False
if (sys.version_info > (3, 0)):
python3 = True
DEFAULT_DEVICE="0x0483:0xdf11" DEFAULT_DEVICE="0x0483:0xdf11"
def named(tuple,names): def named(tuple,names):
@ -21,11 +27,11 @@ def compute_crc(data):
return 0xFFFFFFFF & -zlib.crc32(data) -1 return 0xFFFFFFFF & -zlib.crc32(data) -1
def parse(file,dump_images=False): def parse(file,dump_images=False):
print 'File: "%s"' % file print('File: "%s"' % file)
data = open(file,'rb').read() data = open(file,'rb').read()
crc = compute_crc(data[:-4]) crc = compute_crc(data[:-4])
prefix, data = consume('<5sBIB',data,'signature version size targets') prefix, data = consume('<5sBIB',data,'signature version size targets')
print '%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix print('%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix)
for t in range(prefix['targets']): for t in range(prefix['targets']):
tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements') tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements')
tprefix['num'] = t tprefix['num'] = t
@ -33,40 +39,57 @@ def parse(file,dump_images=False):
tprefix['name'] = cstring(tprefix['name']) tprefix['name'] = cstring(tprefix['name'])
else: else:
tprefix['name'] = '' tprefix['name'] = ''
print '%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix print('%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix)
tsize = tprefix['size'] tsize = tprefix['size']
target, data = data[:tsize], data[tsize:] target, data = data[:tsize], data[tsize:]
for e in range(tprefix['elements']): for e in range(tprefix['elements']):
eprefix, target = consume('<2I',target,'address size') eprefix, target = consume('<2I',target,'address size')
eprefix['num'] = e eprefix['num'] = e
print ' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix print(' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix)
esize = eprefix['size'] esize = eprefix['size']
image, target = target[:esize], target[esize:] image, target = target[:esize], target[esize:]
if dump_images: if dump_images:
out = '%s.target%d.image%d.bin' % (file,t,e) out = '%s.target%d.image%d.bin' % (file,t,e)
open(out,'wb').write(image) open(out,'wb').write(image)
print ' DUMPED IMAGE TO "%s"' % out print(' DUMPED IMAGE TO "%s"' % out)
if len(target): if len(target):
print "target %d: PARSE ERROR" % t print("target %d: PARSE ERROR" % t)
suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc') suffix = named(struct.unpack('<4H3sBI',data[:16]),'device product vendor dfu ufd len crc')
print 'usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix)
if crc != suffix['crc']: if crc != suffix['crc']:
print "CRC ERROR: computed crc32 is 0x%08x" % crc print("CRC ERROR: computed crc32 is 0x%08x" % crc)
data = data[16:] data = data[16:]
if data: if data:
print "PARSE ERROR" print("PARSE ERROR")
def build(file,targets,device=DEFAULT_DEVICE): def build(file,targets,device=DEFAULT_DEVICE):
data = '' data = ''
if (python3):
data = b''
for t,target in enumerate(targets): for t,target in enumerate(targets):
tdata = '' tdata = ''
if (python3):
tdata = b''
for image in target: for image in target:
tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data'] tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data']
tdata = struct.pack('<6sBI255s2I','Target',0,1,'ST...',len(tdata),len(target)) + tdata
trgt = 'Target'
st = 'ST...'
if (python3):
trgt = b'Target'
st = b'ST...'
tdata = struct.pack('<6sBI255s2I',trgt,0,1,st,len(tdata),len(target)) + tdata
data += tdata data += tdata
data = struct.pack('<5sBIB','DfuSe',1,len(data)+11,len(targets)) + data
dfu_se = 'DfuSe'
ufd = 'UFD'
if (python3):
dfu_se = b'DfuSe'
ufd = b'UFD'
data = struct.pack('<5sBIB',dfu_se,1,len(data)+11,len(targets)) + data
v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1))
data += struct.pack('<4H3sB',0,d,v,0x011a,'UFD',16) data += struct.pack('<4H3sB',0,d,v,0x011a,ufd,16)
crc = compute_crc(data) crc = compute_crc(data)
data += struct.pack('<I',crc) data += struct.pack('<I',crc)
open(file,'wb').write(data) open(file,'wb').write(data)
@ -96,15 +119,15 @@ if __name__=="__main__":
try: try:
address,binfile = arg.split(':',1) address,binfile = arg.split(':',1)
except ValueError: except ValueError:
print "Address:file couple '%s' invalid." % arg print("Address:file couple '%s' invalid." % arg)
sys.exit(1) sys.exit(1)
try: try:
address = int(address,0) & 0xFFFFFFFF address = int(address,0) & 0xFFFFFFFF
except ValueError: except ValueError:
print "Address %s invalid." % address print("Address %s invalid." % address)
sys.exit(1) sys.exit(1)
if not os.path.isfile(binfile): if not os.path.isfile(binfile):
print "Unreadable file '%s'." % binfile print("Unreadable file '%s'." % binfile)
sys.exit(1) sys.exit(1)
target.append({ 'address': address, 'data': open(binfile,'rb').read() }) target.append({ 'address': address, 'data': open(binfile,'rb').read() })
@ -116,7 +139,7 @@ if __name__=="__main__":
try: try:
address = address & 0xFFFFFFFF address = address & 0xFFFFFFFF
except ValueError: except ValueError:
print "Address %s invalid." % address print("Address %s invalid." % address)
sys.exit(1) sys.exit(1)
target.append({ 'address': address, 'data': data }) target.append({ 'address': address, 'data': data })
@ -127,13 +150,13 @@ if __name__=="__main__":
try: try:
v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1)) v,d=map(lambda x: int(x,0) & 0xFFFF, device.split(':',1))
except: except:
print "Invalid device '%s'." % device print("Invalid device '%s'." % device)
sys.exit(1) sys.exit(1)
build(outfile,[target],device) build(outfile,[target],device)
elif len(args)==1: elif len(args)==1:
infile = args[0] infile = args[0]
if not os.path.isfile(infile): if not os.path.isfile(infile):
print "Unreadable file '%s'." % infile print("Unreadable file '%s'." % infile)
sys.exit(1) sys.exit(1)
parse(infile, dump_images=options.dump_images) parse(infile, dump_images=options.dump_images)
else: else:

View File

@ -114,7 +114,7 @@ bool connect_assert_srst;
#if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0) #if defined(PLATFORM_HAS_DEBUG) && (PC_HOSTED == 0)
bool debug_bmp; bool debug_bmp;
#endif #endif
long cortexm_wait_timeout = 2000; /* Timeout to wait for Cortex to react on halt command. */ unsigned cortexm_wait_timeout = 2000; /* Timeout to wait for Cortex to react on halt command. */
int command_process(target *t, char *cmd) int command_process(target *t, char *cmd)
{ {

View File

@ -81,6 +81,12 @@ int gdb_getpacket(char *packet, int size)
break; break;
} }
} }
/* Reset the packet buffer start character to zero, because function
* 'remotePacketProcess()' above overwrites this buffer, and
* an arbitrary character may have been placed there. If this is a '$'
* character, this will cause this loop to be terminated, which is wrong.
*/
packet[0] = 0;
} }
#endif #endif
} while (packet[0] != '$'); } while (packet[0] != '$');

View File

@ -1,4 +1,5 @@
CROSS_COMPILE ?= arm-none-eabi- CROSS_COMPILE ?= arm-none-eabi-
BMP_BOOTLOADER ?=
CC = $(CROSS_COMPILE)gcc CC = $(CROSS_COMPILE)gcc
OBJCOPY = $(CROSS_COMPILE)objcopy OBJCOPY = $(CROSS_COMPILE)objcopy
@ -7,12 +8,20 @@ CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \
-DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \ -DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \
-Iplatforms/stm32 -Iplatforms/stm32
LDFLAGS = -lopencm3_stm32f4 \ LDFLAGS_BOOT = -lopencm3_stm32f4 \
-Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \
-Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \
-mfloat-abi=hard -mfpu=fpv4-sp-d16 \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-L../libopencm3/lib -L../libopencm3/lib
ifeq ($(BMP_BOOTLOADER), 1)
$(info Load address 0x08004000 for BMPBootloader)
LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8004000
CFLAGS += -DUSE_BMP_SERIAL
else
LDFLAGS = $(LDFLAGS_BOOT)
endif
VPATH += platforms/stm32 VPATH += platforms/stm32
SRC += cdcacm.c \ SRC += cdcacm.c \
@ -23,7 +32,18 @@ SRC += cdcacm.c \
timing.c \ timing.c \
timing_stm32.c \ timing_stm32.c \
ifneq ($(BMP_BOOTLOADER), 1)
all: blackmagic.bin all: blackmagic.bin
else
all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex
blackmagic_dfu: usbdfu.o dfucore.o dfu_f4.o
$(CC) $^ -o $@ $(LDFLAGS_BOOT)
blackmagic_dfu.bin: blackmagic_dfu
$(OBJCOPY) -O binary $^ $@
blackmagic_dfu.hex: blackmagic_dfu
$(OBJCOPY) -O ihex $^ $@
endif
host_clean: host_clean:
-$(Q)$(RM) blackmagic.bin -$(Q)$(RM) blackmagic.bin

View File

@ -71,8 +71,8 @@ void platform_init(void)
rcc_periph_clock_enable(RCC_CRC); rcc_periph_clock_enable(RCC_CRC);
/* Set up USB Pins and alternate function*/ /* Set up USB Pins and alternate function*/
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12); gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12); gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10 | GPIO11 | GPIO12);
GPIOC_OSPEEDR &=~0xF30; GPIOC_OSPEEDR &=~0xF30;
GPIOC_OSPEEDR |= 0xA20; GPIOC_OSPEEDR |= 0xA20;

View File

@ -33,6 +33,7 @@
#define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_TRACESWO
#define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_DFU "Black Magic Firmware Upgrade (F4Discovery)"
#define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery)" #define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery)"
/* Important pin mappings for STM32 implementation: /* Important pin mappings for STM32 implementation:

View File

@ -27,59 +27,47 @@
#include "general.h" #include "general.h"
#include "platform.h" #include "platform.h"
uint32_t app_address = 0x08000000; uint32_t app_address = 0x08004000;
static uint16_t led_upgrade; extern char _ebss[];
static uint32_t led2_state = 0;
extern uint32_t _stack;
static uint32_t rev;
void dfu_detach(void) void dfu_detach(void)
{ {
platform_request_boot(); scb_reset_system();
scb_reset_core();
} }
int main(void) int main(void)
{ {
rev = detect_rev(); volatile uint32_t *magic = (uint32_t *)_ebss;
rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_periph_clock_enable(RCC_GPIOA);
if (rev == 0) if (gpio_get(GPIOA, GPIO0) ||
led_upgrade = GPIO8; ((magic[0] == BOOTMAGIC0) && (magic[1] == BOOTMAGIC1))) {
else magic[0] = 0;
led_upgrade = GPIO9; magic[1] = 0;
} else {
dfu_jump_app_if_valid();
}
rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]);
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); /* Assert blue LED as indicator we are in the bootloader */
systick_set_reload(900000); rcc_periph_clock_enable(RCC_GPIOD);
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE, LED_BOOTLOADER);
gpio_set(LED_PORT, LED_BOOTLOADER);
dfu_protect(UPD_MODE); /* Enable peripherals */
rcc_periph_clock_enable(RCC_OTGFS);
systick_interrupt_enable(); /* Set up USB Pins and alternate function*/
systick_counter_enable(); gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12);
gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12);
if (rev > 1) /* Reconnect USB */
gpio_set(GPIOA, GPIO15);
dfu_init(&st_usbfs_v1_usb_driver, UPD_MODE);
dfu_protect(false);
dfu_init(&USB_DRIVER);
dfu_main(); dfu_main();
} }
void dfu_event(void) void dfu_event(void)
{ {
} }
void sys_tick_handler(void)
{
if (rev == 0) {
gpio_toggle(GPIOA, led_upgrade);
} else {
if (led2_state & 1) {
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, led_upgrade);
gpio_set(GPIOA, led_upgrade);
} else {
gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
GPIO_CNF_INPUT_ANALOG, led_upgrade);
}
led2_state++;
}
}

View File

@ -37,7 +37,7 @@
#include "adiv5.h" #include "adiv5.h"
int remote_init(bool verbose) int remote_init(void)
{ {
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);
@ -49,8 +49,7 @@ int remote_init(bool verbose)
c ? (char *)&(construct[1]) : "unknown"); c ? (char *)&(construct[1]) : "unknown");
return -1; return -1;
} }
if (verbose) DEBUG_PROBE("Remote is %s\n", &construct[1]);
DEBUG_WARN("Remote is %s\n", &construct[1]);
return 0; return 0;
} }

View File

@ -29,7 +29,7 @@
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(bool verbose); int remote_init(void);
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);

View File

@ -90,7 +90,7 @@ static void jlink_print_interfaces(bmp_info_t *info)
DEBUG_INFO(", %s available\n", DEBUG_INFO(", %s available\n",
(other_interface == JLINK_IF_SWD) ? "SWD": "JTAG"); (other_interface == JLINK_IF_SWD) ? "SWD": "JTAG");
else else
DEBUG_WARN(", %s not available\n", DEBUG_INFO(", %s not available\n",
((res[0] + 1) == JLINK_IF_SWD) ? "JTAG": "SWD"); ((res[0] + 1) == JLINK_IF_SWD) ? "JTAG": "SWD");
} }

View File

@ -113,10 +113,7 @@ static int swdptap_init(bmp_info_t *info)
cmd[1] = SELECT_IF_SWD; cmd[1] = SELECT_IF_SWD;
send_recv(info->usb_link, cmd, 2, res, sizeof(res)); send_recv(info->usb_link, cmd, 2, res, sizeof(res));
platform_delay(10); platform_delay(10);
/* Set speed 256 kHz*/ /* SWD speed is fixed. Do not set it here*/
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; return 0;
} }
@ -178,7 +175,15 @@ int jlink_swdp_scan(bmp_info_t *info)
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 */
return 0; return 0;
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_ALL) {
dp->idcode = jlink_adiv5_swdp_low_access(dp, 1, ADIV5_DP_IDCODE, 0); dp->idcode = jlink_adiv5_swdp_low_access(dp, 1, ADIV5_DP_IDCODE, 0);
}
if (e.type) {
DEBUG_WARN("DP not responding for IDCODE! Reset stuck low?\n");
free(dp);
return 0;
}
dp->dp_read = jlink_adiv5_swdp_read; dp->dp_read = jlink_adiv5_swdp_read;
dp->error = jlink_adiv5_swdp_error; dp->error = jlink_adiv5_swdp_error;
dp->low_access = jlink_adiv5_swdp_low_access; dp->low_access = jlink_adiv5_swdp_low_access;
@ -186,8 +191,6 @@ int jlink_swdp_scan(bmp_info_t *info)
jlink_adiv5_swdp_error(dp); jlink_adiv5_swdp_error(dp);
adiv5_dp_init(dp); adiv5_dp_init(dp);
if (!target_list)
free(dp);
return target_list?1:0; return target_list?1:0;
} }
@ -249,20 +252,26 @@ static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
uint8_t res[8]; uint8_t res[8];
cmd[0] = CMD_HW_JTAG3; cmd[0] = CMD_HW_JTAG3;
cmd[1] = 0; cmd[1] = 0;
cmd[2] = 13; /* It seems, JLINK samples read data at end of previous clock.
* So target data read must start at the 12'th clock, while
* write starts as expected at the 14'th clock (8 cmd, 3 response,
* 2 turn around.
*/
cmd[2] = (RnW) ? 11 : 13;
cmd[3] = 0; cmd[3] = 0;
cmd[4] = 0xff; cmd[4] = 0xff; /* 8 bits command OUT */
cmd[5] = 0xe3; cmd[5] = 0xf0; /* one IN bit to turn around to read, read 2
cmd[6] = request << 2; (read) or 3 (write) IN bits for response and
cmd[7] = request >> 6; and one OUT bit to turn around to write on write*/
cmd[6] = request;
cmd[7] = 0x00;
platform_timeout_set(&timeout, 2000); platform_timeout_set(&timeout, 2000);
do { do {
send_recv(info.usb_link, cmd, 8, res, 2); send_recv(info.usb_link, cmd, 8, res, 2);
send_recv(info.usb_link, NULL, 0, res, 1); send_recv(info.usb_link, NULL, 0, res + 2 , 1);
if (res[0] != 0) if (res[2] != 0)
raise_exception(EXCEPTION_ERROR, "Low access setup failed"); raise_exception(EXCEPTION_ERROR, "Low access setup failed");
ack = res[1] >> 2; ack = res[1] & 7;
ack &= 7;
} while (ack == SWDP_ACK_WAIT && !platform_timeout_is_expired(&timeout)); } while (ack == SWDP_ACK_WAIT && !platform_timeout_is_expired(&timeout));
if (ack == SWDP_ACK_WAIT) if (ack == SWDP_ACK_WAIT)
raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout"); raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout");
@ -276,17 +285,15 @@ static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
if(ack != SWDP_ACK_OK) { if(ack != SWDP_ACK_OK) {
if (cl_debuglevel & BMP_DEBUG_TARGET) if (cl_debuglevel & BMP_DEBUG_TARGET)
DEBUG_WARN( "Protocol\n"); DEBUG_WARN( "Protocol %d\n", ack);
line_reset(&info); line_reset(&info);
return 0; return 0;
} }
cmd[3] = 0; /* Always append 8 idle cycle (SWDIO = 0)!*/
/* Always prepend an idle cycle (SWDIO = 0)!*/
if(RnW) { if(RnW) {
memset(cmd + 4, 0, 10); memset(cmd + 4, 0, 10);
cmd[2] = 34; cmd[2] = 33 + 2; /* 2 idle cycles */
cmd[8] = 0xfe; cmd[8] = 0xfe;
cmd[13] = 0;
send_recv(info.usb_link, cmd, 14, res, 5); send_recv(info.usb_link, cmd, 14, res, 5);
send_recv(info.usb_link, NULL, 0, res + 5, 1); send_recv(info.usb_link, NULL, 0, res + 5, 1);
if (res[5] != 0) if (res[5] != 0)
@ -297,16 +304,16 @@ static uint32_t jlink_adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
if (bit_count & 1) /* Give up on parity error */ if (bit_count & 1) /* Give up on parity error */
raise_exception(EXCEPTION_ERROR, "SWDP Parity error"); raise_exception(EXCEPTION_ERROR, "SWDP Parity error");
} else { } else {
cmd[2] = 35; cmd[2] = 33 + 8; /* 8 idle cycle to move data through SW-DP */
memset(cmd + 4, 0xff, 5); memset(cmd + 4, 0xff, 6);
cmd[ 9] = ((value << 2) & 0xfc); cmd[10] = ((value >> 0) & 0xff);
cmd[10] = ((value >> 6) & 0xff); cmd[11] = ((value >> 8) & 0xff);
cmd[11] = ((value >> 14) & 0xff); cmd[12] = ((value >> 16) & 0xff);
cmd[12] = ((value >> 22) & 0xff); cmd[13] = ((value >> 24) & 0xff);
cmd[13] = ((value >> 30) & 0x03);
int bit_count = __builtin_popcount(value); int bit_count = __builtin_popcount(value);
cmd[13] |= ((bit_count & 1) ? 4 : 0); cmd[14] = bit_count & 1;
send_recv(info.usb_link, cmd, 14, res, 5); cmd[15] = 0;
send_recv(info.usb_link, cmd, 16, res, 6);
send_recv(info.usb_link, NULL, 0, res, 1); send_recv(info.usb_link, NULL, 0, res, 1);
if (res[0] != 0) if (res[0] != 0)
raise_exception(EXCEPTION_ERROR, "Low access write failed"); raise_exception(EXCEPTION_ERROR, "Low access write failed");

View File

@ -361,9 +361,19 @@ static void swdptap_seq_out(uint32_t MS, int ticks)
} }
} }
/* ARM Debug Interface Architecture Specification ADIv5.0 to ADIv5.2
* tells to clock the data through SW-DP to either :
* - immediate start a new transaction
* - continue to drive idle cycles
* - or clock at least 8 idle cycles
*
* Implement last option to favour correctness over
* slight speed decrease
*/
static void swdptap_seq_out_parity(uint32_t MS, int ticks) static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{ {
int parity = __builtin_parity(MS & ((1LL << ticks) - 1)) & 1; (void) ticks;
int parity = __builtin_parity(MS) & 1;
unsigned int index = 0; unsigned int index = 0;
swdptap_turnaround(SWDIO_STATUS_DRIVE); swdptap_turnaround(SWDIO_STATUS_DRIVE);
if (do_mpsse) { if (do_mpsse) {
@ -373,26 +383,26 @@ static void swdptap_seq_out_parity(uint32_t MS, int ticks)
DI[2] = (MS >> 16) & 0xff; DI[2] = (MS >> 16) & 0xff;
DI[3] = (MS >> 24) & 0xff; DI[3] = (MS >> 24) & 0xff;
DI[4] = parity; DI[4] = parity;
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, ticks + 1); DI[5] = 0;
libftdi_jtagtap_tdi_tdo_seq(NULL, 0, DI, 32 + 1 + 8);
} else { } else {
uint8_t cmd[32]; uint8_t cmd[32];
int steps = ticks; int steps = ticks;
while (steps) { while (steps) {
cmd[index++] = MPSSE_TMS_SHIFT; cmd[index++] = MPSSE_TMS_SHIFT;
if (steps >= 7) {
cmd[index++] = 6; cmd[index++] = 6;
if (steps >= 7) {
cmd[index++] = MS & 0x7f; cmd[index++] = MS & 0x7f;
MS >>= 7; MS >>= 7;
steps -= 7; steps -= 7;
} else { } else {
cmd[index++] = steps - 1; cmd[index++] = (MS & 0x7f) | (parity << 4);
cmd[index++] = MS & 0x7f;
steps = 0; steps = 0;
} }
} }
cmd[index++] = MPSSE_TMS_SHIFT; cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 4;
cmd[index++] = 0; cmd[index++] = 0;
cmd[index++] = parity;
libftdi_buffer_write(cmd, index); libftdi_buffer_write(cmd, index);
} }
} }

View File

@ -36,6 +36,7 @@
#include "ftdi_bmp.h" #include "ftdi_bmp.h"
#include "jlink.h" #include "jlink.h"
#include "cmsis_dap.h" #include "cmsis_dap.h"
#include "version.h"
#define VENDOR_ID_STLINK 0x0483 #define VENDOR_ID_STLINK 0x0483
#define PRODUCT_ID_STLINK_MASK 0xffe0 #define PRODUCT_ID_STLINK_MASK 0xffe0
@ -302,14 +303,16 @@ 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);
} }
DEBUG_WARN("Using %04x:%04x %s %s %s\n", info.vid, info.pid, info.serial, DEBUG_INFO("BMP hosted %s\n for ST-Link V2/3, CMSIS_DAP, JLINK and "
"LIBFTDI/MPSSE\n", FIRMWARE_VERSION);
DEBUG_INFO("Using %04x:%04x %s %s\n %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(true); remote_init();
break; break;
case BMP_TYPE_STLINKV2: case BMP_TYPE_STLINKV2:
if (stlink_init( &info)) if (stlink_init( &info))
@ -358,7 +361,6 @@ int platform_adiv5_swdp_scan(void)
if (target_list) if (target_list)
return 1; return 1;
} }
free(dp);
break; break;
} }
case BMP_TYPE_CMSIS_DAP: case BMP_TYPE_CMSIS_DAP:
@ -372,7 +374,6 @@ int platform_adiv5_swdp_scan(void)
if (target_list) if (target_list)
return 1; return 1;
} }
free(dp);
break; break;
} }
case BMP_TYPE_JLINK: case BMP_TYPE_JLINK:

View File

@ -31,6 +31,7 @@
#include "exception.h" #include "exception.h"
#include "jtag_devs.h" #include "jtag_devs.h"
#include "target.h" #include "target.h"
#include "cortexm.h"
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <unistd.h>
@ -348,7 +349,8 @@ static int stlink_send_recv_retry(uint8_t *txbuf, size_t txsize,
if (res == STLINK_ERROR_OK) if (res == STLINK_ERROR_OK)
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) > cortexm_wait_timeout) ||
(res != STLINK_ERROR_WAIT)) {
DEBUG_WARN("write_retry failed. "); DEBUG_WARN("write_retry failed. ");
return res; return res;
} }
@ -434,7 +436,8 @@ static void stlink_version(bmp_info_t *info)
Stlink.ver_swim = (version >> 0) & 0x3f; Stlink.ver_swim = (version >> 0) & 0x3f;
} }
} }
DEBUG_INFO("V%dJ%d",Stlink.ver_stlink, Stlink.ver_jtag); DEBUG_INFO("STLink firmware version: V%dJ%d",Stlink.ver_stlink,
Stlink.ver_jtag);
if (Stlink.ver_hw == 30) { if (Stlink.ver_hw == 30) {
DEBUG_INFO("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) {
@ -829,8 +832,8 @@ static bool stlink_ap_setup(int ap)
ap, ap,
}; };
uint8_t data[2]; uint8_t data[2];
send_recv(info.usb_link, cmd, 16, data, 2);
DEBUG_PROBE("Open AP %d\n", ap); DEBUG_PROBE("Open AP %d\n", ap);
stlink_send_recv_retry(cmd, 16, data, 2);
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) {

View File

@ -42,7 +42,7 @@ int main(void)
if(gpio_get(GPIOB, GPIO12)) if(gpio_get(GPIOB, GPIO12))
dfu_jump_app_if_valid(); dfu_jump_app_if_valid();
dfu_protect(DFU_MODE); dfu_protect(false);
rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_clock_setup_in_hse_8mhz_out_72mhz();
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
@ -60,7 +60,7 @@ int main(void)
gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
GPIO_CNF_OUTPUT_PUSHPULL, LED_0 | LED_1 | LED_2); GPIO_CNF_OUTPUT_PUSHPULL, LED_0 | LED_1 | LED_2);
dfu_init(&st_usbfs_v1_usb_driver, DFU_MODE); dfu_init(&st_usbfs_v1_usb_driver);
/* Configure the USB pull up pin. */ /* Configure the USB pull up pin. */
gpio_set(GPIOA, GPIO8); gpio_set(GPIOA, GPIO8);

View File

@ -28,7 +28,7 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "version.h"
#include "target.h" #include "target.h"
#include "target_internal.h" #include "target_internal.h"
@ -116,8 +116,8 @@ 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)
{ {
DEBUG_WARN("%s for: \n", opt->opt_idstring); DEBUG_WARN("%s for: \n", opt->opt_idstring);
DEBUG_WARN("\tBMP Firmware, ST-Link V2/3, CMSIS_DAP, JLINK and " DEBUG_WARN("\tBMP hosted %s\n\t\tfor ST-Link V2/3, CMSIS_DAP, JLINK and "
"LIBFTDI/MPSSE\n\n"); "LIBFTDI/MPSSE\n\n", FIRMWARE_VERSION);
DEBUG_WARN("Usage: %s [options]\n", argv[0]); DEBUG_WARN("Usage: %s [options]\n", argv[0]);
DEBUG_WARN("\t-h\t\t: This help.\n"); DEBUG_WARN("\t-h\t\t: This help.\n");
DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n"); DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n");
@ -298,7 +298,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
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)
DEBUG_INFO("Running in Test Mode\n"); DEBUG_INFO("Running in Test Mode\n");
if (platform_target_voltage())
DEBUG_INFO("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);

View File

@ -24,7 +24,7 @@
#if !defined(__CL_UTILS_H) #if !defined(__CL_UTILS_H)
#define __CL_UTILS_H #define __CL_UTILS_H
#define RESP_TIMEOUT (100) #include "cortexm.h"
enum bmp_cl_mode { enum bmp_cl_mode {
BMP_MODE_DEBUG, BMP_MODE_DEBUG,

View File

@ -29,6 +29,7 @@
#include "general.h" #include "general.h"
#include "remote.h" #include "remote.h"
#include "cl_utils.h" #include "cl_utils.h"
#include "cortexm.h"
static int fd; /* File descriptor for connection to GDB remote */ static int fd; /* File descriptor for connection to GDB remote */
@ -189,7 +190,7 @@ int platform_buffer_read(uint8_t *data, int maxsize)
c = data; c = data;
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 1000 * RESP_TIMEOUT; tv.tv_usec = 1000 * cortexm_wait_timeout;
/* Look for start of response */ /* Look for start of response */
do { do {

View File

@ -145,7 +145,7 @@ int platform_buffer_read(uint8_t *data, int maxsize)
DWORD s; DWORD s;
uint8_t response = 0; uint8_t response = 0;
uint32_t startTime = platform_time_ms(); uint32_t startTime = platform_time_ms();
uint32_t endTime = platform_time_ms() + RESP_TIMEOUT; uint32_t endTime = platform_time_ms() + cortexm_wait_timeout;
do { do {
if (!ReadFile(hComm, &response, 1, &s, NULL)) { if (!ReadFile(hComm, &response, 1, &s, NULL)) {
DEBUG_WARN("ERROR on read RESP\n"); DEBUG_WARN("ERROR on read RESP\n");

View File

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

View File

@ -42,9 +42,7 @@ int usbuart_debug_write(const char *buf, size_t len);
#define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware " FIRMWARE_VERSION ")"
#define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" #define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)"
#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg"
/* Hardware definitions... */ /* Hardware definitions... */
#define TDI_PORT GPIOA #define TDI_PORT GPIOA

View File

@ -63,7 +63,7 @@ int main(void)
if(((GPIOA_CRL & 0x40) == 0x40) && stlink_test_nrst()) if(((GPIOA_CRL & 0x40) == 0x40) && stlink_test_nrst())
dfu_jump_app_if_valid(); dfu_jump_app_if_valid();
dfu_protect(DFU_MODE); dfu_protect(false);
rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_clock_setup_in_hse_8mhz_out_72mhz();
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
@ -75,7 +75,7 @@ int main(void)
if (rev > 1) if (rev > 1)
gpio_set(GPIOA, GPIO15); gpio_set(GPIOA, GPIO15);
dfu_init(&st_usbfs_v1_usb_driver, DFU_MODE); dfu_init(&st_usbfs_v1_usb_driver);
dfu_main(); dfu_main();
} }

View File

@ -62,9 +62,9 @@ uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum)
return 100; return 100;
} }
void dfu_protect(dfu_mode_t mode) void dfu_protect(bool enable)
{ {
if (mode == DFU_MODE) { if (enable) {
#ifdef DFU_SELF_PROTECT #ifdef DFU_SELF_PROTECT
if ((FLASH_WRPR & 0x03) != 0x00) { if ((FLASH_WRPR & 0x03) != 0x00) {
flash_unlock(); flash_unlock();

View File

@ -47,21 +47,20 @@ static void get_sector_num(uint32_t addr)
} }
if (!sector_addr[i]) if (!sector_addr[i])
return; return;
sector_num = i; sector_num = i & 0x1f;
} }
void dfu_check_and_do_sector_erase(uint32_t addr) void dfu_check_and_do_sector_erase(uint32_t addr)
{ {
if(addr == sector_addr[sector_num]) { if(addr == sector_addr[sector_num]) {
flash_erase_sector((sector_num & 0x1f)<<3, FLASH_PROGRAM_X32); flash_erase_sector(sector_num, FLASH_CR_PROGRAM_X32);
} }
} }
void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len) void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len)
{ {
for(int i = 0; i < len; i += 4) for(int i = 0; i < len; i += 4)
flash_program_word(baseaddr + i, *(uint32_t*)(buf+i), flash_program_word(baseaddr + i, *(uint32_t*)(buf+i));
FLASH_PROGRAM_X32);
} }
uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum)
@ -78,8 +77,9 @@ uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum)
return 26; return 26;
} }
void dfu_protect_enable(void) void dfu_protect(bool enable)
{ {
if (enable) {
#ifdef DFU_SELF_PROTECT #ifdef DFU_SELF_PROTECT
if ((FLASH_OPTCR & 0x10000) != 0) { if ((FLASH_OPTCR & 0x10000) != 0) {
flash_program_option_bytes(FLASH_OPTCR & ~0x10000); flash_program_option_bytes(FLASH_OPTCR & ~0x10000);
@ -87,20 +87,24 @@ void dfu_protect_enable(void)
} }
#endif #endif
} }
}
void dfu_jump_app_if_valid(void) void dfu_jump_app_if_valid(void)
{ {
/* Boot the application if it's valid */ /* Boot the application if it's valid */
/* Vector table may be anywhere in 128 kByte RAM /* Vector table may be anywhere in 128 kByte RAM
CCM not handled*/ CCM not handled*/
if((*(volatile uint32_t*)APP_ADDRESS & 0x2FFC0000) == 0x20000000) { if((*(volatile uint32_t*)app_address & 0x2FFC0000) == 0x20000000) {
/* Set vector table base address */ #if defined(STM32F7) /* Set vector table base address */
SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/ SCB_VTOR = app_address & 0xFFFFFF00;
#else
SCB_VTOR = app_address & 0x1FFFFF; /* Max 2 MByte Flash*/
#endif
/* Initialise master stack pointer */ /* Initialise master stack pointer */
asm volatile ("msr msp, %0"::"g" asm volatile ("msr msp, %0"::"g"
(*(volatile uint32_t*)APP_ADDRESS)); (*(volatile uint32_t*)app_address));
/* Jump to application */ /* Jump to application */
(*(void(**)())(APP_ADDRESS + 4))(); (*(void(**)())(app_address + 4))();
} }
} }

View File

@ -18,6 +18,7 @@
*/ */
#include "general.h" #include "general.h"
#include <libopencm3/stm32/desig.h>
#include <string.h> #include <string.h>
#if defined(STM32F1HD) #if defined(STM32F1HD)
@ -28,8 +29,11 @@
# define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,000*001Kg" # define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,000*001Kg"
# define DFU_IFACE_STRING_OFFSET 38 # define DFU_IFACE_STRING_OFFSET 38
# define DFU_IFACE_PAGESIZE 1 # define DFU_IFACE_PAGESIZE 1
#elif defined(STM32F4) #elif defined(STM32F4) || defined(STM32F7)
# define DFU_IFACE_STRING "/0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" # define FLASH_BASE 0x08000000U
# define DFU_IFACE_PAGESIZE 128
# define DFU_IFACE_STRING_OFFSET 54
# define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,000*128Kg"
#endif #endif
#include <libopencm3/stm32/flash.h> #include <libopencm3/stm32/flash.h>
@ -129,15 +133,6 @@ static const char *usb_strings[] = {
if_string, if_string,
}; };
static char upd_if_string[] = UPD_IFACE_STRING;
static const char *usb_strings_upd[] = {
"Black Sphere Technologies",
BOARD_IDENT_UPD,
serial_no,
/* This string is used by ST Microelectronics' DfuSe utility */
upd_if_string,
};
static uint32_t get_le32(const void *vp) static uint32_t get_le32(const void *vp)
{ {
const uint8_t *p = vp; const uint8_t *p = vp;
@ -290,12 +285,12 @@ static enum usbd_request_return_codes usbdfu_control_request(usbd_device *dev,
return USBD_REQ_NOTSUPP; return USBD_REQ_NOTSUPP;
} }
void dfu_init(const usbd_driver *driver, dfu_mode_t mode) void dfu_init(const usbd_driver *driver)
{ {
get_dev_unique_id(serial_no); get_dev_unique_id(serial_no);
usbdev = usbd_init(driver, &dev, &config, usbdev = usbd_init(driver, &dev, &config,
(mode == DFU_MODE)?usb_strings:usb_strings_upd, 4, usb_strings, 4,
usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_control_buffer, sizeof(usbd_control_buffer));
usbd_register_control_callback(usbdev, usbd_register_control_callback(usbdev,
@ -335,25 +330,12 @@ static void set_dfu_iface_string(uint32_t size)
*p++ = size + '0'; *p++ = size + '0';
} }
#else #else
# define set_dfu_iface_string() # define set_dfu_iface_string(x)
#endif #endif
static char *get_dev_unique_id(char *s) static char *get_dev_unique_id(char *s)
{ {
#if defined(STM32F4) || defined(STM32F2) volatile uint32_t *unique_id_p = (volatile uint32_t *)DESIG_UNIQUE_ID_BASE;
# define UNIQUE_SERIAL_R 0x1FFF7A10
# define FLASH_SIZE_R 0x1fff7A22
#elif defined(STM32F3)
# define UNIQUE_SERIAL_R 0x1FFFF7AC
# define FLASH_SIZE_R 0x1fff77cc
#elif defined(STM32L1)
# define UNIQUE_SERIAL_R 0x1ff80050
# define FLASH_SIZE_R 0x1FF8004C
#else
# define UNIQUE_SERIAL_R 0x1FFFF7E8;
# define FLASH_SIZE_R 0x1ffff7e0
#endif
volatile uint32_t *unique_id_p = (volatile uint32_t *)UNIQUE_SERIAL_R;
uint32_t unique_id = *unique_id_p + uint32_t unique_id = *unique_id_p +
*(unique_id_p + 1) + *(unique_id_p + 1) +
*(unique_id_p + 2); *(unique_id_p + 2);
@ -362,17 +344,11 @@ static char *get_dev_unique_id(char *s)
/* Calculated the upper flash limit from the exported data /* Calculated the upper flash limit from the exported data
in theparameter block*/ in theparameter block*/
fuse_flash_size = *(uint32_t *) FLASH_SIZE_R & 0xfff; fuse_flash_size = desig_get_flash_size();
if (fuse_flash_size == 0x40) /* Handle F103x8 as F103xB! */ if (fuse_flash_size == 0x40) /* Handle F103x8 as F103xB! */
fuse_flash_size = 0x80; fuse_flash_size = 0x80;
set_dfu_iface_string(fuse_flash_size - 8); set_dfu_iface_string(fuse_flash_size - 8);
max_address = FLASH_BASE + (fuse_flash_size << 10); max_address = FLASH_BASE + (fuse_flash_size << 10);
/* If bootloader pages are write protected or device is read
* protected, deny bootloader update.
* User can still force updates, at his own risk!
*/
if (((FLASH_WRPR & 0x03) != 0x03) || (FLASH_OBR & FLASH_OBR_RDPRT_EN))
upd_if_string[30] = '0';
/* Fetch serial number from chip's unique ID */ /* Fetch serial number from chip's unique ID */
for(i = 0; i < 8; i++) { for(i = 0; i < 8; i++) {
s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0';

View File

@ -21,7 +21,7 @@
char *serial_no_read(char *s, int max) char *serial_no_read(char *s, int max)
{ {
#if defined(STM32F1) #if defined(STM32F1) || defined(USE_BMP_SERIAL)
/* Only STM32F103 has no DFU Bootloader. Generate a ID comatible /* Only STM32F103 has no DFU Bootloader. Generate a ID comatible
* with the BMP Bootloader since ages. * with the BMP Bootloader since ages.
*/ */

View File

@ -27,20 +27,15 @@
#define CMD_ERASE 0x41 #define CMD_ERASE 0x41
extern uint32_t app_address; extern uint32_t app_address;
typedef enum {
DFU_MODE = 0,
UPD_MODE = 1
} dfu_mode_t;
/* dfucore.c - DFU core, common to libopencm3 platforms. */ /* dfucore.c - DFU core, common to libopencm3 platforms. */
void dfu_init(const usbd_driver *driver, dfu_mode_t mode); void dfu_init(const usbd_driver *driver);
void dfu_main(void); void dfu_main(void);
/* Device specific functions */ /* Device specific functions */
void dfu_check_and_do_sector_erase(uint32_t sector); void dfu_check_and_do_sector_erase(uint32_t sector);
void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len); void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len);
uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum); uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum);
void dfu_protect(dfu_mode_t mode); void dfu_protect(bool enable);
void dfu_jump_app_if_valid(void); void dfu_jump_app_if_valid(void);
void dfu_event(void); void dfu_event(void);

View File

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

View File

@ -1,68 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2018 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <libopencm3/cm3/systick.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/cm3/scb.h>
#include "usbdfu.h"
#include "general.h"
#include "platform.h"
uint32_t app_address = 0x08000000;
extern uint32_t _stack;
static uint32_t rev;
void dfu_detach(void)
{
platform_request_boot();
scb_reset_core();
}
int main(void)
{
rev = detect_rev();
rcc_clock_setup_in_hse_8mhz_out_72mhz();
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
systick_set_reload(900000);
dfu_protect(UPD_MODE);
systick_interrupt_enable();
systick_counter_enable();
dfu_init(&st_usbfs_v1_usb_driver, UPD_MODE);
dfu_main();
}
void dfu_event(void)
{
}
void sys_tick_handler(void)
{
if (rev == 0) {
gpio_toggle(GPIOA, GPIO8);
} else {
gpio_toggle(GPIOC, GPIO13);
}
}

View File

@ -39,9 +39,7 @@ int usbuart_debug_write(const char *buf, size_t len);
#define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_DFU "Black Magic (Upgrade), SWLINK, (Firmware " FIRMWARE_VERSION ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade), SWLINK, (Firmware " FIRMWARE_VERSION ")"
#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), SWLINK, (Firmware " FIRMWARE_VERSION ")"
#define DFU_IDENT "Black Magic Firmware Upgrade (SWLINK)" #define DFU_IDENT "Black Magic Firmware Upgrade (SWLINK)"
#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg"
/* Hardware definitions... */ /* Hardware definitions... */
#define TMS_PORT GPIOA #define TMS_PORT GPIOA

View File

@ -75,7 +75,7 @@ int main(void)
if(((GPIOA_CRL & 0x40) == 0x40) && normal_boot) if(((GPIOA_CRL & 0x40) == 0x40) && normal_boot)
dfu_jump_app_if_valid(); dfu_jump_app_if_valid();
dfu_protect(DFU_MODE); dfu_protect(false);
rcc_clock_setup_in_hse_8mhz_out_72mhz(); rcc_clock_setup_in_hse_8mhz_out_72mhz();
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
@ -84,7 +84,7 @@ int main(void)
systick_interrupt_enable(); systick_interrupt_enable();
systick_counter_enable(); systick_counter_enable();
dfu_init(&st_usbfs_v1_usb_driver, DFU_MODE); dfu_init(&st_usbfs_v1_usb_driver);
dfu_main(); dfu_main();
} }

View File

@ -614,6 +614,14 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
void adiv5_dp_init(ADIv5_DP_t *dp) void adiv5_dp_init(ADIv5_DP_t *dp)
{ {
#define DPIDR_PARTNO_MASK 0x0ff00000
/* Check IDCODE for a valid designer and sensible PARTNO*/
if (((dp->idcode & 0xfff) == 0) ||
((dp->idcode & DPIDR_PARTNO_MASK)) == DPIDR_PARTNO_MASK) {
DEBUG_WARN("Invalid DP idcode %08" PRIx32 "\n", dp->idcode);
free(dp);
return;
}
DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%d %srev%d)\n", dp->idcode, DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%d %srev%d)\n", dp->idcode,
(dp->idcode >> 12) & 0xf, (dp->idcode >> 12) & 0xf,
(dp->idcode & 0x10000) ? "MINDP " : "", dp->idcode >> 28); (dp->idcode & 0x10000) ? "MINDP " : "", dp->idcode >> 28);
@ -664,7 +672,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
return; return;
} }
} }
/* This AP reset logic is described in ADIv5, but fails to work /* This AP reset logic is described in ADIv5, but fails to work
* 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
@ -691,8 +698,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
} }
} }
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) {
/* Read TargetID. Can be done with device in WFI, sleep or reset!*/ /* Read TargetID. Can be done with device in WFI, sleep or reset!*/
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);
@ -731,6 +737,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
dp->ap_cleanup(i); dp->ap_cleanup(i);
#endif #endif
adiv5_ap_unref(ap); adiv5_ap_unref(ap);
adiv5_dp_unref(dp);
/* FIXME: Should we expect valid APs behind duplicate ones? */ /* FIXME: Should we expect valid APs behind duplicate ones? */
return; return;
} }

View File

@ -97,7 +97,9 @@
#define AP_DESIGNER_ARM 0x43b #define AP_DESIGNER_ARM 0x43b
/*LPC845 with designer 501. Strange!? */ /*LPC845 with designer 501. Strange!? */
#define AP_DESIGNER_SPECULAR 0x501 #define AP_DESIGNER_SPECULAR 0x501
#define AP_DESIGNER_CS 0x555
#define AP_DESIGNER_ENERGY_MICRO 0x673 #define AP_DESIGNER_ENERGY_MICRO 0x673
#define AP_DESIGNER_GIGADEVICE 0x751
/* AP Control and Status Word (CSW) */ /* AP Control and Status Word (CSW) */
#define ADIV5_AP_CSW_DBGSWENABLE (1u << 31) #define ADIV5_AP_CSW_DBGSWENABLE (1u << 31)

View File

@ -50,8 +50,8 @@ void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode)
} }
dp->dp_jd_index = jd_index; dp->dp_jd_index = jd_index;
if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) {
dp->idcode = j_idcode; dp->idcode = j_idcode;
if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) {
dp->dp_read = fw_adiv5_jtagdp_read; dp->dp_read = fw_adiv5_jtagdp_read;
dp->error = adiv5_jtagdp_error; dp->error = adiv5_jtagdp_error;
dp->low_access = fw_adiv5_jtagdp_low_access; dp->low_access = fw_adiv5_jtagdp_low_access;

View File

@ -82,8 +82,6 @@ int adiv5_swdp_scan(void)
firmware_swdp_error(dp); firmware_swdp_error(dp);
adiv5_dp_init(dp); adiv5_dp_init(dp);
if (!target_list)
free(dp);
return target_list?1:0; return target_list?1:0;
} }
@ -169,19 +167,17 @@ uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
raise_exception(EXCEPTION_ERROR, "SWDP Parity error"); raise_exception(EXCEPTION_ERROR, "SWDP Parity error");
} else { } else {
swd_proc.swdptap_seq_out_parity(value, 32); swd_proc.swdptap_seq_out_parity(value, 32);
/* RM0377 Rev. 8 Chapter 27.5.4 for STM32L0x1 states: /* ARM Debug Interface Architecture Specification ADIv5.0 to ADIv5.2
* Because of the asynchronous clock domains SWCLK and HCLK, * tells to clock the data through SW-DP to either :
* two extra SWCLK cycles are needed after a write transaction * - immediate start a new transaction
* (after the parity bit) to make the write effective * - continue to drive idle cycles
* internally. These cycles should be applied while driving * - or clock at least 8 idle cycles
* the line low (IDLE state) *
* This is particularly important when writing the CTRL/STAT * Implement last option to favour correctness over
* for a power-up request. If the next transaction (requiring * slight speed decrease
* a power-up) occurs immediately, it will fail.
*/ */
swd_proc.swdptap_seq_out(0, 2); swd_proc.swdptap_seq_out(0, 8);
} }
return response; return response;
} }

View File

@ -387,6 +387,12 @@ bool cortexm_probe(ADIv5_AP_t *ap)
target_halt_resume(t, 0); target_halt_resume(t, 0);
} }
break; break;
case AP_DESIGNER_CS:
PROBE(stm32f1_probe);
break;
case AP_DESIGNER_GIGADEVICE:
PROBE(gd32f1_probe);
break;
case AP_DESIGNER_STM: case AP_DESIGNER_STM:
PROBE(stm32f1_probe); PROBE(stm32f1_probe);
PROBE(stm32f4_probe); PROBE(stm32f4_probe);
@ -432,20 +438,19 @@ bool cortexm_probe(ADIv5_AP_t *ap)
"probed device\n", ap->ap_designer, ap->ap_partno); "probed device\n", ap->ap_designer, ap->ap_partno);
#endif #endif
} }
if (ap->ap_partno == 0x4c3) /* Cortex-M3 ROM */ if (ap->ap_partno == 0x4c3) { /* Cortex-M3 ROM */
PROBE(stm32f1_probe); /* Care for STM32F1 clones */ PROBE(stm32f1_probe); /* Care for STM32F1 clones */
else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */ PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */
} else if (ap->ap_partno == 0x471) { /* Cortex-M0 ROM */
PROBE(lpc11xx_probe); /* LPC24C11 */ PROBE(lpc11xx_probe); /* LPC24C11 */
PROBE(lpc43xx_probe); PROBE(lpc43xx_probe);
} } else if (ap->ap_partno == 0x4c4) { /* Cortex-M4 ROM */
else if (ap->ap_partno == 0x4c4) { /* Cortex-M4 ROM */
PROBE(lpc43xx_probe); PROBE(lpc43xx_probe);
PROBE(lpc546xx_probe); PROBE(lpc546xx_probe);
PROBE(kinetis_probe); /* Older K-series */ PROBE(kinetis_probe); /* Older K-series */
} }
/* Info on PIDR of these parts wanted! */ /* Info on PIDR of these parts wanted! */
PROBE(sam3x_probe); PROBE(sam3x_probe);
PROBE(lpc15xx_probe);
PROBE(lmi_probe); PROBE(lmi_probe);
PROBE(ke04_probe); PROBE(ke04_probe);
PROBE(lpc17xx_probe); PROBE(lpc17xx_probe);
@ -536,8 +541,6 @@ void cortexm_detach(target *t)
target_mem_write32(t, CORTEXM_DEMCR, ap->ap_cortexm_demcr); target_mem_write32(t, CORTEXM_DEMCR, ap->ap_cortexm_demcr);
/* Disable debug */ /* Disable debug */
target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY);
/* Add some clock cycles to get the CPU running again.*/
target_mem_read32(t, 0);
} }
enum { DB_DHCSR, DB_DCRSR, DB_DCRDR, DB_DEMCR }; enum { DB_DHCSR, DB_DCRSR, DB_DCRDR, DB_DEMCR };
@ -837,8 +840,6 @@ static void cortexm_halt_resume(target *t, bool step)
target_mem_write32(t, CORTEXM_ICIALLU, 0); target_mem_write32(t, CORTEXM_ICIALLU, 0);
target_mem_write32(t, CORTEXM_DHCSR, dhcsr); target_mem_write32(t, CORTEXM_DHCSR, dhcsr);
/* Add some clock cycles to get the CPU running again.*/
target_mem_read32(t, 0);
} }
static int cortexm_fault_unwind(target *t) static int cortexm_fault_unwind(target *t)

View File

@ -22,7 +22,7 @@
#include "target.h" #include "target.h"
#include "adiv5.h" #include "adiv5.h"
extern long cortexm_wait_timeout; extern unsigned cortexm_wait_timeout;
/* Private peripheral bus base address */ /* Private peripheral bus base address */
#define CORTEXM_PPB_BASE 0xE0000000 #define CORTEXM_PPB_BASE 0xE0000000

View File

@ -43,6 +43,8 @@ jtag_dev_descr_t dev_descr[] = {
.descr = "ST Microelectronics: STM32, Value Line, High density."}, .descr = "ST Microelectronics: STM32, Value Line, High density."},
{.idcode = 0x06411041, .idmask = 0xFFFFFFFF, {.idcode = 0x06411041, .idmask = 0xFFFFFFFF,
.descr = "ST Microelectronics: STM32F2xx."}, .descr = "ST Microelectronics: STM32F2xx."},
{.idcode = 0x06422041, .idmask = 0xFFFFFFFF,
.descr = "ST Microelectronics: STM32F3xx."},
{.idcode = 0x06413041 , .idmask = 0xFFFFFFFF, {.idcode = 0x06413041 , .idmask = 0xFFFFFFFF,
.descr = "ST Microelectronics: STM32F4xx."}, .descr = "ST Microelectronics: STM32F4xx."},
{.idcode = 0x0BB11477 , .idmask = 0xFFFFFFFF, {.idcode = 0x0BB11477 , .idmask = 0xFFFFFFFF,

View File

@ -191,6 +191,18 @@ int jtag_scan(const uint8_t *irlens)
/*Transfer needed device information to firmware jtag_devs*/ /*Transfer needed device information to firmware jtag_devs*/
for(i = 0; i < jtag_dev_count; i++) for(i = 0; i < jtag_dev_count; i++)
platform_add_jtag_dev(i, &jtag_devs[i]); platform_add_jtag_dev(i, &jtag_devs[i]);
for(i = 0; i < jtag_dev_count; i++) {
DEBUG_INFO("Idcode 0x%08" PRIx32, jtag_devs[i].jd_idcode);
for(j = 0; dev_descr[j].idcode; j++) {
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
dev_descr[j].idcode) {
DEBUG_INFO(": %s",
(dev_descr[j].descr) ? dev_descr[j].descr : "unknown");
break;
}
}
DEBUG_INFO("\n");
}
#endif #endif
/* Check for known devices and handle accordingly */ /* Check for known devices and handle accordingly */

View File

@ -116,6 +116,38 @@ static void stm32f1_add_flash(target *t,
target_add_flash(t, f); target_add_flash(t, f);
} }
/**
\brief identify the correct gd32 f1/f3 chip
GD32 : STM32 compatible chip
*/
bool gd32f1_probe(target *t)
{
uint16_t stored_idcode = t->idcode;
// M3 & M4 & riscV only afaik
t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff;
uint32_t signature= target_mem_read32(t, FLASHSIZE);
uint32_t flashSize=signature & 0xFFFF;
uint32_t ramSize=signature >>16 ;
switch(t->idcode) {
case 0x414: /* Gigadevice gd32f303 */
t->driver = "GD32F3";
break;
case 0x410: /* Gigadevice gd32f103 */
t->driver = "GD32F1";
break;
default:
t->idcode = stored_idcode;
return false;
}
target_add_ram(t, 0x20000000, ramSize*1024);
stm32f1_add_flash(t, 0x8000000, flashSize*1024, 0x400);
target_add_commands(t, stm32f1_cmd_list, t->driver);
return true;
}
/**
\brief identify the stm32f1 chip
*/
bool stm32f1_probe(target *t) bool stm32f1_probe(target *t)
{ {
uint16_t stored_idcode = t->idcode; uint16_t stored_idcode = t->idcode;
@ -126,6 +158,7 @@ bool stm32f1_probe(target *t)
size_t flash_size; size_t flash_size;
size_t block_size = 0x400; size_t block_size = 0x400;
switch(t->idcode) { switch(t->idcode) {
case 0x29b: /* CS clone */
case 0x410: /* Medium density */ case 0x410: /* Medium density */
case 0x412: /* Low density */ case 0x412: /* Low density */
case 0x420: /* Value Line, Low-/Medium density */ case 0x420: /* Value Line, Low-/Medium density */

View File

@ -169,6 +169,7 @@ int tc_system(target *t, target_addr cmd, size_t cmdlen);
/* Probe for various targets. /* Probe for various targets.
* Actual functions implemented in their respective drivers. * Actual functions implemented in their respective drivers.
*/ */
bool gd32f1_probe(target *t);
bool stm32f1_probe(target *t); bool stm32f1_probe(target *t);
bool stm32f4_probe(target *t); bool stm32f4_probe(target *t);
bool stm32h7_probe(target *t); bool stm32h7_probe(target *t);