hpgl_xy/stm32f103t8u6-bootloader/src/main.c
2021-04-04 20:33:45 +02:00

119 lines
3.3 KiB
C

#include "main.h"
// Configure clocks based on a 8 MHz external crystal for:
// SYSCLK, AHB, APB2 72 Mhz
// APB1, ADC 36 MHz
static inline void Clock_Init(void)
{
// Activate HSE and wait for it to be ready
RCC->CR = RCC_CR_HSEON | RCC_CR_HSION;
while(!(RCC->CR & RCC_CR_HSERDY));
RCC->CFGR = RCC_CFGR_SW_0;
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_0);
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1;
// Set PLL to x9 (-> 72MHz system clock)
RCC->CFGR = RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC | RCC_CFGR_PPRE1_2
| RCC_CFGR_SW_0;
// Activate PLL and wait
RCC->CR = RCC_CR_PLLON | RCC_CR_HSEON | RCC_CR_HSION;
while(!(RCC->CR & RCC_CR_PLLRDY));
// Select PLL as clock source
RCC->CFGR = RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC | RCC_CFGR_PPRE1_2
| RCC_CFGR_SW_1;
// Disable all interrupts
RCC->CIR = 0x00000000;
// Enable peripheral clocks
RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN;
RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN | RCC_APB1ENR_USBEN;
RCC->AHBENR = RCC_AHBENR_CRCEN;
}
static inline bool Bootloader_EntryCondition(void)
{
// Activate pull-up for test point
GPIOA->CRH = (0x44444444
& ~(0x0f << (PIN_TEST_POINT * 4 - 32)))
| (0x08<< (PIN_TEST_POINT * 4 - 32))
;
GPIOA->BSRR = (1 << PIN_TEST_POINT);
// The first word in the application frame is the stack end pointer
const uint32_t *application_start = (uint32_t*)FLASH_APPLICATION_BASE;
// If it is not a valid RAM address, we can assume there's no application
// present in flash and thus enter the bootloader
if((*application_start & 0xffff8000) != 0x20000000)
{
return true;
}
// Check RTC backup register 1 for magic value
PWR->CR = PWR_CR_DBP;
if(BKP->DR1 == 0xb007)
{
return true;
}
// Check if test point is held low externally
if(~GPIOA->IDR & (1 << PIN_TEST_POINT))
{
return true;
}
return false;
}
static inline void Bootloader_Exit(void)
{
// Reset RTC backup register
BKP->DR1 = 0x0000;
// Reset peripherals
RCC->APB1RSTR = RCC_APB1RSTR_USBRST;
RCC->APB2RSTR = RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_AFIORST;
RCC->APB1RSTR = 0x00000000;
RCC->APB2RSTR = 0x00000000;
// Reset peripheral clock enable registers to their reset values
RCC->AHBENR = 0x00000014; // Disable CRC
RCC->APB2ENR = 0x00000000; // Disable GPIOA, GPIOB, AFIO
RCC->APB1ENR = 0x00000000; // Disable USB, PWR, BKP
// Set vector table location
SCB->VTOR = FLASH_APPLICATION_BASE - FLASH_BASE;
// Set stack pointer and jump into application
uint32_t application_stack_pointer = *(uint32_t*)FLASH_APPLICATION_BASE;
uint32_t application_reset_handler = *(uint32_t*)(FLASH_APPLICATION_BASE
+ 4);
__asm__ volatile(".syntax unified \n"
"msr msp, %[stack_pointer] \n"
"bx %[reset_handler] \n"
:
: [stack_pointer] "r" (application_stack_pointer),
[reset_handler] "r" (application_reset_handler));
}
int main(void)
{
Clock_Init();
if(Bootloader_EntryCondition())
{
USB_Init();
while(USB_Poll());
// Delay to allow answer token to be fetched by host
Util_Delay(100000);
}
Bootloader_Exit();
}