diff --git a/src/platforms/stlink/Readme b/src/platforms/stlink/Readme index a677e55..b20a6db 100644 --- a/src/platforms/stlink/Readme +++ b/src/platforms/stlink/Readme @@ -1,3 +1,11 @@ Find a description how to modify a Discovery Board to use it's Stlink as black magic debug at -http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe \ No newline at end of file +http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe + +Differences between V1/V2 + + V1 V2 +ID Pins PC13/14 unconnected PC 13 pulled low +LED STLINK PA8, active High PA9, Dual Led +MCO Out NA PA8 +RESET(Target) T_JRST(PB1) NRST (PB0) diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 40dcf8f..5eaf5fc 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -41,6 +41,34 @@ volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; +uint16_t led_idle_run; +/* Pins PC[14:13] are used to detect hardware revision. Read + * 11 for STLink V1 e.g. on VL Discovery, tag as hwversion 0 + * 10 for STLink V2 e.g. on F4 Discovery, tag as hwversion 1 + */ +int platform_hwversion(void) +{ + static int hwversion = -1; + int i; + if (hwversion == -1) { + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, + GPIO14 | GPIO13); + gpio_set(GPIOC, GPIO14 | GPIO13); + for (i = 0; i<10; i++) + hwversion = ~(gpio_get(GPIOC, GPIO14 | GPIO13) >> 13) & 3; + switch (hwversion) + { + case 0: + led_idle_run = GPIO8; + break; + default: + led_idle_run = GPIO9; + } + } + return hwversion; +} + int platform_init(void) { rcc_clock_setup_in_hse_8mhz_out_72mhz(); @@ -49,8 +77,19 @@ int platform_init(void) rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + /* On Rev 1 unconditionally activate MCO on PORTA8 with HSE + * platform_hwversion() also needed to initialize led_idle_run! + */ + if (platform_hwversion() == 1) + { + RCC_CFGR &= ~( 0xf<< 24); + RCC_CFGR |= (RCC_CFGR_MCO_HSECLK << 24); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); + } /* Setup GPIO ports */ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); @@ -60,13 +99,7 @@ int platform_init(void) GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, LED_IDLE_RUN); - - /* unconditionally activate MCO on PORTA8 with HSE*/ - RCC_CFGR &= ~( 0xf<< 24); - RCC_CFGR |= (RCC_CFGR_MCO_HSECLK << 24); - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); /* Setup heartbeat timer */ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); @@ -96,7 +129,7 @@ void platform_delay(uint32_t delay) void sys_tick_handler(void) { if(running_status) - gpio_toggle(LED_PORT, LED_IDLE_RUN); + gpio_toggle(LED_PORT, led_idle_run); if(timeout_counter) timeout_counter--; @@ -129,9 +162,14 @@ void disconnect_usb(void) void assert_boot_pin(void) { - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); - gpio_set(GPIOC, GPIO13); + uint32_t crl = GPIOA_CRL; + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + /* Enable Pull on GPIOA1. We don't rely on the external pin + * really pulled, but only on the value of the CNF register + * changed from the reset value + */ + crl &= 0xffffff0f; + crl |= 0x80; + GPIOA_CRL = crl; } void setup_vbus_irq(void){}; diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 9b765fb..d22a4e2 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -81,7 +81,6 @@ extern usbd_device *usbdev; /* Use PC14 for a "dummy" uart led. So we can observere at least with scope*/ #define LED_PORT_UART GPIOC #define LED_UART GPIO14 -#define LED_IDLE_RUN GPIO9 #define TMS_SET_MODE() \ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ @@ -134,8 +133,9 @@ extern const char *morse_msg; gpio_clear((port), (pin)); \ } while(0) +extern uint16_t led_idle_run; #define SET_RUN_STATE(state) {running_status = (state);} -#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} +#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} #define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} #define PLATFORM_FATAL_ERROR(error) { \ diff --git a/src/platforms/stm32/usbdfu.c b/src/platforms/stm32/usbdfu.c index e42e00f..b582a44 100644 --- a/src/platforms/stm32/usbdfu.c +++ b/src/platforms/stm32/usbdfu.c @@ -54,17 +54,44 @@ u8 usbd_control_buffer[1024]; #endif #if defined(DISCOVERY_STLINK) +uint8_t rev; +uint16_t led_idle_run; u32 led2_state = 0; int stlink_test_nrst(void) { -/* Test if NRST is pulled down*/ +/* Test if JRST/NRST is pulled down*/ int i; uint16_t nrst; + uint16_t pin; + + /* First, get Board revision by pulling PC13/14 up. Read + * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 + * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 + */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14|GPIO13); + gpio_set(GPIOC, GPIO14|GPIO13); + for (i=0; i< 100; i++) + rev = (~(gpio_get(GPIOC, GPIO14|GPIO13))>>13) & 3; + + switch (rev) + { + case 0: + pin = GPIO1; + led_idle_run= GPIO8; + break; + default: + pin = GPIO0; + led_idle_run = GPIO9; + } + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); - gpio_set(GPIOB, GPIO0); - for (i=0; i< 100000; i++) - nrst = gpio_get(GPIOB, GPIO0); + GPIO_CNF_INPUT_PULL_UPDOWN, pin); + gpio_set(GPIOB, pin); + for (i=0; i< 100; i++) + nrst = gpio_get(GPIOB, pin); return (nrst)?1:0; } #endif @@ -380,8 +407,12 @@ int main(void) { /* Check the force bootloader pin*/ #if defined (DISCOVERY_STLINK) - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - if(!gpio_get(GPIOC, GPIO13) && stlink_test_nrst()) { + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); +/* Check value of GPIOA1 configuration. This pin is unconnected on + * STLink V1 and V2. If we have a value other than the reset value (0x4), + * we have a warm start and request Bootloader entry + */ + if(((GPIOA_CRL & 0x40) == 0x40) && stlink_test_nrst()) { #elif defined (STM32_CAN) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); if(!gpio_get(GPIOA, GPIO0)) { @@ -569,14 +600,19 @@ static char *get_dev_unique_id(char *s) void sys_tick_handler() { -#if defined(DISCOVERY_STLINK) - if (led2_state & 1) - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO9); + #if defined(DISCOVERY_STLINK) + if (rev == 0) + gpio_toggle(GPIOA, led_idle_run); else - gpio_set_mode(GPIOA, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_ANALOG, GPIO9); - led2_state++; + { + if (led2_state & 1) + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); + else + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_ANALOG, led_idle_run); + led2_state++; + } #elif defined (F4DISCOVERY) gpio_toggle(GPIOD, GPIO12); /* Green LED on/off */ #elif defined (USPS_F407)