156 lines
3.8 KiB
C
156 lines
3.8 KiB
C
#include "main.h"
|
|
#include "usb_device.h"
|
|
#include "usbd_dfu_bootloader.h"
|
|
|
|
typedef void (*ApplicationEntry)(void);
|
|
|
|
static void Bootloader_SystemClockConfig(void);
|
|
static void Bootloader_GPIOInit(void);
|
|
static uint8_t Bootloader_IsApplicationValid(uint32_t address);
|
|
static void Bootloader_JumpToApplication(uint32_t address);
|
|
|
|
int main(void)
|
|
{
|
|
uint32_t selectedAddress = 0U;
|
|
|
|
HAL_Init();
|
|
Bootloader_GPIOInit();
|
|
HAL_Delay(20U);
|
|
|
|
/* Holding START during reset always forces USB DFU mode. */
|
|
if (HAL_GPIO_ReadPin(Start_GPIO_Port, Start_Pin) != GPIO_PIN_RESET)
|
|
{
|
|
GPIO_PinState pa4 = HAL_GPIO_ReadPin(DINPUT_GPIO_Port, DINPUT_Pin);
|
|
GPIO_PinState pa5 = HAL_GPIO_ReadPin(XINPUT_GPIO_Port, XINPUT_Pin);
|
|
|
|
/* Actual board wiring: PA4 LOW selects XInput, PA5 LOW selects DInput. */
|
|
if ((pa4 == GPIO_PIN_RESET) && (pa5 == GPIO_PIN_SET))
|
|
{
|
|
selectedAddress = DFU_APP1_ADDRESS;
|
|
}
|
|
else if ((pa4 == GPIO_PIN_SET) && (pa5 == GPIO_PIN_RESET))
|
|
{
|
|
selectedAddress = DFU_APP2_ADDRESS;
|
|
}
|
|
}
|
|
|
|
if ((selectedAddress != 0U) && Bootloader_IsApplicationValid(selectedAddress))
|
|
{
|
|
Bootloader_JumpToApplication(selectedAddress);
|
|
}
|
|
|
|
Bootloader_SystemClockConfig();
|
|
MX_USB_DEVICE_Init();
|
|
|
|
while (1)
|
|
{
|
|
}
|
|
}
|
|
|
|
static void Bootloader_GPIOInit(void)
|
|
{
|
|
GPIO_InitTypeDef gpio = {0};
|
|
|
|
__HAL_RCC_GPIOA_CLK_ENABLE();
|
|
__HAL_RCC_GPIOC_CLK_ENABLE();
|
|
|
|
gpio.Pin = DINPUT_Pin | XINPUT_Pin;
|
|
gpio.Mode = GPIO_MODE_INPUT;
|
|
gpio.Pull = GPIO_PULLUP;
|
|
HAL_GPIO_Init(GPIOA, &gpio);
|
|
|
|
gpio.Pin = Start_Pin;
|
|
HAL_GPIO_Init(GPIOC, &gpio);
|
|
}
|
|
|
|
static uint8_t Bootloader_IsApplicationValid(uint32_t address)
|
|
{
|
|
uint32_t stackPointer = *(volatile uint32_t *)address;
|
|
uint32_t resetHandler = *(volatile uint32_t *)(address + 4U);
|
|
uint32_t slotEnd = address + DFU_APP_SLOT_SIZE;
|
|
|
|
return ((stackPointer >= SRAM_BASE) &&
|
|
(stackPointer <= (SRAM_BASE + (20U * 1024U))) &&
|
|
((resetHandler & 1U) != 0U) &&
|
|
((resetHandler & ~1U) >= address) &&
|
|
((resetHandler & ~1U) < slotEnd)) ? 1U : 0U;
|
|
}
|
|
|
|
static void Bootloader_JumpToApplication(uint32_t address)
|
|
{
|
|
uint32_t stackPointer = *(volatile uint32_t *)address;
|
|
uint32_t resetHandler = *(volatile uint32_t *)(address + 4U);
|
|
|
|
__disable_irq();
|
|
SysTick->CTRL = 0U;
|
|
SysTick->LOAD = 0U;
|
|
SysTick->VAL = 0U;
|
|
HAL_DeInit();
|
|
|
|
NVIC->ICER[0] = 0xFFFFFFFFU;
|
|
NVIC->ICER[1] = 0xFFFFFFFFU;
|
|
NVIC->ICPR[0] = 0xFFFFFFFFU;
|
|
NVIC->ICPR[1] = 0xFFFFFFFFU;
|
|
|
|
SCB->VTOR = address;
|
|
__DSB();
|
|
__ISB();
|
|
__enable_irq();
|
|
|
|
__asm volatile (
|
|
"msr msp, %0\n"
|
|
"bx %1\n"
|
|
:
|
|
: "r" (stackPointer), "r" (resetHandler)
|
|
: "memory");
|
|
|
|
while (1)
|
|
{
|
|
}
|
|
}
|
|
|
|
static void Bootloader_SystemClockConfig(void)
|
|
{
|
|
RCC_OscInitTypeDef oscillator = {0};
|
|
RCC_ClkInitTypeDef clocks = {0};
|
|
RCC_PeriphCLKInitTypeDef peripheral = {0};
|
|
|
|
oscillator.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
|
oscillator.HSEState = RCC_HSE_ON;
|
|
oscillator.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
|
|
oscillator.HSIState = RCC_HSI_ON;
|
|
oscillator.PLL.PLLState = RCC_PLL_ON;
|
|
oscillator.PLL.PLLSource = RCC_PLLSOURCE_HSE;
|
|
oscillator.PLL.PLLMUL = RCC_PLL_MUL9;
|
|
if (HAL_RCC_OscConfig(&oscillator) != HAL_OK)
|
|
{
|
|
Error_Handler();
|
|
}
|
|
|
|
clocks.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK |
|
|
RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
|
|
clocks.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
|
clocks.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
|
clocks.APB1CLKDivider = RCC_HCLK_DIV2;
|
|
clocks.APB2CLKDivider = RCC_HCLK_DIV1;
|
|
if (HAL_RCC_ClockConfig(&clocks, FLASH_LATENCY_2) != HAL_OK)
|
|
{
|
|
Error_Handler();
|
|
}
|
|
|
|
peripheral.PeriphClockSelection = RCC_PERIPHCLK_USB;
|
|
peripheral.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5;
|
|
if (HAL_RCCEx_PeriphCLKConfig(&peripheral) != HAL_OK)
|
|
{
|
|
Error_Handler();
|
|
}
|
|
}
|
|
|
|
void Error_Handler(void)
|
|
{
|
|
__disable_irq();
|
|
while (1)
|
|
{
|
|
}
|
|
}
|