Merge pull request #511 from UweBonnes/pc-stlinkv2

Pc stlinkv2
This commit is contained in:
UweBonnes 2019-09-01 13:07:35 +02:00 committed by GitHub
commit 71b8a4e081
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 210 additions and 87 deletions

View File

@ -59,8 +59,14 @@ static char morse_repeat;
void morse(const char *msg, char repeat) void morse(const char *msg, char repeat)
{ {
morse_msg = morse_ptr = msg; #if defined(PC_HOSTED)
if (msg)
DEBUG("%s\n", msg);
(void) repeat;
#else
morse_msg = morse_ptr = msg;
morse_repeat = repeat; morse_repeat = repeat;
#endif
} }
bool morse_update(void) bool morse_update(void)

View File

@ -37,7 +37,8 @@
#define PLATFORM_IDENT "StlinkV2/3" #define PLATFORM_IDENT "StlinkV2/3"
#define SET_RUN_STATE(state) #define SET_RUN_STATE(state)
#define SET_IDLE_STATE(state) void stlink_check_detach(int state);
#define SET_IDLE_STATE(state) stlink_check_detach(state)
//#define SET_ERROR_STATE(state) //#define SET_ERROR_STATE(state)
void platform_buffer_flush(void); void platform_buffer_flush(void);

View File

@ -228,7 +228,7 @@ stlink Stlink;
static void exit_function(void) static void exit_function(void)
{ {
libusb_exit(NULL); libusb_exit(NULL);
DEBUG_STLINK("Cleanup\n"); DEBUG("\nCleanup\n");
} }
/* SIGTERM handler. */ /* SIGTERM handler. */
@ -245,6 +245,46 @@ struct trans_ctx {
}; };
int debug_level = 0; int debug_level = 0;
bool has_attached = false;
static int LIBUSB_CALL hotplug_callback_attach(
libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event,
void *user_data)
{
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
has_attached = true;
return 1; /* deregister Callback*/
}
int device_detached = 0;
static int LIBUSB_CALL hotplug_callback_detach(
libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event,
void *user_data)
{
(void)ctx;
(void)dev;
(void)event;
(void)user_data;
device_detached = 1;
return 1; /* deregister Callback*/
}
void stlink_check_detach(int state)
{
if (state == 1) {
/* Check for hotplug events */
struct timeval tv = {0,0};
libusb_handle_events_timeout_completed(
Stlink.libusb_ctx, &tv, &device_detached);
if (device_detached) {
DEBUG("Dongle was detached\n");
exit(0);
}
}
}
static void LIBUSB_CALL on_trans_done(struct libusb_transfer * trans) static void LIBUSB_CALL on_trans_done(struct libusb_transfer * trans)
{ {
@ -319,6 +359,7 @@ static int send_recv(uint8_t *txbuf, size_t txsize,
uint8_t *rxbuf, size_t rxsize) uint8_t *rxbuf, size_t rxsize)
{ {
int res = 0; int res = 0;
stlink_check_detach(1);
if( txsize) { if( txsize) {
int txlen = txsize; int txlen = txsize;
libusb_fill_bulk_transfer(Stlink.req_trans, Stlink.handle, libusb_fill_bulk_transfer(Stlink.req_trans, Stlink.handle,
@ -440,6 +481,7 @@ static int stlink_usb_error_check(uint8_t *data, bool verbose)
case STLINK_SWD_DP_ERROR: case STLINK_SWD_DP_ERROR:
if (verbose) if (verbose)
DEBUG("STLINK_SWD_DP_ERROR\n"); DEBUG("STLINK_SWD_DP_ERROR\n");
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)
@ -487,7 +529,7 @@ static int send_recv_retry(uint8_t *txbuf, size_t txsize,
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
timersub(&now, &start, &diff); timersub(&now, &start, &diff);
if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) { if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) {
DEBUG_STLINK("Failed: "); DEBUG("write_retry failed");
return res; return res;
} }
} }
@ -510,7 +552,7 @@ static int read_retry(uint8_t *txbuf, size_t txsize,
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
timersub(&now, &start, &diff); timersub(&now, &start, &diff);
if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) { if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) {
DEBUG_STLINK("Failed: "); DEBUG("read_retry failed");
return res; return res;
} }
} }
@ -534,7 +576,6 @@ static int write_retry(uint8_t *cmdbuf, size_t cmdsize,
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
timersub(&now, &start, &diff); timersub(&now, &start, &diff);
if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) { if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) {
DEBUG_STLINK("failed");
return res; return res;
} }
} }
@ -645,6 +686,7 @@ void stlink_help(char **argv)
DEBUG("\t-v[1|2]\t\t: Increasing verbosity\n"); DEBUG("\t-v[1|2]\t\t: Increasing verbosity\n");
DEBUG("\t-s \"string\"\t: Use Stlink with (partial) " DEBUG("\t-s \"string\"\t: Use Stlink with (partial) "
"serial number \"string\"\n"); "serial number \"string\"\n");
DEBUG("\t-n\t\t: Exit immediate if no device found\n");
DEBUG("\t-h\t\t: This help.\n"); DEBUG("\t-h\t\t: This help.\n");
exit(0); exit(0);
} }
@ -659,8 +701,12 @@ void stlink_init(int argc, char **argv)
libusb_init(&Stlink.libusb_ctx); libusb_init(&Stlink.libusb_ctx);
char *serial = NULL; char *serial = NULL;
int c; int c;
while((c = getopt(argc, argv, "s:v:h")) != -1) { bool wait_for_attach = true;
while((c = getopt(argc, argv, "ns:v:h")) != -1) {
switch(c) { switch(c) {
case 'n':
wait_for_attach = false;
break;
case 's': case 's':
serial = optarg; serial = optarg;
break; break;
@ -676,14 +722,22 @@ void stlink_init(int argc, char **argv)
r = libusb_init(NULL); r = libusb_init(NULL);
if (r < 0) if (r < 0)
DEBUG("Failed: %s", libusb_strerror(r)); DEBUG("Failed: %s", libusb_strerror(r));
ssize_t cnt = libusb_get_device_list(NULL, &devs); bool hotplug = true;
if (!libusb_has_capability (LIBUSB_CAP_HAS_HOTPLUG)) {
printf("Hotplug capabilites are not supported on this platform\n");
hotplug = false;
}
ssize_t cnt;
rescan:
has_attached = 0;
memset(&Stlink, 0, sizeof(Stlink));
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0) { if (cnt < 0) {
libusb_exit(NULL);
DEBUG("Failed: %s", libusb_strerror(r)); DEBUG("Failed: %s", libusb_strerror(r));
goto error; goto error;
} }
int i = 0; int i = 0;
bool multiple_devices = false; int nr_stlinks = 0;
while ((dev = devs[i++]) != NULL) { while ((dev = devs[i++]) != NULL) {
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);
@ -699,10 +753,8 @@ void stlink_init(int argc, char **argv)
DEBUG("STLINKV1 not supported\n"); DEBUG("STLINKV1 not supported\n");
continue; continue;
} }
if (Stlink.handle) { Stlink.vid = desc.idVendor;
libusb_close(Stlink.handle); Stlink.pid = desc.idProduct;
multiple_devices = (serial)? false : true;
}
r = libusb_open(dev, &Stlink.handle); r = libusb_open(dev, &Stlink.handle);
if (r == LIBUSB_SUCCESS) { if (r == LIBUSB_SUCCESS) {
uint8_t data[32]; uint8_t data[32];
@ -736,44 +788,77 @@ void stlink_init(int argc, char **argv)
} }
if (serial && (!strncmp(Stlink.serial, serial, strlen(serial)))) if (serial && (!strncmp(Stlink.serial, serial, strlen(serial))))
DEBUG("Found "); DEBUG("Found ");
if (!serial || (!strncmp(Stlink.serial, serial, strlen(serial)))) { if (desc.idProduct == PRODUCT_ID_STLINKV2) {
if (desc.idProduct == PRODUCT_ID_STLINKV2) { DEBUG("STLINKV20 serial %s\n", Stlink.serial);
DEBUG("STLINKV20 serial %s\n", Stlink.serial); Stlink.ver_hw = 20;
Stlink.ver_hw = 20; Stlink.ep_tx = 2;
Stlink.ep_tx = 2; } else if (desc.idProduct == PRODUCT_ID_STLINKV21) {
} else if (desc.idProduct == PRODUCT_ID_STLINKV21) { DEBUG("STLINKV21 serial %s\n", Stlink.serial);
DEBUG("STLINKV21 serial %s\n", Stlink.serial); Stlink.ver_hw = 21;
Stlink.ver_hw = 21; Stlink.ep_tx = 1;
Stlink.ep_tx = 1; } else if (desc.idProduct == PRODUCT_ID_STLINKV21_MSD) {
} else if (desc.idProduct == PRODUCT_ID_STLINKV21_MSD) { DEBUG("STLINKV21_MSD serial %s\n", Stlink.serial);
DEBUG("STLINKV21_MSD serial %s\n", Stlink.serial); Stlink.ver_hw = 21;
Stlink.ver_hw = 21; Stlink.ep_tx = 1;
Stlink.ep_tx = 1; } else if (desc.idProduct == PRODUCT_ID_STLINKV3E) {
} else if (desc.idProduct == PRODUCT_ID_STLINKV3E) { DEBUG("STLINKV3E serial %s\n", Stlink.serial);
DEBUG("STLINKV3E serial %s\n", Stlink.serial); Stlink.ver_hw = 30;
Stlink.ver_hw = 30; Stlink.ep_tx = 1;
Stlink.ep_tx = 1; } else if (desc.idProduct == PRODUCT_ID_STLINKV3) {
} else if (desc.idProduct == PRODUCT_ID_STLINKV3) { DEBUG("STLINKV3 serial %s\n", Stlink.serial);
DEBUG("STLINKV3 serial %s\n", Stlink.serial); Stlink.ver_hw = 30;
Stlink.ver_hw = 30; Stlink.ep_tx = 1;
Stlink.ep_tx = 1; } else {
DEBUG("Unknown STLINK variant, serial %s\n", Stlink.serial);
}
nr_stlinks++;
if (serial) {
if (!strncmp(Stlink.serial, serial, strlen(serial))) {
break;
} else { } else {
DEBUG("Unknown STLINK variant, serial %s\n", Stlink.serial); libusb_close(Stlink.handle);
Stlink.handle = 0;
} }
} }
if (serial && (!strncmp(Stlink.serial, serial, strlen(serial))))
break;
} else { } else {
DEBUG("Open failed %s\n", libusb_strerror(r)); DEBUG("Open failed %s\n", libusb_strerror(r));
} }
} }
} }
if (multiple_devices) { libusb_free_device_list(devs, 1);
DEBUG("Multiple Stlinks. Please specify serial number\n");
goto error_1;
}
if (!Stlink.handle) { if (!Stlink.handle) {
DEBUG("No Stlink device found!\n"); if (nr_stlinks && serial) {
DEBUG("No Stlink with given serial number %s\n", serial);
} else if (nr_stlinks > 1) {
DEBUG("Multiple Stlinks. Please specify serial number\n");
goto error;
} else {
DEBUG("No Stlink device found!\n");
}
if (hotplug && wait_for_attach) {
libusb_hotplug_callback_handle hp;
int rc = libusb_hotplug_register_callback
(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 0,
VENDOR_ID_STLINK, LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
hotplug_callback_attach, NULL, &hp);
if (LIBUSB_SUCCESS != rc) {
DEBUG("Error registering attach callback\n");
goto error;
}
DEBUG("Waiting for %sST device%s%s to attach\n",
(serial)? "" : "some ",
(serial)? " with serial ": "",
(serial)? serial: "");
DEBUG("Terminate with ^C\n");
while (has_attached == 0) {
rc = libusb_handle_events (NULL);
if (rc < 0)
printf("libusb_handle_events() failed: %s\n",
libusb_error_name(rc));
}
goto rescan;
}
goto error; goto error;
} }
int config; int config;
@ -797,6 +882,16 @@ void stlink_init(int argc, char **argv)
DEBUG("libusb_claim_interface failed %s\n", libusb_strerror(r)); DEBUG("libusb_claim_interface failed %s\n", libusb_strerror(r));
goto error_1; goto error_1;
} }
if (hotplug) { /* Allow gracefully exit when stlink is unplugged*/
libusb_hotplug_callback_handle hp;
int rc = libusb_hotplug_register_callback
(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 0, Stlink.vid, Stlink.pid,
LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback_detach, NULL, &hp);
if (LIBUSB_SUCCESS != rc) {
DEBUG("Error registering detach callback\n");
goto error;
}
}
Stlink.req_trans = libusb_alloc_transfer(0); Stlink.req_trans = libusb_alloc_transfer(0);
Stlink.rep_trans = libusb_alloc_transfer(0); Stlink.rep_trans = libusb_alloc_transfer(0);
stlink_version(); stlink_version();
@ -827,7 +922,7 @@ void stlink_init(int argc, char **argv)
error_1: error_1:
libusb_close(Stlink.handle); libusb_close(Stlink.handle);
error: error:
libusb_free_device_list(devs, 1); libusb_exit(Stlink.libusb_ctx);
exit(-1); exit(-1);
} }
@ -898,14 +993,8 @@ int stlink_enter_debug_swd(void)
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("Enter SWD\n");
if (send_recv_retry(cmd, 16, data, 2) != STLINK_ERROR_OK) send_recv(cmd, 16, data, 2);
return -1; return stlink_usb_error_check(data, true);
uint8_t cmd1[16] = {STLINK_DEBUG_COMMAND,
STLINK_DEBUG_READCOREID};
uint8_t data1[4];
send_recv(cmd1, 16, data1, 4);
stlink_usb_error_check(data, false);
return 0;
} }
int stlink_enter_debug_jtag(void) int stlink_enter_debug_jtag(void)
@ -1077,8 +1166,7 @@ bool adiv5_ap_setup(int ap)
uint8_t data[2]; uint8_t data[2];
send_recv_retry(cmd, 16, data, 2); send_recv_retry(cmd, 16, data, 2);
DEBUG_STLINK("Open AP %d\n", ap); DEBUG_STLINK("Open AP %d\n", ap);
stlink_usb_error_check(data, true); return (stlink_usb_error_check(data, true))? false: true;
return true;
} }
void adiv5_ap_cleanup(int ap) void adiv5_ap_cleanup(int ap)

View File

@ -32,6 +32,7 @@
# include <netinet/in.h> # include <netinet/in.h>
# include <netinet/tcp.h> # include <netinet/tcp.h>
# include <sys/select.h> # include <sys/select.h>
# include <fcntl.h>
#endif #endif
#include <stdio.h> #include <stdio.h>
@ -100,7 +101,33 @@ unsigned char gdb_if_getchar(void)
while(i <= 0) { while(i <= 0) {
if(gdb_if_conn <= 0) { if(gdb_if_conn <= 0) {
gdb_if_conn = accept(gdb_if_serv, NULL, NULL); #if defined(_WIN32) || defined(__CYGWIN__)
unsigned long opt = 1;
ioctlsocket(gdb_if_serv, FIONBIO, &opt);
#else
int flags = fcntl(gdb_if_serv, F_GETFL);
fcntl(gdb_if_serv, F_SETFL, flags | O_NONBLOCK);
#endif
while(1) {
gdb_if_conn = accept(gdb_if_serv, NULL, NULL);
if (gdb_if_conn == -1) {
if (errno == EWOULDBLOCK) {
SET_IDLE_STATE(1);
platform_delay(100);
} else {
DEBUG("error when accepting connection");
exit(1);
}
} else {
#if defined(_WIN32) || defined(__CYGWIN__)
unsigned long opt = 0;
ioctlsocket(gdb_if_serv, FIONBIO, &opt);
#else
fcntl(gdb_if_serv, F_SETFL, flags);
#endif
break;
}
}
DEBUG("Got connection\n"); DEBUG("Got connection\n");
} }
i = recv(gdb_if_conn, (void*)&ret, 1, 0); i = recv(gdb_if_conn, (void*)&ret, 1, 0);

View File

@ -20,34 +20,31 @@ This flash may have been tested bad, or not have been tested at all,
or, in the best case, was tested good but market requirements made STM sell or, in the best case, was tested good but market requirements made STM sell
it as F103C8. it as F103C8.
Ignoring the chip marking and using an F103C8 blindly as a F103Cb is done Ignoring the chip marking and using an F103C8 blindly as a F103CB is done
already with few problems on many china boards (e.g. blue pill). Probably already with no known problems on many STM board and china boards (e.g. blue
this second approach will work for many of the older STLinks. pill) with genuine STM32. China stlinks clones with a GD32F103x8 will
probably not work. Best is to get new genuine ST hardware. The
dfu-util cares for the size and refuses to programm above the announced size: STLINK-Vmini is < 10 $ without VAT or to resolder a genuine
> dfu-util -S E4D078EA -s 0x08002000:leave -D blackmagic.bin STM32F103CB chip. Think also about using the pc-hosted pc-stlinkv2
dfu-util 0.9 platform on stlinks with revent firmware.
...
dfu-util: Last page at 0x0801093f is not writeable
Flash above the announced size with recent bootloader/BMP: Flash above the announced size with recent bootloader/BMP:
========================================================== ==========================================================
script/stm32_mem.py does not care for the announced size:
Use either the provided python tool, as script/stm32_mem.py
does not care for the announced size and verifies:
> ../scripts/stm32_mem.py blackmagic.bin > ../scripts/stm32_mem.py blackmagic.bin
...
USB Device Firmware Upgrade - Host Utility -- version 1.2
...
Programming memory at 0x08010800
All operations complete!
Get length of binary or compile and use the upgrade executable.
> ls -l blackmagic.bin
-rwxr-xr-x 1 bon users 59712 21. Sep 22:47 blackmagic.bin
Actual file size may differ!
Upload binary from flash with the exact size > cd upgrade
> dfu-util -s 0x08002000:leave:force:59712 -U blackmagic.bin.1 > make (PROBE_HOST=...)
> ./blackmagic_upgrade
Compare To long to read
> diff blackmagic.bin* ===============
No differences should get reported! Use the BMP provided upgrade tools:
- scripts/stm32_mem.py
- Compiled upgrade tool in upgrade
Only if mismatch is reported, think further.

View File

@ -491,7 +491,10 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
ap = adiv5_new_ap(dp, i); ap = adiv5_new_ap(dp, i);
if (ap == NULL) { if (ap == NULL) {
adiv5_ap_cleanup(i); adiv5_ap_cleanup(i);
continue; if (i == 0)
return;
else
continue;
} }
extern void kinetis_mdm_probe(ADIv5_AP_t *); extern void kinetis_mdm_probe(ADIv5_AP_t *);
kinetis_mdm_probe(ap); kinetis_mdm_probe(ap);

View File

@ -451,17 +451,18 @@ static void cortexm_regs_read(target *t, void *data)
{ {
uint32_t *regs = data; uint32_t *regs = data;
ADIv5_AP_t *ap = cortexm_ap(t); ADIv5_AP_t *ap = cortexm_ap(t);
unsigned i;
#if defined(STLINKV2) #if defined(STLINKV2)
uint32_t base_regs[21];
extern void stlink_regs_read(ADIv5_AP_t *ap, void *data); extern void stlink_regs_read(ADIv5_AP_t *ap, void *data);
extern uint32_t stlink_reg_read(ADIv5_AP_t *ap, int idx); extern uint32_t stlink_reg_read(ADIv5_AP_t *ap, int idx);
stlink_regs_read(ap, data); stlink_regs_read(ap, base_regs);
regs += sizeof(regnum_cortex_m); for(i = 0; i < sizeof(regnum_cortex_m) / 4; i++)
*regs++ = base_regs[regnum_cortex_m[i]];
if (t->target_options & TOPT_FLAVOUR_V7MF) if (t->target_options & TOPT_FLAVOUR_V7MF)
for(size_t t = 0; t < sizeof(regnum_cortex_mf) / 4; t++) for(size_t t = 0; t < sizeof(regnum_cortex_mf) / 4; t++)
*regs++ = stlink_reg_read(ap, regnum_cortex_mf[t]); *regs++ = stlink_reg_read(ap, regnum_cortex_mf[t]);
#else #else
unsigned i;
/* FIXME: Describe what's really going on here */ /* FIXME: Describe what's really going on here */
adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD); adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD);
@ -494,14 +495,14 @@ static void cortexm_regs_write(target *t, const void *data)
ADIv5_AP_t *ap = cortexm_ap(t); ADIv5_AP_t *ap = cortexm_ap(t);
#if defined(STLINKV2) #if defined(STLINKV2)
extern void stlink_reg_write(ADIv5_AP_t *ap, int num, uint32_t val); extern void stlink_reg_write(ADIv5_AP_t *ap, int num, uint32_t val);
for(size_t z = 1; z < sizeof(regnum_cortex_m) / 4; z++) { for(size_t z = 0; z < sizeof(regnum_cortex_m) / 4; z++) {
stlink_reg_write(ap, regnum_cortex_m[z], *regs); stlink_reg_write(ap, regnum_cortex_m[z], *regs);
regs++; regs++;
}
if (t->target_options & TOPT_FLAVOUR_V7MF) if (t->target_options & TOPT_FLAVOUR_V7MF)
for(size_t z = 0; z < sizeof(regnum_cortex_mf) / 4; z++) { for(size_t z = 0; z < sizeof(regnum_cortex_mf) / 4; z++) {
stlink_reg_write(ap, regnum_cortex_mf[z], *regs); stlink_reg_write(ap, regnum_cortex_mf[z], *regs);
regs++; regs++;
}
} }
#else #else
unsigned i; unsigned i;

View File

@ -36,7 +36,7 @@ endif
bindata.o: $(PROBE_HOST).d bindata.o: $(PROBE_HOST).d
$(PROBE_HOST).d: ../src/blackmagic.bin $(PROBE_HOST).d: $(wildcard ../src/blackmagic.bin)
-rm *.d -rm *.d
make -C ../src $0 clean make -C ../src $0 clean
make -C ../src $0 make -C ../src $0