From afaded2782ca193841198a5451b2bec89998a7e3 Mon Sep 17 00:00:00 2001 From: nightwalker-87 <15526941+Nightwalker-87@users.noreply.github.com> Date: Sat, 22 Feb 2020 17:50:31 +0100 Subject: [PATCH 1/2] General Project Update - Formatting fixes in CHANGELOG.md - Added comment in .travis.sh - Update for .travis.yml: gcc/g++ v5->v6 --- .travis.sh | 2 +- .travis.yml | 13 ++++++++----- CHANGELOG.md | 14 +++++++------- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.travis.sh b/.travis.sh index 06e95ef80..05568d37d 100755 --- a/.travis.sh +++ b/.travis.sh @@ -8,7 +8,7 @@ echo "----" if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq || true sudo apt-get install -qq -y --no-install-recommends libgtk-3-dev -else +else #("$TRAVIS_OS_NAME" == "osx") brew install libusb fi diff --git a/.travis.yml b/.travis.yml index c878be799..b0f985012 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,24 @@ -language: c + compiler: - gcc - clang + +language: c + os: - linux - osx + addons: apt: sources: -# - llvm-toolchain-precise-3.8 - sourceline: 'ppa:ubuntu-toolchain-r/test' packages: - clang -# - clang-3.8 - - g++-5 - - gcc-5 + - g++-6 + - gcc-6 - libusb-1.0.0-dev + script: - git fetch --tags - printenv diff --git a/CHANGELOG.md b/CHANGELOG.md index f122e77ec..25abd0a54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ Release date: 2020-02-20 Major changes and added features: * Added O_BINARY option to open file ([#753](https://github.com/texane/stlink/pull/753)) -* Added preliminary support for some STM32G0 chips ([#759](https://github.com/texane/stlink/pull/759)) ([#760](https://github.com/texane/stlink/pull/760)) +* Added preliminary support for some STM32G0 chips ([#759](https://github.com/texane/stlink/pull/759), [#760](https://github.com/texane/stlink/pull/760)) * Added support for mass erasing second bank on STM32F10x_XL ([#767](https://github.com/texane/stlink/pull/767)) * Added call to clear PG bit after writing to flash ([#773](https://github.com/texane/stlink/pull/773)) * Added howto for sending NRST signal through GDB ([#776](https://github.com/texane/stlink/pull/776)) @@ -39,7 +39,7 @@ Updates and fixes: * Fixed package name "devscripts" in doc/compiling.md ([#775](https://github.com/texane/stlink/pull/775)) * Fixed apparent STM32G0 flashing issue ([#797](https://github.com/texane/stlink/pull/797)) * Fixed few potential memory/resource leaks ([#803](https://github.com/texane/stlink/pull/803)) -* Fixed flash verification error on STM32WB55RG ([#810](https://github.com/texane/stlink/pull/810)) ([#816](https://github.com/texane/stlink/pull/816)) +* Fixed flash verification error on STM32WB55RG ([#810](https://github.com/texane/stlink/pull/810), [#816](https://github.com/texane/stlink/pull/816)) * Do not issue JTAG reset on stlink-v1 (Gwenhael Goavec-Merou) * Fixed flash size of STM32 Discovery vl (Gwenhael Goavec-Merou) * Added support for writing option bytes on STM32L0 (Adrian Imboden) @@ -63,10 +63,10 @@ Major changes and added features: * Updated libusb to 1.0.22 ([#695](https://github.com/texane/stlink/pull/695)) * Added desktop file for linux ([#688](https://github.com/texane/stlink/pull/688)) * Added icons for stlink GUI ([#697](https://github.com/texane/stlink/pull/697)) -* Added support for STM32L4R9 target ([#694](https://github.com/texane/stlink/pull/694), [#699](https://github.com/texane/stlink/pull/699) +* Added support for STM32L4R9 target ([#694](https://github.com/texane/stlink/pull/694), [#699](https://github.com/texane/stlink/pull/699)) * Added creation of icons for .desktop file ([#708](https://github.com/texane/stlink/pull/708)) * Added memory map for STM32F411RE target ([#709](https://github.com/texane/stlink/pull/709)) -* Added reset through AIRCR ([#540](https://github.com/texane/stlink/pull/540), [#712](https://github.com/texane/stlink/pull/712) +* Added reset through AIRCR ([#540](https://github.com/texane/stlink/pull/540), [#712](https://github.com/texane/stlink/pull/712)) * Implemented intel hex support for GTK GUI ([#718](https://github.com/texane/stlink/pull/718)) Fixes: @@ -74,12 +74,12 @@ Fixes: * Fixed missing flash_loader for L011 ([#675](https://github.com/texane/stlink/pull/675)) * Fixed serial number size mismatch with stlink_open_usb() ([#680](https://github.com/texane/stlink/pull/680)) * Debian packaging, CMake and README.md fixes ([#683](https://github.com/texane/stlink/pull/683)) -* Fix for stlink library calls exit() or _exit() ([#634](https://github.com/texane/stlink/pull/634), [#696](https://github.com/texane/stlink/pull/696) -* Fix for libusb deprecation ([#703](https://github.com/texane/stlink/pull/703), [#704](https://github.com/texane/stlink/pull/704) +* Fix for stlink library calls exit() or _exit() ([#634](https://github.com/texane/stlink/pull/634), [#696](https://github.com/texane/stlink/pull/696)) +* Fix for libusb deprecation ([#703](https://github.com/texane/stlink/pull/703), [#704](https://github.com/texane/stlink/pull/704)) * Renamed STLINK_CHIPID_STM32_L4R9 to STLINK_CHIPID_STM32_L4RX ([#706](https://github.com/texane/stlink/pull/706)) * Fixed flash memory map for F72XXX target ([#711](https://github.com/texane/stlink/pull/711)) * Proper flash page size calculation for F412 target ([#721](https://github.com/texane/stlink/pull/721)) -* Return correct value on EOF for Semihosting SYS_READ ([#725](https://github.com/texane/stlink/pull/725), [#726](https://github.com/texane/stlink/pull/726, [#729](https://github.com/texane/stlink/pull/729, [#731](https://github.com/texane/stlink/pull/731) +* Return correct value on EOF for Semihosting SYS_READ ([#725](https://github.com/texane/stlink/pull/725), [#726](https://github.com/texane/stlink/pull/726), [#729](https://github.com/texane/stlink/pull/729), [#731](https://github.com/texane/stlink/pull/731)) * Fix for mem_write() ([#730](https://github.com/texane/stlink/pull/730)) * FreeBSD defines LIBUSB_API_VERSION instead of LIBUSBX_API_VERSION ([#733](https://github.com/texane/stlink/pull/733)) From 09ea99aea51f741ce9c8c0e2ad755d40b3d86021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikl=C3=B3s=20M=C3=A1rton?= Date: Mon, 24 Feb 2020 21:34:36 +0100 Subject: [PATCH 2/2] Add support for STLink V3 Flash programming is broken --- include/stlink.h | 68 ++++++- include/stlink/commands.h | 48 +++-- include/stlink/tools/flash.h | 2 +- include/stlink/usb.h | 14 +- src/common.c | 100 ++++++---- src/flash_loader.c | 4 +- src/gdbserver/gdb-server.c | 2 +- src/logging.c | 2 +- src/sg.c | 20 +- src/tools/flash.c | 10 +- src/usb.c | 368 ++++++++++++++++++++++++++++------- 11 files changed, 479 insertions(+), 159 deletions(-) diff --git a/include/stlink.h b/include/stlink.h index d4170c7a7..f9de94fd4 100644 --- a/include/stlink.h +++ b/include/stlink.h @@ -24,10 +24,17 @@ extern "C" { //#define Q_BUF_LEN 96 #define Q_BUF_LEN (1024 * 100) - // STLINK_DEBUG_RESETSYS, etc: +// STLINK_DEBUG_RESETSYS, etc: +enum target_state { + TARGET_UNKNOWN = 0, + TARGET_RUNNING = 1, + TARGET_HALTED = 2, + TARGET_RESET = 3, + TARGET_DEBUG_RUNNING = 4, +}; + #define STLINK_CORE_RUNNING 0x80 #define STLINK_CORE_HALTED 0x81 -#define STLINK_CORE_STAT_UNKNOWN -1 #define STLINK_GET_VERSION 0xf1 #define STLINK_GET_CURRENT_MODE 0xf5 @@ -52,6 +59,11 @@ extern "C" { #define STLINK_DEBUG_APIV2_SWD_SET_FREQ 0x43 +#define STLINK_APIV3_SET_COM_FREQ 0x61 +#define STLINK_APIV3_GET_COM_FREQ 0x62 + +#define STLINK_APIV3_GET_VERSION_EX 0xFB + // Baud rate divisors for SWDCLK #define STLINK_SWDCLK_4MHZ_DIVISOR 0 #define STLINK_SWDCLK_1P8MHZ_DIVISOR 1 @@ -68,7 +80,45 @@ extern "C" { #define STLINK_SERIAL_MAX_SIZE 64 - /* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/ +#define STLINK_V3_MAX_FREQ_NB 10 + +/* Cortex Debug Control Block */ +#define DCB_DHCSR 0xE000EDF0 +#define DCB_DCRSR 0xE000EDF4 +#define DCB_DCRDR 0xE000EDF8 +#define DCB_DEMCR 0xE000EDFC + +/* DCB_DHCSR bit and field definitions */ +#define DBGKEY (0xA05F << 16) +#define C_DEBUGEN (1 << 0) +#define C_HALT (1 << 1) +#define C_STEP (1 << 2) +#define C_MASKINTS (1 << 3) +#define S_REGRDY (1 << 16) +#define S_HALT (1 << 17) +#define S_SLEEP (1 << 18) +#define S_LOCKUP (1 << 19) +#define S_RETIRE_ST (1 << 24) +#define S_RESET_ST (1 << 25) + + +/* + * Map the relevant features, quirks and workaround for specific firmware + * version of stlink + */ +#define STLINK_F_HAS_TRACE (1<<0) +#define STLINK_F_HAS_SWD_SET_FREQ (1<<1) +#define STLINK_F_HAS_JTAG_SET_FREQ (1<<2) +#define STLINK_F_HAS_MEM_16BIT (1<<3) +#define STLINK_F_HAS_GETLASTRWSTATUS2 (1<<4) +#define STLINK_F_HAS_DAP_REG (1<<5) +#define STLINK_F_QUIRK_JTAG_DP_READ (1<<6) +#define STLINK_F_HAS_AP_INIT (1<<7) +#define STLINK_F_HAS_DPBANKSEL (1<<8) +#define STLINK_F_HAS_RW8_512BYTES (1<<9) + + +/* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/ #define C_BUF_LEN 32 enum stlink_flash_type { @@ -111,12 +161,22 @@ typedef struct flash_loader { uint8_t revision; } cortex_m3_cpuid_t; + enum stlink_jtag_api_version { + STLINK_JTAG_API_V1 = 1, + STLINK_JTAG_API_V2, + STLINK_JTAG_API_V3, + }; + typedef struct stlink_version_ { uint32_t stlink_v; uint32_t jtag_v; uint32_t swim_v; uint32_t st_vid; uint32_t stlink_pid; + /** jtag api version supported */ + enum stlink_jtag_api_version jtag_api; + /** one bit for each feature supported. See macros STLINK_F_* */ + uint32_t flags; } stlink_version_t; enum transport_type { @@ -144,7 +204,7 @@ typedef struct flash_loader { int verbose; uint32_t core_id; // set by stlink_core_id(), result from STLINK_DEBUGREADCOREID uint32_t chip_id; // set by stlink_load_device_params(), used to identify flash and sram - int core_stat; // set by stlink_status(), values STLINK_CORE_xxxxx + enum target_state core_stat; // set by stlink_status() char serial[STLINK_SERIAL_MAX_SIZE]; int serial_size; diff --git a/include/stlink/commands.h b/include/stlink/commands.h index 9ff5a8fb9..a6830ff26 100644 --- a/include/stlink/commands.h +++ b/include/stlink/commands.h @@ -2,25 +2,35 @@ #define STLINK_COMMANDS_H_ enum stlink_debug_commands { - STLINK_DEBUG_ENTER_JTAG = 0x00, - STLINK_DEBUG_GETSTATUS = 0x01, - STLINK_DEBUG_FORCEDEBUG = 0x02, - STLINK_DEBUG_RESETSYS = 0x03, - STLINK_DEBUG_READALLREGS = 0x04, - STLINK_DEBUG_READREG = 0x05, - STLINK_DEBUG_WRITEREG = 0x06, - STLINK_DEBUG_READMEM_32BIT = 0x07, - STLINK_DEBUG_WRITEMEM_32BIT = 0x08, - STLINK_DEBUG_RUNCORE = 0x09, - STLINK_DEBUG_STEPCORE = 0x0a, - STLINK_DEBUG_SETFP = 0x0b, - STLINK_DEBUG_WRITEMEM_8BIT = 0x0d, - STLINK_DEBUG_CLEARFP = 0x0e, - STLINK_DEBUG_WRITEDEBUGREG = 0x0f, - STLINK_DEBUG_ENTER = 0x20, - STLINK_DEBUG_EXIT = 0x21, - STLINK_DEBUG_READCOREID = 0x22, - STLINK_DEBUG_ENTER_SWD = 0xa3 + STLINK_DEBUG_ENTER_JTAG = 0x00, + STLINK_DEBUG_GETSTATUS = 0x01, + STLINK_DEBUG_FORCEDEBUG = 0x02, + STLINK_DEBUG_APIV1_RESETSYS = 0x03, + STLINK_DEBUG_APIV1_READALLREGS = 0x04, + STLINK_DEBUG_APIV1_READREG = 0x05, + STLINK_DEBUG_APIV1_WRITEREG = 0x06, + STLINK_DEBUG_READMEM_32BIT = 0x07, + STLINK_DEBUG_WRITEMEM_32BIT = 0x08, + STLINK_DEBUG_RUNCORE = 0x09, + STLINK_DEBUG_STEPCORE = 0x0a, + STLINK_DEBUG_APIV1_SETFP = 0x0b, + STLINK_DEBUG_WRITEMEM_8BIT = 0x0d, + STLINK_DEBUG_APIV1_CLEARFP = 0x0e, + STLINK_DEBUG_APIV1_WRITEDEBUGREG = 0x0f, + STLINK_DEBUG_APIV1_ENTER = 0x20, + STLINK_DEBUG_EXIT = 0x21, + STLINK_DEBUG_READCOREID = 0x22, + STLINK_DEBUG_APIV2_ENTER = 0x30, + STLINK_DEBUG_APIV2_READ_IDCODES = 0x31, + STLINK_DEBUG_APIV2_RESETSYS = 0x32, + STLINK_DEBUG_APIV2_READREG = 0x33, + STLINK_DEBUG_APIV2_WRITEREG = 0x34, + STLINK_DEBUG_APIV2_WRITEDEBUGREG = 0x35, + STLINK_DEBUG_APIV2_READDEBUGREG = 0x36, + STLINK_DEBUG_APIV2_READALLREGS = 0x3A, + STLINK_DEBUG_APIV2_GETLASTRWSTATUS = 0x3B, + STLINK_DEBUG_APIV2_GETLASTRWSTATUS2 = 0x3E, + STLINK_DEBUG_ENTER_SWD = 0xa3 }; #endif /* STLINK_COMMANDS_H_ */ diff --git a/include/stlink/tools/flash.h b/include/stlink/tools/flash.h index 8ca1eddf9..6851ede8b 100644 --- a/include/stlink/tools/flash.h +++ b/include/stlink/tools/flash.h @@ -5,7 +5,7 @@ #include #define DEBUG_LOG_LEVEL 100 -#define STND_LOG_LEVEL 50 +#define STND_LOG_LEVEL 100 enum flash_cmd {FLASH_CMD_NONE = 0, FLASH_CMD_WRITE = 1, FLASH_CMD_READ = 2, FLASH_CMD_ERASE = 3, CMD_RESET = 4}; enum flash_format {FLASH_FORMAT_BINARY = 0, FLASH_FORMAT_IHEX = 1}; diff --git a/include/stlink/usb.h b/include/stlink/usb.h index 621695ea4..a69101c1f 100644 --- a/include/stlink/usb.h +++ b/include/stlink/usb.h @@ -18,11 +18,15 @@ extern "C" { #endif -#define STLINK_USB_VID_ST 0x0483 -#define STLINK_USB_PID_STLINK 0x3744 -#define STLINK_USB_PID_STLINK_32L 0x3748 -#define STLINK_USB_PID_STLINK_32L_AUDIO 0x374a -#define STLINK_USB_PID_STLINK_NUCLEO 0x374b +#define STLINK_USB_VID_ST 0x0483 +#define STLINK_USB_PID_STLINK 0x3744 +#define STLINK_USB_PID_STLINK_32L 0x3748 +#define STLINK_USB_PID_STLINK_32L_AUDIO 0x374a +#define STLINK_USB_PID_STLINK_NUCLEO 0x374b +#define STLINK_USB_PID_STLINK_V3_USBLOADER 0x374d +#define STLINK_USB_PID_STLINK_V3E_PID 0x374e +#define STLINK_USB_PID_STLINK_V3S_PID 0x374f +#define STLINK_USB_PID_STLINK_V3_2VCP_PID 0x3753 #define STLINK_SG_SIZE 31 #define STLINK_CMD_SIZE 16 diff --git a/src/common.c b/src/common.c index 9a3098114..db0ab445e 100644 --- a/src/common.c +++ b/src/common.c @@ -892,23 +892,48 @@ int stlink_status(stlink_t *sl) { * @param sl stlink context, assumed to contain valid data in the buffer * @param slv output parsed version object */ -void _parse_version(stlink_t *sl, stlink_version_t *slv) { - uint32_t b0 = sl->q_buf[0]; //lsb - uint32_t b1 = sl->q_buf[1]; - uint32_t b2 = sl->q_buf[2]; - uint32_t b3 = sl->q_buf[3]; - uint32_t b4 = sl->q_buf[4]; - uint32_t b5 = sl->q_buf[5]; //msb - - // b0 b1 || b2 b3 | b4 b5 - // 4b | 6b | 6b || 2B | 2B - // stlink_v | jtag_v | swim_v || st_vid | stlink_pid - - slv->stlink_v = (b0 & 0xf0) >> 4; - slv->jtag_v = ((b0 & 0x0f) << 2) | ((b1 & 0xc0) >> 6); - slv->swim_v = b1 & 0x3f; - slv->st_vid = (b3 << 8) | b2; - slv->stlink_pid = (b5 << 8) | b4; +void _parse_version(stlink_t *sl, stlink_version_t *slv) +{ + sl->version.flags = 0; + if (sl->version.stlink_v < 3) { + uint32_t b0 = sl->q_buf[0]; //lsb + uint32_t b1 = sl->q_buf[1]; + uint32_t b2 = sl->q_buf[2]; + uint32_t b3 = sl->q_buf[3]; + uint32_t b4 = sl->q_buf[4]; + uint32_t b5 = sl->q_buf[5]; //msb + + // b0 b1 || b2 b3 | b4 b5 + // 4b | 6b | 6b || 2B | 2B + // stlink_v | jtag_v | swim_v || st_vid | stlink_pid + + slv->stlink_v = (b0 & 0xf0) >> 4; + slv->jtag_v = ((b0 & 0x0f) << 2) | ((b1 & 0xc0) >> 6); + slv->swim_v = b1 & 0x3f; + slv->st_vid = (b3 << 8) | b2; + slv->stlink_pid = (b5 << 8) | b4; + /* ST-LINK/V1 from J11 switch to api-v2 (and support SWD) */ + if (slv->stlink_v == 1) + slv->jtag_api = slv->jtag_v > 11? STLINK_JTAG_API_V2 : STLINK_JTAG_API_V1; + else { + slv->jtag_api = STLINK_JTAG_API_V2; + /* preferred API to get last R/W status from J15 */ + if (sl->version.jtag_v >= 15) + sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2; + } + } else { + // V3 uses different version format, for reference see OpenOCD source + // (that was written from docs available from ST under NDA): + // https://github.com/ntfreak/openocd/blob/a6dacdff58ef36fcdac00c53ec27f19de1fbce0d/src/jtag/drivers/stlink_usb.c#L965 + slv->stlink_v = sl->q_buf[0]; + slv->swim_v = sl->q_buf[1]; + slv->jtag_v = sl->q_buf[2]; + slv->st_vid = (uint32_t)((sl->q_buf[9] << 8) | sl->q_buf[8]); + slv->stlink_pid = (uint32_t)((sl->q_buf[11] << 8) | sl->q_buf[10]); + slv->jtag_api = STLINK_JTAG_API_V3; + /* preferred API to get last R/W status */ + sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2; + } return; } @@ -1065,13 +1090,8 @@ int stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, struct s bool stlink_is_core_halted(stlink_t *sl) { - bool ret = false; - - stlink_status(sl); - if (sl->q_buf[0] == STLINK_CORE_HALTED) - ret = true; - - return ret; + stlink_status(sl); + return sl->core_stat == TARGET_HALTED; } int stlink_step(stlink_t *sl) { @@ -1140,21 +1160,21 @@ void stlink_run_at(stlink_t *sl, stm32_addr_t addr) { // this function is called by stlink_status() // do not call stlink_core_stat() directly, always use stlink_status() void stlink_core_stat(stlink_t *sl) { - if (sl->q_len <= 0) - return; - - switch (sl->q_buf[0]) { - case STLINK_CORE_RUNNING: - sl->core_stat = STLINK_CORE_RUNNING; + switch (sl->core_stat ) { + case TARGET_RUNNING: DLOG(" core status: running\n"); return; - case STLINK_CORE_HALTED: - sl->core_stat = STLINK_CORE_HALTED; + case TARGET_HALTED: DLOG(" core status: halted\n"); return; + case TARGET_RESET: + DLOG(" core status: reset\n"); + return; + case TARGET_DEBUG_RUNNING: + DLOG(" core status: debug running\n"); + return; default: - sl->core_stat = STLINK_CORE_STAT_UNKNOWN; - fprintf(stderr, " core status: unknown\n"); + DLOG(" core status: unknown\n"); } } @@ -1162,7 +1182,7 @@ void stlink_print_data(stlink_t * sl) { if (sl->q_len <= 0 || sl->verbose < UDEBUG) return; if (sl->verbose > 2) - fprintf(stdout, "data_len = %d 0x%x\n", sl->q_len, sl->q_len); + DLOG("data_len = %d 0x%x\n", sl->q_len, sl->q_len); for (int i = 0; i < sl->q_len; i++) { if (i % 16 == 0) { @@ -1173,9 +1193,9 @@ void stlink_print_data(stlink_t * sl) { fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i); */ } - fprintf(stdout, " %02x", (unsigned int) sl->q_buf[i]); + DLOG(" %02x", (unsigned int) sl->q_buf[i]); } - fputs("\n\n", stdout); + DLOG("\n\n"); } /* memory mapped file */ @@ -2059,17 +2079,15 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t /* erase each page */ int page_count = 0; for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + (uint32_t) off)) { - /* addr must be an addr inside the page */ + // addr must be an addr inside the page if (stlink_erase_flash_page(sl, addr + (uint32_t) off) == -1) { ELOG("Failed to erase_flash_page(%#zx) == -1\n", addr + off); return -1; } - fprintf(stdout,"\rFlash page at addr: 0x%08lx erased", + ILOG("Flash page at addr: 0x%08lx erased\n", (unsigned long)(addr + off)); - fflush(stdout); page_count++; } - fprintf(stdout,"\n"); ILOG("Finished erasing %d pages of %d (%#x) bytes\n", page_count, sl->flash_pgsz, sl->flash_pgsz); diff --git a/src/flash_loader.c b/src/flash_loader.c index 73db427a7..eaf81019e 100644 --- a/src/flash_loader.c +++ b/src/flash_loader.c @@ -321,7 +321,9 @@ int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* } memcpy(sl->q_buf, loader_code, loader_size); - stlink_write_mem32(sl, sl->sram_base, loader_size); + int ret = stlink_write_mem32(sl, sl->sram_base, loader_size); + if (ret) + return ret; *addr = sl->sram_base; *size = loader_size; diff --git a/src/gdbserver/gdb-server.c b/src/gdbserver/gdb-server.c index bdfeb703d..2dfbc7454 100644 --- a/src/gdbserver/gdb-server.c +++ b/src/gdbserver/gdb-server.c @@ -1384,7 +1384,7 @@ int serve(stlink_t *sl, st_state_t *st) { } stlink_status(sl); - if(sl->core_stat == STLINK_CORE_HALTED) { + if(sl->core_stat == TARGET_HALTED) { struct stlink_reg reg; int ret; stm32_addr_t pc; diff --git a/src/logging.c b/src/logging.c index d4fb96b2e..d2ca11f2a 100644 --- a/src/logging.c +++ b/src/logging.c @@ -11,7 +11,7 @@ #include "stlink/logging.h" -static int max_level = UINFO; +static int max_level = UDEBUG; int ugly_init(int maximum_threshold) { max_level = maximum_threshold; diff --git a/src/sg.c b/src/sg.c index e7ff5d14e..4e8349bc2 100644 --- a/src/sg.c +++ b/src/sg.c @@ -435,7 +435,7 @@ int _stlink_sg_current_mode(stlink_t *stl) { int _stlink_sg_enter_swd_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_SWD; sl->q_len = 0; // >0 -> aboard return stlink_q(sl); @@ -448,7 +448,7 @@ int _stlink_sg_enter_jtag_mode(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_enter_jtag_mode ***\n"); clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_ENTER; sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG; sl->q_len = 0; return stlink_q(sl); @@ -529,7 +529,7 @@ int _stlink_sg_core_id(stlink_t *sl) { int _stlink_sg_reset(stlink_t *sl) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_RESETSYS; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_RESETSYS; sl->q_len = 2; sg->q_addr = 0; if (stlink_q(sl)) @@ -593,7 +593,7 @@ int _stlink_sg_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_READALLREGS; sl->q_len = 84; sg->q_addr = 0; if (stlink_q(sl)) @@ -634,7 +634,7 @@ int _stlink_sg_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { int _stlink_sg_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_READREG; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_READREG; sg->cdb_cmd_blk[2] = r_idx; sl->q_len = 4; sg->q_addr = 0; @@ -679,7 +679,7 @@ int _stlink_sg_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { int _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) { struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEREG; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_WRITEREG; // 2: reg index // 3-6: reg content sg->cdb_cmd_blk[2] = idx; @@ -701,7 +701,7 @@ void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_write_dreg ***\n"); clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEDEBUGREG; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_WRITEDEBUGREG; // 2-5: address of reg of the debug module // 6-9: reg content write_uint32(sg->cdb_cmd_blk + 2, addr); @@ -750,7 +750,7 @@ void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) { DLOG("\n*** stlink_set_hw_bp ***\n"); struct stlink_libsg *sg = sl->backend_data; clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_SETFP; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_SETFP; // 2:The number of the flash patch used to set the breakpoint // 3-6: Address of the breakpoint (LSB) // 7: FP_ALL (0x02) / FP_UPPER (0x01) / FP_LOWER (0x00) @@ -770,7 +770,7 @@ void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) { struct stlink_libsg *sg = sl->backend_data; DLOG("\n*** stlink_clr_hw_bp ***\n"); clear_cdb(sg); - sg->cdb_cmd_blk[1] = STLINK_DEBUG_CLEARFP; + sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_CLEARFP; sg->cdb_cmd_blk[2] = fp_nr; sl->q_len = 2; @@ -1045,7 +1045,7 @@ static stlink_t* stlink_open(const int verbose) { sl->backend_data = slsg; sl->backend = &_stlink_sg_backend; - sl->core_stat = STLINK_CORE_STAT_UNKNOWN; + sl->core_stat = TARGET_UNKNOWN; slsg->q_addr = 0; return sl; diff --git a/src/tools/flash.c b/src/tools/flash.c index f5fd1a386..a8d937930 100644 --- a/src/tools/flash.c +++ b/src/tools/flash.c @@ -29,11 +29,11 @@ static void cleanup(int signum) { static void usage(void) { - puts("stlinkv1 command line: ./st-flash [--debug] [--reset] [--format ] [--flash=] {read|write} /dev/sgX "); - puts("stlinkv1 command line: ./st-flash [--debug] /dev/sgX erase"); - puts("stlinkv2 command line: ./st-flash [--debug] [--reset] [--serial ] [--format ] [--flash=] {read|write} "); - puts("stlinkv2 command line: ./st-flash [--debug] [--serial ] erase"); - puts("stlinkv2 command line: ./st-flash [--debug] [--serial ] reset"); + puts("stlinkv1 command line: ./st-flash [--debug] [--reset] [--format ] [--flash=] {read|write} /dev/sgX "); + puts("stlinkv1 command line: ./st-flash [--debug] /dev/sgX erase"); + puts("stlinkv2/3 command line: ./st-flash [--debug] [--reset] [--serial ] [--format ] [--flash=] {read|write} "); + puts("stlinkv2/3 command line: ./st-flash [--debug] [--serial ] erase"); + puts("stlinkv2/3 command line: ./st-flash [--debug] [--serial ] reset"); puts(" Use hex format for addr, and ."); puts(" fsize: Use decimal, octal or hex by prefix 0xXXX for hex, optionally followed by k=KB, or m=MB (eg. --flash=128k)"); puts(" Format may be 'binary' (default) or 'ihex', although must be specified for binary format only."); diff --git a/src/usb.c b/src/usb.c index 7f5c21283..12945d6d2 100644 --- a/src/usb.c +++ b/src/usb.c @@ -22,6 +22,53 @@ enum SCSI_Generic_Direction {SG_DXFER_TO_DEV=0, SG_DXFER_FROM_DEV=0x80}; +static inline uint32_t le_to_h_u32(const uint8_t* buf) +{ + return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24); +} + +static int _stlink_match_speed_map(const uint32_t *map, unsigned int map_size, uint32_t khz) +{ + unsigned int i; + int speed_index = -1; + int speed_diff = INT_MAX; + int last_valid_speed = -1; + bool match = true; + + for (i = 0; i < map_size; i++) { + if (!map[i]) + continue; + last_valid_speed = i; + if (khz == map[i]) { + speed_index = i; + break; + } else { + int current_diff = khz - map[i]; + /* get abs value for comparison */ + current_diff = (current_diff > 0) ? current_diff : -current_diff; + if ((current_diff < speed_diff) && khz >= map[i]) { + speed_diff = current_diff; + speed_index = i; + } + } + } + + if (speed_index == -1) { + /* this will only be here if we cannot match the slow speed. + * use the slowest speed we support.*/ + speed_index = last_valid_speed; + match = false; + } else if (i == map_size) + match = false; + + if (!match) { + ILOG("Unable to match requested speed %d kHz, using %d kHz\n", \ + khz, map[speed_index]); + } + + return speed_index; +} + void _stlink_usb_close(stlink_t* sl) { if (!sl) return; @@ -39,34 +86,34 @@ void _stlink_usb_close(stlink_t* sl) { } ssize_t send_recv(struct stlink_libusb* handle, int terminate, - unsigned char* txbuf, size_t txsize, - unsigned char* rxbuf, size_t rxsize) { + unsigned char* txbuf, size_t txsize, + unsigned char* rxbuf, size_t rxsize) { /* note: txbuf and rxbuf can point to the same area */ int res = 0; int t; t = libusb_bulk_transfer(handle->usb_handle, handle->ep_req, - txbuf, - (int) txsize, - &res, - 3000); + txbuf, + (int) txsize, + &res, + 3000); if (t) { printf("[!] send_recv send request failed: %s\n", libusb_error_name(t)); return -1; } else if ((size_t)res != txsize) { printf("[!] send_recv send request wrote %u bytes (instead of %u).\n", - (unsigned int)res, (unsigned int)txsize); + (unsigned int)res, (unsigned int)txsize); } if (rxsize != 0) { t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, - rxbuf, - (int) rxsize, - &res, - 3000); + rxbuf, + (int) rxsize, + &res, + 3000); if (t) { printf("[!] send_recv read reply failed: %s\n", - libusb_error_name(t)); + libusb_error_name(t)); return -1; } } @@ -75,13 +122,13 @@ ssize_t send_recv(struct stlink_libusb* handle, int terminate, /* Read the SG reply */ unsigned char sg_buf[13]; t = libusb_bulk_transfer(handle->usb_handle, handle->ep_rep, - sg_buf, - 13, - &res, - 3000); + sg_buf, + 13, + &res, + 3000); if (t) { printf("[!] send_recv read storage failed: %s\n", - libusb_error_name(t)); + libusb_error_name(t)); return -1; } /* The STLink doesn't seem to evaluate the sequence number */ @@ -135,6 +182,19 @@ int _stlink_usb_version(stlink_t *sl) { return (int) size; } + /* STLINK-V3 requires a specific command */ + if (sl->version.stlink_v == 3) { + rep_len = 12; + i = fill_command(sl, SG_DXFER_FROM_DEV, 16); + cmd[i++] = STLINK_APIV3_GET_VERSION_EX; + + size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + if (size != rep_len) { + printf("[!] send_recv STLINK_APIV3_GET_VERSION_EX\n"); + return (int) size; + } + } + return 0; } @@ -207,6 +267,30 @@ int _stlink_usb_write_debug32(stlink_t *sl, uint32_t addr, uint32_t data) { return 0; } +int _stlink_usb_get_rw_status(stlink_t *sl) +{ + if (sl->version.jtag_api == STLINK_JTAG_API_V1) + return -1; + + unsigned char* const rdata = sl->q_buf; + struct stlink_libusb * const slu = sl->backend_data; + unsigned char* const cmd = sl->c_buf; + int i, ret = 0; + + i = fill_command(sl, SG_DXFER_FROM_DEV, 12); + cmd[i++] = STLINK_DEBUG_COMMAND; + if (sl->version.flags & STLINK_F_HAS_GETLASTRWSTATUS2) { + cmd[i++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS2; + ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 12); + } else { + cmd[i++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS; + ret = send_recv(slu, 1, cmd, slu->cmd_len, rdata, 2); + } + if (ret < 0) + return -1; + return 0; +} + int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { struct stlink_libusb * const slu = sl->backend_data; unsigned char* const data = sl->q_buf; @@ -221,12 +305,11 @@ int _stlink_usb_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) { ret = send_only(slu, 0, cmd, slu->cmd_len); if (ret == -1) return ret; - - ret = send_only(slu, 1, data, len); + ret = send_only(slu, 0, data, len); if (ret == -1) return ret; - return 0; + return _stlink_usb_get_rw_status(sl); } int _stlink_usb_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) { @@ -274,11 +357,14 @@ int _stlink_usb_core_id(stlink_t * sl) { unsigned char* const cmd = sl->c_buf; unsigned char* const data = sl->q_buf; ssize_t size; - int rep_len = 4; + int rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 12; int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_READCOREID; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) + cmd[i++] = STLINK_DEBUG_READCOREID; + else + cmd[i++] = STLINK_DEBUG_APIV2_READ_IDCODES; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { @@ -286,11 +372,39 @@ int _stlink_usb_core_id(stlink_t * sl) { return -1; } - sl->core_id = read_uint32(data, 0); + if (sl->version.jtag_api == STLINK_JTAG_API_V1) + sl->core_id = read_uint32(data, 0); + else + sl->core_id = read_uint32(data, 4); return 0; } +int _stlink_usb_status_v2(stlink_t *sl) +{ + int result; + uint32_t status; + + result = _stlink_usb_read_debug32(sl, DCB_DHCSR, &status); + DLOG("core status: %08X\n", status); + if (result != 0) { + sl->core_stat = TARGET_UNKNOWN; + } else { + if (status & S_HALT) { + sl->core_stat = TARGET_HALTED; + } else if (status & S_RESET_ST) { + sl->core_stat = TARGET_RESET; + } else { + sl->core_stat = TARGET_RUNNING; + } + } + + return result; +} int _stlink_usb_status(stlink_t * sl) { + if (sl->version.jtag_api != STLINK_JTAG_API_V1) { + return _stlink_usb_status_v2(sl); + } + struct stlink_libusb * const slu = sl->backend_data; unsigned char* const data = sl->q_buf; unsigned char* const cmd = sl->c_buf; @@ -307,6 +421,14 @@ int _stlink_usb_status(stlink_t * sl) { return (int) size; } sl->q_len = (int) size; + if (sl->q_len > 1) { + if (sl->q_buf[0] == STLINK_CORE_RUNNING) + sl->core_stat = TARGET_RUNNING; + else if (sl->q_buf[0] == STLINK_CORE_HALTED) + sl->core_stat = TARGET_HALTED; + else + sl->core_stat = TARGET_UNKNOWN; + } return 0; } @@ -334,14 +456,19 @@ int _stlink_usb_enter_swd_mode(stlink_t * sl) { struct stlink_libusb * const slu = sl->backend_data; unsigned char* const cmd = sl->c_buf; ssize_t size; - const int rep_len = 0; + unsigned char* const data = sl->q_buf; + const uint32_t rep_len = sl->version.stlink_v > 1 ? 2 : 0; int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_ENTER; + cmd[i++] = sl->version.jtag_api == STLINK_JTAG_API_V1 ? STLINK_DEBUG_APIV1_ENTER : STLINK_DEBUG_APIV2_ENTER; cmd[i++] = STLINK_DEBUG_ENTER_SWD; - size = send_only(slu, 1, cmd, slu->cmd_len); + if (rep_len == 0) { + size = send_only(slu, 1, cmd, slu->cmd_len); + } else { + size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); + } if (size == -1) { printf("[!] send_recv STLINK_DEBUG_ENTER\n"); return (int) size; @@ -378,7 +505,10 @@ int _stlink_usb_reset(stlink_t * sl) { int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_RESETSYS; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) + cmd[i++] = STLINK_DEBUG_APIV1_RESETSYS; + else + cmd[i++] = STLINK_DEBUG_APIV2_RESETSYS; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { @@ -388,7 +518,7 @@ int _stlink_usb_reset(stlink_t * sl) { // Reset through AIRCR so NRST does not need to be connected return stlink_write_debug32(sl, STLINK_REG_AIRCR, - STLINK_REG_AIRCR_VECTKEY | STLINK_REG_AIRCR_SYSRESETREQ); + STLINK_REG_AIRCR_VECTKEY | STLINK_REG_AIRCR_SYSRESETREQ); } @@ -440,6 +570,14 @@ int _stlink_usb_step(stlink_t* sl) { */ int _stlink_usb_run(stlink_t* sl) { struct stlink_libusb * const slu = sl->backend_data; + + int res; + if (sl->version.jtag_api != STLINK_JTAG_API_V1) { + res = _stlink_usb_write_debug32(sl, DCB_DHCSR, DBGKEY|C_DEBUGEN); + return res; + } + + unsigned char* const data = sl->q_buf; unsigned char* const cmd = sl->c_buf; ssize_t size; @@ -466,9 +604,8 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) { ssize_t size; int rep_len = 2; int i; - // clock speed only supported by stlink/v2 and for firmware >= 22 - if (sl->version.stlink_v >= 2 && sl->version.jtag_v >= 22) { + if (sl->version.stlink_v == 2 && sl->version.jtag_v >= 22) { i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; @@ -483,9 +620,55 @@ int _stlink_usb_set_swdclk(stlink_t* sl, uint16_t clk_divisor) { } return 0; - } else { - return -1; + } else if (sl->version.stlink_v == 3) { + int speed_index; + uint32_t map[STLINK_V3_MAX_FREQ_NB]; + i = fill_command(sl, SG_DXFER_FROM_DEV, 16); + + cmd[i++] = STLINK_DEBUG_COMMAND; + cmd[i++] = STLINK_APIV3_GET_COM_FREQ; + cmd[i++] = 0; // SWD mode + + size = send_recv(slu, 1, cmd, slu->cmd_len, data, 52); + if (size == -1) { + printf("[!] send_recv STLINK_APIV3_GET_COM_FREQ\n"); + return (int) size; + } + + int speeds_size = data[8]; + + if (speeds_size > STLINK_V3_MAX_FREQ_NB) + speeds_size = STLINK_V3_MAX_FREQ_NB; + + for (i = 0; i < speeds_size; i++) + map[i] = le_to_h_u32(&data[12 + 4 * i]); + + /* set to zero all the next entries */ + for (i = speeds_size; i < STLINK_V3_MAX_FREQ_NB; i++) + map[i] = 0; + + speed_index = _stlink_match_speed_map(map, STLINK_ARRAY_SIZE(map), 1800); + + i = fill_command(sl, SG_DXFER_FROM_DEV, 16); + + cmd[i++] = STLINK_DEBUG_COMMAND; + cmd[i++] = STLINK_APIV3_SET_COM_FREQ; + cmd[i++] = 0; // SWD mode + cmd[i++] = 0; + cmd[i++] = (uint8_t)((map[speed_index] >> 0) & 0xFF); + cmd[i++] = (uint8_t)((map[speed_index] >> 8) & 0xFF); + cmd[i++] = (uint8_t)((map[speed_index] >> 16) & 0xFF); + cmd[i++] = (uint8_t)((map[speed_index] >> 24) & 0xFF); + + size = send_recv(slu, 1, cmd, slu->cmd_len, data, 8); + if (size == -1) { + printf("[!] send_recv STLINK_APIV3_SET_COM_FREQ\n"); + return (int) size; + } + + return 0; } + return -1; } int _stlink_usb_exit_debug_mode(stlink_t *sl) { @@ -535,33 +718,40 @@ int _stlink_usb_read_all_regs(stlink_t *sl, struct stlink_reg *regp) { unsigned char* const cmd = sl->c_buf; unsigned char* const data = sl->q_buf; ssize_t size; - uint32_t rep_len = 84; + uint32_t rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 84 : 88; int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_READALLREGS; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) + cmd[i++] = STLINK_DEBUG_APIV1_READALLREGS; + else + cmd[i++] = STLINK_DEBUG_APIV2_READALLREGS; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { printf("[!] send_recv STLINK_DEBUG_READALLREGS\n"); return (int) size; } + + /* V1: regs data from offset 0 */ + /* V2: status at offset 0, regs data from offset 4 */ + int reg_offset = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 4; sl->q_len = (int) size; stlink_print_data(sl); - for(i=0; i<16; i++) + for(i=reg_offset; i<16; i++) regp->r[i]= read_uint32(sl->q_buf, i*4); - regp->xpsr = read_uint32(sl->q_buf, 64); - regp->main_sp = read_uint32(sl->q_buf, 68); - regp->process_sp = read_uint32(sl->q_buf, 72); - regp->rw = read_uint32(sl->q_buf, 76); - regp->rw2 = read_uint32(sl->q_buf, 80); + regp->xpsr = read_uint32(sl->q_buf, reg_offset + 64); + regp->main_sp = read_uint32(sl->q_buf, reg_offset + 68); + regp->process_sp = read_uint32(sl->q_buf, reg_offset + 72); + regp->rw = read_uint32(sl->q_buf, reg_offset + 76); + regp->rw2 = read_uint32(sl->q_buf, reg_offset + 80); if (sl->verbose < 2) return 0; - DLOG("xpsr = 0x%08x\n", read_uint32(sl->q_buf, 64)); - DLOG("main_sp = 0x%08x\n", read_uint32(sl->q_buf, 68)); - DLOG("process_sp = 0x%08x\n", read_uint32(sl->q_buf, 72)); - DLOG("rw = 0x%08x\n", read_uint32(sl->q_buf, 76)); - DLOG("rw2 = 0x%08x\n", read_uint32(sl->q_buf, 80)); + DLOG("xpsr = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 64)); + DLOG("main_sp = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 68)); + DLOG("process_sp = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 72)); + DLOG("rw = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 76)); + DLOG("rw2 = 0x%08x\n", read_uint32(sl->q_buf, reg_offset + 80)); return 0; } @@ -572,11 +762,15 @@ int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { unsigned char* const cmd = sl->c_buf; ssize_t size; uint32_t r; - uint32_t rep_len = 4; + uint32_t rep_len = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 8; + int reg_offset = sl->version.jtag_api == STLINK_JTAG_API_V1 ? 0 : 4; int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_READREG; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) + cmd[i++] = STLINK_DEBUG_APIV1_READREG; + else + cmd[i++] = STLINK_DEBUG_APIV2_READREG; cmd[i++] = (uint8_t) r_idx; size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); if (size == -1) { @@ -585,7 +779,7 @@ int _stlink_usb_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) { } sl->q_len = (int) size; stlink_print_data(sl); - r = read_uint32(sl->q_buf, 0); + r = read_uint32(sl->q_buf, reg_offset); DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r); switch (r_idx) { @@ -723,7 +917,10 @@ int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) { int i = fill_command(sl, SG_DXFER_FROM_DEV, rep_len); cmd[i++] = STLINK_DEBUG_COMMAND; - cmd[i++] = STLINK_DEBUG_WRITEREG; + if (sl->version.jtag_api == STLINK_JTAG_API_V1) + cmd[i++] = STLINK_DEBUG_APIV1_WRITEREG; + else + cmd[i++] = STLINK_DEBUG_APIV2_WRITEREG; cmd[i++] = idx; write_uint32(&cmd[i], reg); size = send_recv(slu, 1, cmd, slu->cmd_len, data, rep_len); @@ -731,7 +928,7 @@ int _stlink_usb_write_reg(stlink_t *sl, uint32_t reg, int idx) { printf("[!] send_recv STLINK_DEBUG_WRITEREG\n"); return (int) size; } -sl->q_len = (int) size; + sl->q_len = (int) size; stlink_print_data(sl); return 0; @@ -785,7 +982,7 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[ST sl->backend = &_stlink_usb_backend; sl->backend_data = slu; - sl->core_stat = STLINK_CORE_STAT_UNKNOWN; + sl->core_stat = TARGET_UNKNOWN; if (libusb_init(&(slu->libusb_ctx))) { WLOG("failed to init libusb context, wrong version of libraries?\n"); goto on_error; @@ -822,36 +1019,54 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[ST if (devBus && devAddr) { if ((libusb_get_bus_number(list[cnt]) != devBus) - || (libusb_get_device_address(list[cnt]) != devAddr)) { + || (libusb_get_device_address(list[cnt]) != devAddr)) { continue; } } - if ((desc.idProduct == STLINK_USB_PID_STLINK_32L) || (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO) || (desc.idProduct == STLINK_USB_PID_STLINK_32L_AUDIO)) { + if ((desc.idProduct == STLINK_USB_PID_STLINK_32L) + || (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO) + || (desc.idProduct == STLINK_USB_PID_STLINK_32L_AUDIO) + || (desc.idProduct == STLINK_USB_PID_STLINK_V3_USBLOADER) + || (desc.idProduct == STLINK_USB_PID_STLINK_V3E_PID) + || (desc.idProduct == STLINK_USB_PID_STLINK_V3S_PID) + || (desc.idProduct == STLINK_USB_PID_STLINK_V3_2VCP_PID)) { struct libusb_device_handle *handle; ret = libusb_open(list[cnt], &handle); if (ret) - continue; + continue; sl->serial_size = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)sl->serial, sizeof(sl->serial)); libusb_close(handle); + if ((desc.idProduct == STLINK_USB_PID_STLINK_32L) + || (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO) + || (desc.idProduct == STLINK_USB_PID_STLINK_32L_AUDIO)) { + sl->version.stlink_v = 2; + } else if ((desc.idProduct == STLINK_USB_PID_STLINK_V3_USBLOADER) + || (desc.idProduct == STLINK_USB_PID_STLINK_V3E_PID) + || (desc.idProduct == STLINK_USB_PID_STLINK_V3S_PID) + || (desc.idProduct == STLINK_USB_PID_STLINK_V3_2VCP_PID)) { + sl->version.stlink_v = 3; + } + if ((serial == NULL) || (*serial == 0)) - break; + break; if (sl->serial_size < 0) - continue; + continue; if (memcmp(serial, &sl->serial, sl->serial_size) == 0) - break; + break; continue; } if (desc.idProduct == STLINK_USB_PID_STLINK) { slu->protocoll = 1; + sl->version.stlink_v = 1; break; } } @@ -901,7 +1116,12 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[ST // TODO - could use the scanning techniq from stm8 code here... slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN; - if (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO || desc.idProduct == STLINK_USB_PID_STLINK_32L_AUDIO) { + if (desc.idProduct == STLINK_USB_PID_STLINK_NUCLEO + || desc.idProduct == STLINK_USB_PID_STLINK_32L_AUDIO + || desc.idProduct == STLINK_USB_PID_STLINK_V3_USBLOADER + || desc.idProduct == STLINK_USB_PID_STLINK_V3E_PID + || desc.idProduct == STLINK_USB_PID_STLINK_V3S_PID + || desc.idProduct == STLINK_USB_PID_STLINK_V3_2VCP_PID) { slu->ep_req = 1 /* ep req */ | LIBUSB_ENDPOINT_OUT; } else { slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT; @@ -911,21 +1131,23 @@ stlink_t *stlink_open_usb(enum ugly_loglevel verbose, bool reset, char serial[ST // TODO - never used at the moment, always CMD_SIZE slu->cmd_len = (slu->protocoll == 1)? STLINK_SG_SIZE: STLINK_CMD_SIZE; + // Initialize stlink version (sl->version) + stlink_version(sl); + if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) { ILOG("-- exit_dfu_mode\n"); stlink_exit_dfu_mode(sl); } + // set the speed before entering the mode + // as the chip discovery phase should be done at this speed too + // Set the stlink clock speed (default is 1800kHz) + stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR); + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) { stlink_enter_swd_mode(sl); } - - // Initialize stlink version (sl->version) - stlink_version(sl); - // Set the stlink clock speed (default is 1800kHz) - stlink_set_swdclk(sl, STLINK_SWDCLK_1P8MHZ_DIVISOR); - if (reset) { if( sl->version.stlink_v > 1 ) stlink_jtag_reset(sl, 2); stlink_reset(sl); @@ -972,9 +1194,13 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { break; } - if (desc.idProduct != STLINK_USB_PID_STLINK_32L && - desc.idProduct != STLINK_USB_PID_STLINK_32L_AUDIO && - desc.idProduct != STLINK_USB_PID_STLINK_NUCLEO) + if (desc.idProduct != STLINK_USB_PID_STLINK_32L + && desc.idProduct != STLINK_USB_PID_STLINK_32L_AUDIO + && desc.idProduct != STLINK_USB_PID_STLINK_NUCLEO + && desc.idProduct != STLINK_USB_PID_STLINK_V3_USBLOADER + && desc.idProduct != STLINK_USB_PID_STLINK_V3E_PID + && desc.idProduct != STLINK_USB_PID_STLINK_V3S_PID + && desc.idProduct != STLINK_USB_PID_STLINK_V3_2VCP_PID) continue; slcnt++; @@ -997,9 +1223,9 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { break; } - if (desc.idProduct != STLINK_USB_PID_STLINK_32L && - desc.idProduct != STLINK_USB_PID_STLINK_32L_AUDIO && - desc.idProduct != STLINK_USB_PID_STLINK_NUCLEO) + if (desc.idProduct != STLINK_USB_PID_STLINK_32L && + desc.idProduct != STLINK_USB_PID_STLINK_32L_AUDIO && + desc.idProduct != STLINK_USB_PID_STLINK_NUCLEO) continue; struct libusb_device_handle* handle; @@ -1014,7 +1240,7 @@ static size_t stlink_probe_usb_devs(libusb_device **devs, stlink_t **sldevs[]) { ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, (unsigned char *)&serial, sizeof(serial)); if (ret < 0) - *serial = 0; + *serial = 0; libusb_close(handle);