STM32启动过程分析

基于STM32H750XB HAL库分析

start.s

; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler                    [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

在进入main函数之前会先调用SystemInit函数,之后再调用__main进入main函数

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();

  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* Configure the peripherals common clocks */
  PeriphCommonClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */
  
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      
  }
    
}

主要分析如下几个函数

SystemInit();  
HAL_Init();
SystemClock_Config();
PeriphCommonClock_Config();

SystemInit(); 函数分析

void SystemInit (void)
{
#if defined (DATA_IN_D2_SRAM)
 __IO uint32_t tmpreg;
#endif /* DATA_IN_D2_SRAM */

  /* FPU设置:如果FPU存在并被使用,则设置完全访问权限 */
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2)));  /* 设置CP10和CP11完全访问 */
  #endif

  /* 重置RCC时钟配置到默认复位状态 */
  /* 增加CPU频率前,检查并设置FLASH延迟 */
  if(FLASH_LATENCY_DEFAULT  > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
  {
    MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
  }

  /* 设置HSION位,启用内部高速时钟 */
  RCC->CR |= RCC_CR_HSION;

  /* 重置CFGR寄存器 */
  RCC->CFGR = 0x00000000;

  /* 重置各种时钟控制位 */
  RCC->CR &= 0xEAF6ED7FU;

  /* 降低CPU频率后,检查并设置FLASH延迟 */
  if(FLASH_LATENCY_DEFAULT  < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
  {
    MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
  }

  /* 以下是根据具体型号的STM32设备进行的额外配置 */
#if defined(D3_SRAM_BASE)
  /* 重置D1CFGR, D2CFGR, D3CFGR寄存器 */
  RCC->D1CFGR = 0x00000000;
  RCC->D2CFGR = 0x00000000;
  RCC->D3CFGR = 0x00000000;
#else
  /* 重置CDCFGR1, CDCFGR2, SRDCFGR寄存器 */
  RCC->CDCFGR1 = 0x00000000;
  RCC->CDCFGR2 = 0x00000000;
  RCC->SRDCFGR = 0x00000000;
#endif

  /* 重置并配置PLL相关寄存器 */
  RCC->PLLCKSELR = 0x02020200;
  RCC->PLLCFGR = 0x01FF0000;
  RCC->PLL1DIVR = 0x01010280;
  RCC->PLL1FRACR = 0x00000000;
  RCC->PLL2DIVR = 0x01010280;
  RCC->PLL2FRACR = 0x00000000;
  RCC->PLL3DIVR = 0x01010280;
  RCC->PLL3FRACR = 0x00000000;

  /* 重置HSEBYP位 */
  RCC->CR &= 0xFFFBFFFFU;

  /* 禁用所有中断 */
  RCC->CIER = 0x00000000;

#if (STM32H7_DEV_ID == 0x450UL)
  /* 特定于STM32H7系列的配置 */
  if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
  {
    *((__IO uint32_t*)0x51008108) = 0x000000001U;
  }
#endif /* STM32H7_DEV_ID */

#if defined(DATA_IN_D2_SRAM)
  /* 如果数据存储在D2 SRAM中,启用D2 SRAM时钟 */
  RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
  tmpreg = RCC->AHB2ENR;
  (void) tmpreg;
#endif /* DATA_IN_D2_SRAM */

#if defined(DUAL_CORE) && defined(CORE_CM4)
  /* 双核设备上为Cortex-M4配置向量表 */
  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; 
#else
  /* 禁用FMC back1(开机后默认启用)。
   * 这防止了CPU在FMC使用期间的推测性访问,这可能会在24us内阻碍FMC的使用。
   * 在此时间内,其他FMC主控(如LTDC)不能使用它! */
  FMC_Bank1_R->BTCR[0] = 0x000030D2;

  /* 配置向量表位置 */
  /* 根据定义,将中断向量表定位到特定的地址,可以是内部的D1 AXI-RAM或者内部FLASH */
#if defined(USER_VECT_TAB_ADDRESS)
  SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET;
#endif /* USER_VECT_TAB_ADDRESS */

#endif /*DUAL_CORE && CORE_CM4*/
} // SystemInit函数结束

配合开发手册可以知道大部分是在控制RCC的寄存器

image-20231203154627742

image-20231203161628926

CR寄存器

image-20231203161749551

image-20231203162137289

image-20231203162158145

image-20231203162238472

image-20231203162304736

image-20231203162323360

image-20231203161806482

  • 复位三个锁相环PLL1,PLL2,PLL3(默认关闭)
  • 关闭除开HSI的其他时钟(默认关闭)
  • 关闭DI域以及D2域的时钟(默认关闭)
  • 开启HSI时钟(默认不分频为64MHZ)

CFGR寄存器

image-20231203164023846

以上寄存器各个位就不展示了,到手册中看

  • 将HSI用作系统时钟

各个域时钟配置D1CFGR,D2CFGR,D3CFGR寄存器

image-20231203170700807

image-20231203170930466

image-20231203171105145

image-20231203171127641

image-20231203171148104

D1CFGR:用于控制 D1 域 CPU 时钟分频系数, 用于控制 rcc_pclk3(APB3) 的分频系数,用于控制 rcc_hclk3rcc_aclk (AHB)的分频系数(复位不分频)

D2CFGR:控制 D2 域 APB1、APB2 时钟分频系数(复位不分频)

D3CFGR:用于控制 D3 域 APB4 时钟分频系数(复位不分频)

锁相环寄存器8个

PLLCKSELR,PLLCFGR,PLL1DIVR,PLL1FRACR,PLL2DIVR,PLL2FRACR,PLL3DIVR,PLL3FRACR

image-20231203172307751

  /* Reset PLLCKSELR register */
  RCC->PLLCKSELR = 0x02020200;

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x01FF0000;
  /* Reset PLL1DIVR register */
  RCC->PLL1DIVR = 0x01010280;
  /* Reset PLL1FRACR register */
  RCC->PLL1FRACR = 0x00000000;

  /* Reset PLL2DIVR register */
  RCC->PLL2DIVR = 0x01010280;

  /* Reset PLL2FRACR register */

  RCC->PLL2FRACR = 0x00000000;
  /* Reset PLL3DIVR register */
  RCC->PLL3DIVR = 0x01010280;

  /* Reset PLL3FRACR register */
  RCC->PLL3FRACR = 0x00000000;
  • 以上都是复位值,禁止输出

再次设置源控制寄存器CR

 /* Reset HSEBYP bit */
  RCC->CR &= 0xFFFBFFFFU;

关闭所有中断

  /* Disable all interrupts */
  RCC->CIER = 0x00000000;

禁用FMC bank1

 FMC_Bank1_R->BTCR[0] = 0x000030D2;

由此看来SystemInitinit()函数使用HSI作用于启动时钟,并禁止了其他时钟系统以及分频器的开启,也就相当于没有打开外设时钟,关闭了中断以防止后面的过程被中断,并设置了中断向量表的地址,禁用FMC bank1(禁止其他内存使用)

HAL_Init();函数分析

/**
  * @brief  初始化HAL库,必须是主程序中执行的第一个指令(在调用任何其他HAL函数之前)。
  *         它执行以下操作:
  *           配置SysTick以每1毫秒生成一次中断,该中断由HSI提供时钟
  *           (在此阶段,时钟尚未配置,因此系统运行在内部HSI上,频率为16 MHz)。
  *           设置NVIC组优先级为4。
  *           调用用户文件 "stm32h7xx_hal_msp.c" 中定义的 HAL_MspInit() 回调函数,
  *           以执行全局低级硬件初始化。
  *
  * @note   SysTick被用作HAL_Delay()函数的时间基准,应用程序需要确保SysTick时间基准始终设置为1毫秒,
  *         以确保正确的HAL操作。
  * @retval HAL状态
  */

 //以上的注释可能存在错误,只有在配置了系统滴答定时器时候才会出如上情况,我这里使用的是基本定时器作为系统时钟基准
HAL_StatusTypeDef HAL_Init(void)
{
  uint32_t common_system_clock;

#if defined(DUAL_CORE) && defined(CORE_CM4)
  /* 为Cortex-M4配置指令缓存和ART加速器 */
  __HAL_RCC_ART_CLK_ENABLE();                   /* 启用Cortex-M4 ART时钟 */
  __HAL_ART_CONFIG_BASE_ADDRESS(0x08100000UL);  /* 将Cortex-M4 ART基地址配置到Flash Bank 2 */
  __HAL_ART_ENABLE();                           /* 启用Cortex-M4 ART */
#endif /* DUAL_CORE && CORE_CM4 */

  /* 设置中断组优先级 */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* 更新全局变量SystemCoreClock */
#if defined(RCC_D1CFGR_D1CPRE)
  common_system_clock = HAL_RCC_GetSysClockFreq() >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE)>> RCC_D1CFGR_D1CPRE_Pos]) & 0x1FU);
#else
  common_system_clock = HAL_RCC_GetSysClockFreq() >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_CDCPRE)>> RCC_CDCFGR1_CDCPRE_Pos]) & 0x1FU);
#endif

  /* 更新全局变量SystemD2Clock */
#if defined(RCC_D1CFGR_HPRE)
  SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
#else
  SystemD2Clock = (common_system_clock >> ((D1CorePrescTable[(RCC->CDCFGR1 & RCC_CDCFGR1_HPRE)>> RCC_CDCFGR1_HPRE_Pos]) & 0x1FU));
#endif

#if defined(DUAL_CORE) && defined(CORE_CM4)
  SystemCoreClock = SystemD2Clock;
#else
  SystemCoreClock = common_system_clock;
#endif /* DUAL_CORE && CORE_CM4 */

  /* 使用systick作为时间基准源,并配置1ms的tick(复位后默认时钟为HSI) */
  if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
  {
    return HAL_ERROR;
  }

  /* 初始化低级硬件 */
  HAL_MspInit();

  /* 返回函数状态 */
  return HAL_OK;
}
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
  • 优先级分组为4 (4位全是抢占优先级,16个优先级0-15)

image-20231203192406612

  • 初始化定时器7所在的时钟,并查询当前时钟频率,根据频率来配置定时器开启1ms的中断,基于此中断会提供一个系统延时函数
  • HAL_MspInit为初始化SYSCFG所在的时钟APB4

    image-20231203202352284

image-20231203202545052

SystemClock_Config();函数分析

void SystemClock_Config(void)
{
  // 定义并初始化RCC的振荡器和时钟配置结构体
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /* 使能电源配置更新 */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  /* 配置主内部电压调节器的输出电压 */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  // 等待电压调节器准备就绪
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  // 使能SYSCFG时钟
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  // 再次配置电压调节器的输出电压
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  // 再次等待电压调节器准备就绪
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  /* 根据RCC_OscInitTypeDef结构体中的参数初始化RCC振荡器 */
  // 配置HSE(高速外部)振荡器为开启状态
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  // 配置PLL(锁相环)为开启状态
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  // 设置PLL的各个分频参数
  RCC_OscInitStruct.PLL.PLLM = 5;
  RCC_OscInitStruct.PLL.PLLN = 192;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  // 如果振荡器配置失败,调用错误处理函数
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** 初始化CPU、AHB和APB总线的时钟 */
  // 配置各种时钟类型
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  // 设置系统时钟源为PLL时钟
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  // 设置各种分频器
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  // 如果时钟配置失败,调用错误处理函数
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
  {
    Error_Handler();
  }
}
 HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);

  /* Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  • 有关电源配置(这一块以后再研究吧,配合低功耗一起)

配置微控制器的电压等级,包括在必要时启用或禁用过载保护功能。这些操作对于微控制器的能效和性能至关重要,特别是在改变运行频率或功耗模式时

  RCC_OscInitStruct.PLL.PLLM = 5;
  RCC_OscInitStruct.PLL.PLLN = 192;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  对应的时钟如下

image-20231203205210300

  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;  

image-20231203211313723

image-20231203211253360

image-20231203211440377

  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;

image-20231203211522530

RCC_OscInitStruct.PLL.PLLFRACN = 0;

image-20231203211745618

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  • ClockType 指定配置的时钟类型
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

image-20231203212955624

PeriphCommonClock_Config();函数分析

void PeriphCommonClock_Config(void)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  /** Initializes the peripherals clock
  */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB|RCC_PERIPHCLK_ADC
                              |RCC_PERIPHCLK_SDMMC|RCC_PERIPHCLK_SPI1
                              |RCC_PERIPHCLK_LTDC;
  PeriphClkInitStruct.PLL2.PLL2M = 2;
  PeriphClkInitStruct.PLL2.PLL2N = 16;
  PeriphClkInitStruct.PLL2.PLL2P = 4;
  PeriphClkInitStruct.PLL2.PLL2Q = 1;
  PeriphClkInitStruct.PLL2.PLL2R = 1;
  PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
  PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
  PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
    
  PeriphClkInitStruct.PLL3.PLL3M = 5;
  PeriphClkInitStruct.PLL3.PLL3N = 50;
  PeriphClkInitStruct.PLL3.PLL3P = 1;
  PeriphClkInitStruct.PLL3.PLL3Q = 5;
  PeriphClkInitStruct.PLL3.PLL3R = 10;
  PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
  PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
  PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    
  PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;
  PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL2;
  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;
  PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
}

理解SystemClock_Config()函数这个也就差不多了

PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB|RCC_PERIPHCLK_ADC
                              |RCC_PERIPHCLK_SDMMC|RCC_PERIPHCLK_SPI1
                              |RCC_PERIPHCLK_LTDC;
  PeriphClkInitStruct.PLL2.PLL2M = 2;
  PeriphClkInitStruct.PLL2.PLL2N = 16;
  PeriphClkInitStruct.PLL2.PLL2P = 4;
  PeriphClkInitStruct.PLL2.PLL2Q = 1;
  PeriphClkInitStruct.PLL2.PLL2R = 1;
  PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
  PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
  PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
    
  PeriphClkInitStruct.PLL3.PLL3M = 5;
  PeriphClkInitStruct.PLL3.PLL3N = 50;
  PeriphClkInitStruct.PLL3.PLL3P = 1;
  PeriphClkInitStruct.PLL3.PLL3Q = 5;
  PeriphClkInitStruct.PLL3.PLL3R = 10;
  PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
  PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
  PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
  • 上面的配置对应着下图的部分

image-20231203213539904

具体寄存器可在如下部分找到

image-20231203213858918

  PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;
  PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL2;
  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;
  PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;

此外这里有单独的外设配置对应着经过锁相环输出的频率,只是确定哪一个锁相环输出,并没有确定具体是DIVP,DIVQ,DIVR哪一个,确定是哪一个应该是由后面的配置决定

image-20231203215059508

总结:

SystemInit() 为main函数之前运行的函数,依赖库文件,主要有以下作用

  • 确定是否开启FPU
  • 启用内部时钟HSI 复位时钟
  • 复位时钟,关闭锁相环
  • 关闭中断
  • 禁用FMC bank1
  • 设置中断向量表地址

HAL_Init()

  • 设置中断优先级
  • 设置定时器提供系统时基
  • 开启SYSCFG(系统配置控制器)所在时钟单元

SystemClock_Config() 这一步配置完成就确定了各个总线的时钟

  • 电源配置
  • 初始化锁相环PLL配置(这里对应着PLL1,H7系列有三个锁相环)
  • 初始化分频器(对部分总线进行分频)

PeriphCommonClock_Config() 这一步配置PLL2以及PLL3分频器和时钟在PLL上的外设

  • 配置PLL2
  • 配置PLL3
  • 配置时钟在PLL上的外设
如果觉得我的文章对你有用,请随意赞赏