Initial Refleks Lite hardware and firmware release
This commit is contained in:
155
arcadestick_software/Core/Src/bootloader_main.c
Normal file
155
arcadestick_software/Core/Src/bootloader_main.c
Normal file
@@ -0,0 +1,155 @@
|
||||
#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)
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user