stm32 HAL初始化分析
时钟初始化HAL_Init
首先运行初始化,代码再stm32h7xx_hal.c中
stm32h7xx_hal.c
HAL_StatusTypeDef HAL_Init(void)
{
uint32_t common_system_clock;
由于使用h7,部分型号带双核,这个是双核时的条件编译
#if defined(DUAL_CORE) && defined(CORE_CM4)
/* Configure Cortex-M4 Instruction cache through ART accelerator */
__HAL_RCC_ART_CLK_ENABLE(); /* Enable the Cortex-M4 ART Clock */
__HAL_ART_CONFIG_BASE_ADDRESS(0x08100000UL); /* Configure the Cortex-M4 ART Base address to the Flash Bank 2 : */
__HAL_ART_ENABLE(); /* Enable the Cortex-M4 ART */
#endif /* DUAL_CORE && CORE_CM4 */
//设置中断优先级分组4,抢占0~15,子0
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
//更新全局变量
/* Update the SystemCoreClock global variable */
#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
//更新时钟全局变量SystemCoreClock
/* Update the SystemD2Clock global variable */
#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 */
//关键在于HAL_InitTick(TICK_INT_PRIORITY)函数,初始化嘀嗒定时器
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
return HAL_ERROR;
}
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
//*********************************************************************
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
if((uint32_t)uwTickFreq == 0UL)
{
return HAL_ERROR;
}
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
stm32h7xx_hal_cortex.c
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}
core_cm7.h
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
分析:
由HAL_InitTick
函数会一步步到SysTick_Config
,其中SysTick_Config再对应的内核文件core_cm7.h
中,并且SysTick_Config会将嘀嗒定时器配置为1kHz。
会配置优先级HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
其中TickPriority的参数TICK_INT_PRIORITY
是宏定义,在stm32h7xx_hal_conf.h
文件内可以找到
初始化代码继续讲解
前面SystemCoreClock一直使用内部高速时钟HSI
–64M,并且初始化了嘀嗒定时器
后面开始各种PLL时钟初始化SystemClock_Config
函数
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
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();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
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_RCC_ClockConfig
中,在文件stm32h7xx_hal_rcc.c
中可以找到,由于函数太长,就不全放了
其中重点在下面这段
/* Update the SystemCoreClock global variable */
#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
#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 */
/* Configure the source of time base considering new system clocks settings*/
halstatus = HAL_InitTick (uwTickPrio);
在这里我们更新了系统时钟SystemCoreClock
变量,并且再次调用HAL_InitTick
函数进行更新
注意:HAL_InitTick
函数我们总共调用两次
- 第一次是在HAL_Init时,那时我们还是用的HSI-64M
- 第二次就是在这里,这是我们的时钟就是HSE了,具体频率看配置400/480
至此基础初始化完成
验证:相关变量的查看
在这里:
SystemCoreClock
由最开始定义的64M变成了480MSysTick->LOAD
变成了 ( 480M/1000-1 )SysTick->VAL
值改变看不出来,由于不是us定时,我们在下面测
我们换个代码专门测一下Systick->VAL的变化
可以看到延时500us,嘀嗒定时器的值减少了一半,是符合预期的
版权声明:本文为CSDN博主「gxt_kt」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/my_id_kt/article/details/122975133
stm32 HAL初始化分析
时钟初始化HAL_Init
首先运行初始化,代码再stm32h7xx_hal.c中
stm32h7xx_hal.c
HAL_StatusTypeDef HAL_Init(void)
{
uint32_t common_system_clock;
由于使用h7,部分型号带双核,这个是双核时的条件编译
#if defined(DUAL_CORE) && defined(CORE_CM4)
/* Configure Cortex-M4 Instruction cache through ART accelerator */
__HAL_RCC_ART_CLK_ENABLE(); /* Enable the Cortex-M4 ART Clock */
__HAL_ART_CONFIG_BASE_ADDRESS(0x08100000UL); /* Configure the Cortex-M4 ART Base address to the Flash Bank 2 : */
__HAL_ART_ENABLE(); /* Enable the Cortex-M4 ART */
#endif /* DUAL_CORE && CORE_CM4 */
//设置中断优先级分组4,抢占0~15,子0
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
//更新全局变量
/* Update the SystemCoreClock global variable */
#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
//更新时钟全局变量SystemCoreClock
/* Update the SystemD2Clock global variable */
#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 */
//关键在于HAL_InitTick(TICK_INT_PRIORITY)函数,初始化嘀嗒定时器
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
return HAL_ERROR;
}
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
//*********************************************************************
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
if((uint32_t)uwTickFreq == 0UL)
{
return HAL_ERROR;
}
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000UL / (uint32_t)uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
stm32h7xx_hal_cortex.c
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
{
return SysTick_Config(TicksNumb);
}
core_cm7.h
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
{
return (1UL); /* Reload value impossible */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0UL); /* Function successful */
}
分析:
由HAL_InitTick
函数会一步步到SysTick_Config
,其中SysTick_Config再对应的内核文件core_cm7.h
中,并且SysTick_Config会将嘀嗒定时器配置为1kHz。
会配置优先级HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
其中TickPriority的参数TICK_INT_PRIORITY
是宏定义,在stm32h7xx_hal_conf.h
文件内可以找到
初始化代码继续讲解
前面SystemCoreClock一直使用内部高速时钟HSI
–64M,并且初始化了嘀嗒定时器
后面开始各种PLL时钟初始化SystemClock_Config
函数
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
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();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
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_RCC_ClockConfig
中,在文件stm32h7xx_hal_rcc.c
中可以找到,由于函数太长,就不全放了
其中重点在下面这段
/* Update the SystemCoreClock global variable */
#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
#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 */
/* Configure the source of time base considering new system clocks settings*/
halstatus = HAL_InitTick (uwTickPrio);
在这里我们更新了系统时钟SystemCoreClock
变量,并且再次调用HAL_InitTick
函数进行更新
注意:HAL_InitTick
函数我们总共调用两次
- 第一次是在HAL_Init时,那时我们还是用的HSI-64M
- 第二次就是在这里,这是我们的时钟就是HSE了,具体频率看配置400/480
至此基础初始化完成
验证:相关变量的查看
在这里:
SystemCoreClock
由最开始定义的64M变成了480MSysTick->LOAD
变成了 ( 480M/1000-1 )SysTick->VAL
值改变看不出来,由于不是us定时,我们在下面测
我们换个代码专门测一下Systick->VAL的变化
可以看到延时500us,嘀嗒定时器的值减少了一半,是符合预期的
版权声明:本文为CSDN博主「gxt_kt」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/my_id_kt/article/details/122975133
暂无评论