diff --git a/src/morse.c b/src/morse.c index 6b17c16..55db0ba 100644 --- a/src/morse.c +++ b/src/morse.c @@ -59,8 +59,14 @@ static char morse_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; +#endif } bool morse_update(void) diff --git a/src/platforms/pc-stlinkv2/platform.h b/src/platforms/pc-stlinkv2/platform.h index a100a06..7db112d 100644 --- a/src/platforms/pc-stlinkv2/platform.h +++ b/src/platforms/pc-stlinkv2/platform.h @@ -37,7 +37,8 @@ #define PLATFORM_IDENT "StlinkV2/3" #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) void platform_buffer_flush(void); diff --git a/src/platforms/pc-stlinkv2/stlinkv2.c b/src/platforms/pc-stlinkv2/stlinkv2.c index f3de39e..86c7a1e 100644 --- a/src/platforms/pc-stlinkv2/stlinkv2.c +++ b/src/platforms/pc-stlinkv2/stlinkv2.c @@ -228,7 +228,7 @@ stlink Stlink; static void exit_function(void) { libusb_exit(NULL); - DEBUG_STLINK("Cleanup\n"); + DEBUG("\nCleanup\n"); } /* SIGTERM handler. */ @@ -245,6 +245,46 @@ struct trans_ctx { }; 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) { @@ -319,6 +359,7 @@ static int send_recv(uint8_t *txbuf, size_t txsize, uint8_t *rxbuf, size_t rxsize) { int res = 0; + stlink_check_detach(1); if( txsize) { int txlen = txsize; 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: if (verbose) DEBUG("STLINK_SWD_DP_ERROR\n"); + raise_exception(EXCEPTION_ERROR, "STLINK_SWD_DP_ERROR"); return STLINK_ERROR_FAIL; case STLINK_SWD_DP_PARITY_ERROR: if (verbose) @@ -487,7 +529,7 @@ static int send_recv_retry(uint8_t *txbuf, size_t txsize, gettimeofday(&now, NULL); timersub(&now, &start, &diff); if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) { - DEBUG_STLINK("Failed: "); + DEBUG("write_retry failed"); return res; } } @@ -510,7 +552,7 @@ static int read_retry(uint8_t *txbuf, size_t txsize, gettimeofday(&now, NULL); timersub(&now, &start, &diff); if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) { - DEBUG_STLINK("Failed: "); + DEBUG("read_retry failed"); return res; } } @@ -534,7 +576,6 @@ static int write_retry(uint8_t *cmdbuf, size_t cmdsize, gettimeofday(&now, NULL); timersub(&now, &start, &diff); if ((diff.tv_sec >= 1) || (res != STLINK_ERROR_WAIT)) { - DEBUG_STLINK("failed"); return res; } } @@ -645,6 +686,7 @@ void stlink_help(char **argv) DEBUG("\t-v[1|2]\t\t: Increasing verbosity\n"); DEBUG("\t-s \"string\"\t: Use Stlink with (partial) " "serial number \"string\"\n"); + DEBUG("\t-n\t\t: Exit immediate if no device found\n"); DEBUG("\t-h\t\t: This help.\n"); exit(0); } @@ -659,8 +701,12 @@ void stlink_init(int argc, char **argv) libusb_init(&Stlink.libusb_ctx); char *serial = NULL; 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) { + case 'n': + wait_for_attach = false; + break; case 's': serial = optarg; break; @@ -676,14 +722,22 @@ void stlink_init(int argc, char **argv) r = libusb_init(NULL); if (r < 0) 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) { - libusb_exit(NULL); DEBUG("Failed: %s", libusb_strerror(r)); goto error; } int i = 0; - bool multiple_devices = false; + int nr_stlinks = 0; while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor 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"); continue; } - if (Stlink.handle) { - libusb_close(Stlink.handle); - multiple_devices = (serial)? false : true; - } + Stlink.vid = desc.idVendor; + Stlink.pid = desc.idProduct; r = libusb_open(dev, &Stlink.handle); if (r == LIBUSB_SUCCESS) { uint8_t data[32]; @@ -736,44 +788,77 @@ void stlink_init(int argc, char **argv) } if (serial && (!strncmp(Stlink.serial, serial, strlen(serial)))) DEBUG("Found "); - if (!serial || (!strncmp(Stlink.serial, serial, strlen(serial)))) { - if (desc.idProduct == PRODUCT_ID_STLINKV2) { - DEBUG("STLINKV20 serial %s\n", Stlink.serial); - Stlink.ver_hw = 20; - Stlink.ep_tx = 2; - } else if (desc.idProduct == PRODUCT_ID_STLINKV21) { - DEBUG("STLINKV21 serial %s\n", Stlink.serial); - Stlink.ver_hw = 21; - Stlink.ep_tx = 1; - } else if (desc.idProduct == PRODUCT_ID_STLINKV21_MSD) { - DEBUG("STLINKV21_MSD serial %s\n", Stlink.serial); - Stlink.ver_hw = 21; - Stlink.ep_tx = 1; - } else if (desc.idProduct == PRODUCT_ID_STLINKV3E) { - DEBUG("STLINKV3E serial %s\n", Stlink.serial); - Stlink.ver_hw = 30; - Stlink.ep_tx = 1; - } else if (desc.idProduct == PRODUCT_ID_STLINKV3) { - DEBUG("STLINKV3 serial %s\n", Stlink.serial); - Stlink.ver_hw = 30; - Stlink.ep_tx = 1; + if (desc.idProduct == PRODUCT_ID_STLINKV2) { + DEBUG("STLINKV20 serial %s\n", Stlink.serial); + Stlink.ver_hw = 20; + Stlink.ep_tx = 2; + } else if (desc.idProduct == PRODUCT_ID_STLINKV21) { + DEBUG("STLINKV21 serial %s\n", Stlink.serial); + Stlink.ver_hw = 21; + Stlink.ep_tx = 1; + } else if (desc.idProduct == PRODUCT_ID_STLINKV21_MSD) { + DEBUG("STLINKV21_MSD serial %s\n", Stlink.serial); + Stlink.ver_hw = 21; + Stlink.ep_tx = 1; + } else if (desc.idProduct == PRODUCT_ID_STLINKV3E) { + DEBUG("STLINKV3E serial %s\n", Stlink.serial); + Stlink.ver_hw = 30; + Stlink.ep_tx = 1; + } else if (desc.idProduct == PRODUCT_ID_STLINKV3) { + DEBUG("STLINKV3 serial %s\n", Stlink.serial); + Stlink.ver_hw = 30; + 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 { - 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 { DEBUG("Open failed %s\n", libusb_strerror(r)); } } } - if (multiple_devices) { - DEBUG("Multiple Stlinks. Please specify serial number\n"); - goto error_1; - } + libusb_free_device_list(devs, 1); 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; } int config; @@ -797,6 +882,16 @@ void stlink_init(int argc, char **argv) DEBUG("libusb_claim_interface failed %s\n", libusb_strerror(r)); 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.rep_trans = libusb_alloc_transfer(0); stlink_version(); @@ -827,7 +922,7 @@ void stlink_init(int argc, char **argv) error_1: libusb_close(Stlink.handle); error: - libusb_free_device_list(devs, 1); + libusb_exit(Stlink.libusb_ctx); exit(-1); } @@ -898,14 +993,8 @@ int stlink_enter_debug_swd(void) STLINK_DEBUG_ENTER_SWD_NO_RESET}; uint8_t data[2]; DEBUG("Enter SWD\n"); - if (send_recv_retry(cmd, 16, data, 2) != STLINK_ERROR_OK) - return -1; - 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; + send_recv(cmd, 16, data, 2); + return stlink_usb_error_check(data, true); } int stlink_enter_debug_jtag(void) @@ -1077,8 +1166,7 @@ bool adiv5_ap_setup(int ap) uint8_t data[2]; send_recv_retry(cmd, 16, data, 2); DEBUG_STLINK("Open AP %d\n", ap); - stlink_usb_error_check(data, true); - return true; + return (stlink_usb_error_check(data, true))? false: true; } void adiv5_ap_cleanup(int ap) diff --git a/src/platforms/pc/gdb_if.c b/src/platforms/pc/gdb_if.c index 5da42da..b5583b6 100644 --- a/src/platforms/pc/gdb_if.c +++ b/src/platforms/pc/gdb_if.c @@ -32,6 +32,7 @@ # include # include # include +# include #endif #include @@ -100,7 +101,33 @@ unsigned char gdb_if_getchar(void) while(i <= 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"); } i = recv(gdb_if_conn, (void*)&ret, 1, 0); diff --git a/src/platforms/stlink/Flashsize_F103 b/src/platforms/stlink/Flashsize_F103 index c6b55a2..24047b5 100644 --- a/src/platforms/stlink/Flashsize_F103 +++ b/src/platforms/stlink/Flashsize_F103 @@ -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 it as F103C8. -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 -this second approach will work for many of the older STLinks. - -dfu-util cares for the size and refuses to programm above the announced size: - > dfu-util -S E4D078EA -s 0x08002000:leave -D blackmagic.bin - dfu-util 0.9 - ... - dfu-util: Last page at 0x0801093f is not writeable +Ignoring the chip marking and using an F103C8 blindly as a F103CB is done +already with no known problems on many STM board and china boards (e.g. blue +pill) with genuine STM32. China stlinks clones with a GD32F103x8 will +probably not work. Best is to get new genuine ST hardware. The +STLINK-Vmini is < 10 $ without VAT or to resolder a genuine +STM32F103CB chip. Think also about using the pc-hosted pc-stlinkv2 +platform on stlinks with revent firmware. 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 - ... - USB Device Firmware Upgrade - Host Utility -- version 1.2 - ... - Programming memory at 0x08010800 - All operations complete! -Get length of binary - > ls -l blackmagic.bin - -rwxr-xr-x 1 bon users 59712 21. Sep 22:47 blackmagic.bin -Actual file size may differ! +or compile and use the upgrade executable. -Upload binary from flash with the exact size - > dfu-util -s 0x08002000:leave:force:59712 -U blackmagic.bin.1 +> cd upgrade +> make (PROBE_HOST=...) +> ./blackmagic_upgrade -Compare - > diff blackmagic.bin* -No differences should get reported! +To long to read +=============== +Use the BMP provided upgrade tools: +- scripts/stm32_mem.py +- Compiled upgrade tool in upgrade +Only if mismatch is reported, think further. diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 0e507c1..66c45a9 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -491,7 +491,10 @@ void adiv5_dp_init(ADIv5_DP_t *dp) ap = adiv5_new_ap(dp, i); if (ap == NULL) { adiv5_ap_cleanup(i); - continue; + if (i == 0) + return; + else + continue; } extern void kinetis_mdm_probe(ADIv5_AP_t *); kinetis_mdm_probe(ap); diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 882022d..a67b599 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -451,17 +451,18 @@ static void cortexm_regs_read(target *t, void *data) { uint32_t *regs = data; ADIv5_AP_t *ap = cortexm_ap(t); + unsigned i; #if defined(STLINKV2) + uint32_t base_regs[21]; extern void stlink_regs_read(ADIv5_AP_t *ap, void *data); extern uint32_t stlink_reg_read(ADIv5_AP_t *ap, int idx); - stlink_regs_read(ap, data); - regs += sizeof(regnum_cortex_m); + stlink_regs_read(ap, base_regs); + for(i = 0; i < sizeof(regnum_cortex_m) / 4; i++) + *regs++ = base_regs[regnum_cortex_m[i]]; if (t->target_options & TOPT_FLAVOUR_V7MF) for(size_t t = 0; t < sizeof(regnum_cortex_mf) / 4; t++) *regs++ = stlink_reg_read(ap, regnum_cortex_mf[t]); #else - unsigned i; - /* FIXME: Describe what's really going on here */ 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); #if defined(STLINKV2) 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); regs++; + } if (t->target_options & TOPT_FLAVOUR_V7MF) for(size_t z = 0; z < sizeof(regnum_cortex_mf) / 4; z++) { stlink_reg_write(ap, regnum_cortex_mf[z], *regs); regs++; - } } #else unsigned i; diff --git a/upgrade/Makefile b/upgrade/Makefile index 17d898e..9f7285d 100644 --- a/upgrade/Makefile +++ b/upgrade/Makefile @@ -36,7 +36,7 @@ endif bindata.o: $(PROBE_HOST).d -$(PROBE_HOST).d: ../src/blackmagic.bin +$(PROBE_HOST).d: $(wildcard ../src/blackmagic.bin) -rm *.d make -C ../src $0 clean make -C ../src $0