From b85f4319eee38792748a9d26e70142574658de43 Mon Sep 17 00:00:00 2001
From: Hristo Mitrev
Date: Tue, 9 Jan 2024 20:41:38 +0200
Subject: [PATCH] stlink: support stlink v2 isol variant
---
src/platforms/stlink/Makefile.inc | 4 ++++
src/platforms/stlink/platform.c | 19 +++++++++++++++++++
src/platforms/stlink/platform.h | 21 +++++++++++++++++++++
src/platforms/stlink/stlink_common.c | 19 +++++++++++++++----
4 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc
index e8e25ebbe3b..895787556ca 100644
--- a/src/platforms/stlink/Makefile.inc
+++ b/src/platforms/stlink/Makefile.inc
@@ -39,6 +39,10 @@ ifeq ($(STLINK_FORCE_CLONE), 1)
CFLAGS += -DSTLINK_FORCE_CLONE=1
endif
+ifeq ($(STLINK_V2_ISOL), 1)
+CFLAGS += -DSTLINK_V2_ISOL=1
+endif
+
VPATH += platforms/common/stm32
SRC += \
diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c
index e9ba1ae2128..60815077130 100644
--- a/src/platforms/stlink/platform.c
+++ b/src/platforms/stlink/platform.c
@@ -52,6 +52,19 @@ void platform_init(void)
#ifdef BLUEPILL
led_idle_run = GPIO13;
nrst_pin = NRST_PIN_V1;
+#elif defined(STLINK_V2_ISOL)
+ led_idle_run = GPIO9;
+ nrst_pin = NRST_PIN_V2;
+ /* PB12 is SWDIO_IN */
+ gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO12);
+ /* PA4 is used to set SWDCLK floating when set to 1 */
+ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO4);
+ gpio_clear(GPIOA, GPIO4);
+ /* PA1 is used to set SWDIO floating and MUXED to SWDIO_IN when set to 1 */
+ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO1);
+#elif defined(STLINK_FORCE_CLONE)
+ led_idle_run = GPIO9;
+ nrst_pin = NRST_PIN_CLONE;
#else
switch (rev) {
case 0:
@@ -69,7 +82,13 @@ void platform_init(void)
}
#endif
/* Setup GPIO ports */
+#ifdef STLINK_V2_ISOL
+ /* In case of ISOL variant, this pin is never set to high impedance */
+ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN);
+#else
+ /* In all other variants, this pin is initialized as high impedance */
gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_INPUT_FLOAT, TMS_PIN);
+#endif
gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN);
gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN);
diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h
index fa56aa105e7..67e5f5fd662 100644
--- a/src/platforms/stlink/platform.h
+++ b/src/platforms/stlink/platform.h
@@ -53,6 +53,11 @@ extern bool debug_bmp;
#define SWDIO_PIN TMS_PIN
#define SWCLK_PIN TCK_PIN
+#ifdef STLINK_V2_ISOL
+#define SWDIO_IN_PORT GPIOB
+#define SWDIO_IN_PIN GPIO12
+#endif
+
#define NRST_PORT GPIOB
#define NRST_PIN_V1 GPIO1
#define NRST_PIN_V2 GPIO0
@@ -77,7 +82,22 @@ extern bool debug_bmp;
#define SWD_CR GPIO_CRH(SWDIO_PORT)
#define SWD_CR_MULT (1U << ((14U - 8U) << 2U))
+#define SWDIODIR_ODR GPIO_ODR(GPIOA)
+
#define TMS_SET_MODE() gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN);
+
+#ifdef STLINK_V2_ISOL
+/* The ISOL variant floats SWDIO with GPIO A1 */
+#define SWDIO_MODE_FLOAT() \
+ do { \
+ SWDIODIR_ODR |= (GPIO1); \
+ } while (0)
+#define SWDIO_MODE_DRIVE() \
+ do { \
+ SWDIODIR_ODR &= ~(GPIO1); \
+ } while (0)
+#else
+/* All other variants just set SWDIO_PIN to floating */
#define SWDIO_MODE_FLOAT() \
do { \
uint32_t cr = SWD_CR; \
@@ -92,6 +112,7 @@ extern bool debug_bmp;
cr |= (0x1U * SWD_CR_MULT); \
SWD_CR = cr; \
} while (0)
+#endif
#define UART_PIN_SETUP() \
do { \
gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); \
diff --git a/src/platforms/stlink/stlink_common.c b/src/platforms/stlink/stlink_common.c
index 3f638c21cbe..0e9df492796 100644
--- a/src/platforms/stlink/stlink_common.c
+++ b/src/platforms/stlink/stlink_common.c
@@ -25,6 +25,8 @@
#include "platform.h"
+/* If we force CLONE or V2_ISOL variant, we don't need to read GPIO levels */
+#if !(defined(STLINK_FORCE_CLONE) || defined(STLINK_V2_ISOL))
static bool stlink_stable_read(const uint32_t gpio_port, const uint16_t gpio)
{
bool result = false;
@@ -32,6 +34,7 @@ static bool stlink_stable_read(const uint32_t gpio_port, const uint16_t gpio)
result = gpio_get(gpio_port, gpio);
return result;
}
+#endif
/* Return 0 for ST-Link v1, 1 for ST-Link v2 and 2 for ST-Link v2.1 */
uint32_t detect_rev(void)
@@ -45,6 +48,17 @@ uint32_t detect_rev(void)
rcc_periph_reset_pulse(RST_USB);
rcc_periph_clock_enable(RCC_AFIO);
rcc_periph_clock_enable(RCC_CRC);
+
+#if defined(STLINK_FORCE_CLONE)
+ /* PA12 is USB D+ pin */
+ gpio_clear(GPIOA, GPIO12);
+ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12);
+ /* Override detection to use clone pinmap (i.e. PB6 as nRST). */
+ return 0x101;
+#elif defined(STLINK_V2_ISOL)
+ /* Override detection to stlink v2 isol*/
+ return 0x103;
+#else
/*
* First, get the board revision by pulling PC13/14 up then reading them.
* This gives us the following table of values for these pins:
@@ -89,16 +103,13 @@ uint32_t detect_rev(void)
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8);
}
- /* Override detection to use clone pinmap (i.e. PB6 as nRST). */
-#if defined(STLINK_FORCE_CLONE)
- revision = 0x101;
-#endif
/* Clean up after ourself on boards that aren't identified as ST-Link v2.1's */
if ((revision & 0xff) < 2U) {
gpio_clear(GPIOA, GPIO12);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12);
}
return revision;
+#endif
}
void platform_request_boot(void)