64 lines
3.0 KiB
C
64 lines
3.0 KiB
C
#include "stm32f4xx_hal.h"
|
||
#include "boot_config.h"
|
||
#include "usb_cdc.h"
|
||
#include "boot_port.h"
|
||
#if F407_BOOT_HSE_HZ != HSE_VALUE
|
||
#error boot_config.h and HAL HSE_VALUE must describe the same crystal
|
||
#endif
|
||
#if (F407_BOOT_HSE_HZ % 1000000UL) || F407_BOOT_HSE_HZ < 2000000UL || F407_BOOT_HSE_HZ > 50000000UL
|
||
#error HSE must provide a valid integer PLLM divider (2..50 MHz)
|
||
#endif
|
||
uint32_t SystemCoreClock=16000000;
|
||
const uint8_t AHBPrescTable[16]={0,0,0,0,0,0,0,0,1,2,3,4,6,7,8,9};
|
||
const uint8_t APBPrescTable[8]={0,0,0,0,1,2,3,4};
|
||
static uint8_t usb_clock_ready;
|
||
static volatile uint32_t clock_fault;
|
||
void SystemInit(void) { SCB->CPACR|=0xFu<<20; SCB->VTOR=0x08000000; }
|
||
void SysTick_Handler(void) { HAL_IncTick(); }
|
||
static void board_fatal(uint32_t code) { clock_fault=code; for(;;) {} }
|
||
static void peripheral_clock(void)
|
||
{
|
||
RCC_OscInitTypeDef osc={0};
|
||
RCC_ClkInitTypeDef clk={0};
|
||
/* Разрешаем доступ к PWR и выбираем диапазон питания ядра перед повышением частоты. */
|
||
__HAL_RCC_PWR_CLK_ENABLE();
|
||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||
osc.OscillatorType=RCC_OSCILLATORTYPE_HSE;
|
||
osc.HSEState=RCC_HSE_ON;
|
||
/* Готовность HSE проверяется HAL с ограниченным временем ожидания, а не бесконечным циклом. */
|
||
if (HAL_RCC_OscConfig(&osc)==HAL_OK) usb_clock_ready=1;
|
||
else {
|
||
clock_fault=1;
|
||
osc.HSEState=RCC_HSE_OFF;
|
||
if (HAL_RCC_OscConfig(&osc)!=HAL_OK) board_fatal(3);
|
||
}
|
||
/* CPU 72 MHz, APB1 36 MHz, USB 48 MHz; USB requires the HSE crystal. */
|
||
osc.OscillatorType=RCC_OSCILLATORTYPE_HSI;
|
||
osc.HSIState=RCC_HSI_ON;
|
||
osc.HSICalibrationValue=RCC_HSICALIBRATION_DEFAULT;
|
||
osc.PLL.PLLState=RCC_PLL_ON;
|
||
osc.PLL.PLLSource=usb_clock_ready ? RCC_PLLSOURCE_HSE : RCC_PLLSOURCE_HSI;
|
||
osc.PLL.PLLM=usb_clock_ready ? F407_BOOT_HSE_HZ/1000000UL : 16;
|
||
osc.PLL.PLLN=144; osc.PLL.PLLP=RCC_PLLP_DIV2; osc.PLL.PLLQ=3;
|
||
if (HAL_RCC_OscConfig(&osc)!=HAL_OK) board_fatal(3);
|
||
clk.ClockType=RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||
clk.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK;
|
||
clk.AHBCLKDivider=RCC_SYSCLK_DIV1;
|
||
clk.APB1CLKDivider=RCC_HCLK_DIV2; clk.APB2CLKDivider=RCC_HCLK_DIV1;
|
||
/* HAL задаёт два такта ожидания Flash и перестраивает SysTick для новой частоты CPU. */
|
||
if (HAL_RCC_ClockConfig(&clk,FLASH_LATENCY_2)!=HAL_OK) board_fatal(3);
|
||
}
|
||
|
||
|
||
void boot_protocol_init(void);
|
||
void boot_protocol_poll(uint32_t now);
|
||
int main(void) {
|
||
/* Jump from reset, before initializing USB, DMA, clocks or interrupts. */
|
||
bool requested=f407_boot_requested();
|
||
if(!requested && f407_app_valid()) f407_jump_app();
|
||
if(HAL_Init()!=HAL_OK) board_fatal(3);
|
||
peripheral_clock(); boot_protocol_init();
|
||
if(usb_clock_ready) usb_cdc_init();
|
||
for(;;) { uint32_t now=HAL_GetTick(); usb_cdc_poll(now); boot_protocol_poll(now); }
|
||
}
|