#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); } }