Yes indeed the Cube generated code contains constructs where you are allowed to insert your own code:
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/* PendSV_IRQn interrupt configuration */
HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
However I am not sure that is anywhere near the whole story. I have just gone through the entire initialisation code and compiled the various bits into one piece of code which is inline and starts at the start of main(). The first bit of it was in SystemInit() which was called from the assembler startup code, just before it went to main(). Why from there? Why call a C function from asm startup, immediately before you go main()?
There is a number of clear duplicates, but I am not 100% sure if there might be a reason behind them, to do with subtle timing issues (like the famous Ethernet one where having a PCLK2 divisor of 8 or 16 broke the ethernet subsystem, unless timing was ensured via another route):
int main(void)
{
// This was in SystemInit()
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Disable all interrupts */
RCC->CIR = 0x00000000;
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
// This was in SetSysClock(), and the settings were partly overriden later by
// stuff in SystemClock_Config()!
volatile uint32_t StartUpCounter = 0, HSEStatus = 0;
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
/* Enable high performance mode, System frequency up to 168 MHz */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_PMODE;
// *** THIS CLOCK CONFIG GETS OVERRIDEN below ***
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 4 i.e. 42MHz */
RCC->CFGR |= RCC_CFGR_PPRE2_DIV4;
/* PCLK1 = HCLK / 4 i.e. 42MHz */
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
/************************* PLL Parameters *************************************/
// These produce a 168MHz CPU clock (336/2) and a 48MHz USB clock (336/7)
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M 25
#define PLL_N 336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P 2
/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
#define PLL_Q 7
/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
(RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0) {}
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
// This stuff is also partly repeated further below. What is not being done here, for
// no obvious reason, is FLASH_ACR_PRFTEN. So this line is partly pointless.
// But maybe there are timing reasons for this...
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;
/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL) {}
/* Configure the Vector Table location add offset address ------------------*/
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
// Copy of HAL_Init from stm32f4xx_hal.c
// Stripped down to NOT enable interrupts!
/* Configure Flash prefetch, Instruction cache, Data cache. These are according to the config
* in stm32f4xx_hal_conf.h which currently is:
* #define PREFETCH_ENABLE 1 The prefetch will be enabled in SystemClock_Config(), depending
* on the used STM32F405/415/07/417 device: RevA (prefetch must be
* off) or RevZ (prefetch can be on/off)
* #define INSTRUCTION_CACHE_ENABLE 1
* #define DATA_CACHE_ENABLE 1
*/
// This overrides FLASH_ACR_ICEN above
#if (INSTRUCTION_CACHE_ENABLE != 0U)
__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */
// This overrides FLASH_ACR_DCEN above
#if (DATA_CACHE_ENABLE != 0U)
__HAL_FLASH_DATA_CACHE_ENABLE();
#endif /* DATA_CACHE_ENABLE */
// This setting is controlled from stm32f4xx_hal_conf.h which was edited to enable this 5/8/2021
#if (PREFETCH_ENABLE != 0U)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
//HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
//HAL_InitTick(TICK_INT_PRIORITY);
/* Init the low level hardware */
//HAL_MspInit();
// This was in SystemClock_Config()
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/* Configure the main internal regulator output voltage */
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Initialise the CPU, AHB and APB busses clocks */
// This is a duplicate of stuff further above
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
/** Initializes the CPU, AHB and APB busses clocks
* These settings override stuff set earlier */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 42MHz - SPI2,SPI3,UART2,UART3,TIM2,3,4,5,6,7,12,13,15 etc
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4; // 42MHz - UART1,UART6
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
// Stop IWDG if single stepping
__HAL_DBGMCU_FREEZE_IWDG();
// Initialise clocks. Without this one cannot set up any I/O pins etc.
B_HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_HSE, RCC_MCODIV_1);
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();