#include <stdint.h>
#include <stddef.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include "platform.h"
static bool stlink_stable_read(const uint32_t gpio_port, const uint16_t gpio)
{
bool result = false;
for (volatile size_t i = 0; i < 100U; ++i)
result = gpio_get(gpio_port, gpio);
return result;
}
uint32_t detect_rev(void)
{
while (RCC_CFGR & 0xfU)
RCC_CFGR &= ~3U;
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_GPIOB);
rcc_periph_clock_enable(RCC_GPIOC);
rcc_periph_clock_enable(RCC_USB);
rcc_periph_reset_pulse(RST_USB);
rcc_periph_clock_enable(RCC_AFIO);
rcc_periph_clock_enable(RCC_CRC);
gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13);
gpio_set(GPIOC, GPIO14 | GPIO13);
gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO11);
gpio_clear(GPIOB, GPIO11);
uint32_t revision = 0;
if (stlink_stable_read(GPIOC, GPIO13))
revision = gpio_get(GPIOB, GPIO11) ? 0x101 : 0;
else {
rcc_periph_clock_enable(RCC_AFIO);
AFIO_MAPR |= 0x02000000U;
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO15);
gpio_clear(GPIOA, GPIO15);
if (stlink_stable_read(GPIOA, GPIO15)) {
revision = 2;
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO15);
gpio_clear(GPIOB, GPIO15);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO15);
gpio_clear(GPIOA, GPIO15);
} else
revision = 1;
RCC_CFGR &= ~(0xfU << 24U);
RCC_CFGR |= (RCC_CFGR_MCO_HSE << 24U);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8);
}
if ((revision & 0xff) < 2U) {
gpio_clear(GPIOA, GPIO12);
gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12);
}
return revision;
}
void platform_request_boot(void)
{
#if defined(ST_BOOTLOADER)
rcc_periph_reset_pulse(RST_USB);
scb_reset_system();
#else
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO1);
SCB_VTOR = 0;
#endif
}