From d39dc343827a2c4f2c64f7b76ddf42806812fae4 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Wed, 28 Aug 2019 20:28:25 +0200 Subject: [PATCH 1/5] pc-stlinkv2: Fix reg_read|write - Fix wrong placed brace in cortexm_regs_write() - Start writing with r0 - With register read, save only registers listed --- src/target/cortexm.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 882022d1..a67b5994 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; From 80a9fd51ca0c904ed689aaf2fe1467dc8f474613 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 29 Aug 2019 13:35:20 +0200 Subject: [PATCH 2/5] Clarify STM32F103x8 Flashsize handling. Should finally fix #471. --- src/platforms/stlink/Flashsize_F103 | 45 ++++++++++++++--------------- upgrade/Makefile | 2 +- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/platforms/stlink/Flashsize_F103 b/src/platforms/stlink/Flashsize_F103 index c6b55a24..24047b5a 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/upgrade/Makefile b/upgrade/Makefile index 17d898ed..9f7285d1 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 From 86d0be97081b4e394fdd82d665a3b5c4ad3eba00 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 31 Aug 2019 17:08:14 +0200 Subject: [PATCH 3/5] pc-hosted: Display morse message on controlling terminal. --- src/morse.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/morse.c b/src/morse.c index 6b17c16b..55db0ba0 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) From 6f1cae9203004e3bd91357e56b7ffddce2ce0884 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 31 Aug 2019 12:32:23 +0200 Subject: [PATCH 4/5] pc-stlinkv2: Wait for device attach. --- src/platforms/pc-stlinkv2/stlinkv2.c | 67 +++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/src/platforms/pc-stlinkv2/stlinkv2.c b/src/platforms/pc-stlinkv2/stlinkv2.c index f7aeb4cc..441a5f2a 100644 --- a/src/platforms/pc-stlinkv2/stlinkv2.c +++ b/src/platforms/pc-stlinkv2/stlinkv2.c @@ -245,6 +245,19 @@ 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 0; +} static void LIBUSB_CALL on_trans_done(struct libusb_transfer * trans) { @@ -645,6 +658,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 +673,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,9 +694,17 @@ 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; } @@ -769,13 +795,40 @@ void stlink_init(int argc, char **argv) } } } + libusb_free_device_list(devs, 1); if (!Stlink.handle) { - if (nr_stlinks && serial) + if (nr_stlinks && serial) { DEBUG("No Stlink with given serial number %s\n", serial); - else if (nr_stlinks > 1) + } else if (nr_stlinks > 1) { DEBUG("Multiple Stlinks. Please specify serial number\n"); - else + 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; @@ -829,7 +882,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); } From 1d868bfffbfd38fe4d5e3f75213bfb23e6ea3321 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sat, 31 Aug 2019 15:27:16 +0200 Subject: [PATCH 5/5] pc-stlinkv2: Detect stlink detach. As libusb has no real async callback, we need to call libusb_handle_events() in different places. While waiting for the gdb connection, we set the socket to non-blocking and check additional for usb events in that loop. That way, detach is also detected while waiting for connection. With debugger attached, SET_IDLE_STATE ist missused for checking for usb events. --- src/platforms/pc-stlinkv2/platform.h | 3 +- src/platforms/pc-stlinkv2/stlinkv2.c | 44 ++++++++++++++++++++++++++-- src/platforms/pc/gdb_if.c | 29 +++++++++++++++++- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/platforms/pc-stlinkv2/platform.h b/src/platforms/pc-stlinkv2/platform.h index a100a063..7db112d4 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 441a5f2a..86c7a1ec 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. */ @@ -256,7 +256,34 @@ static int LIBUSB_CALL hotplug_callback_attach( (void)event; (void)user_data; has_attached = true; - return 0; + 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) @@ -332,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, @@ -725,6 +753,8 @@ void stlink_init(int argc, char **argv) DEBUG("STLINKV1 not supported\n"); continue; } + Stlink.vid = desc.idVendor; + Stlink.pid = desc.idProduct; r = libusb_open(dev, &Stlink.handle); if (r == LIBUSB_SUCCESS) { uint8_t data[32]; @@ -852,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(); diff --git a/src/platforms/pc/gdb_if.c b/src/platforms/pc/gdb_if.c index 5da42da4..b5583b6f 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);