一、对于系统的启动和初始化流程
1.启动流程
系统启动文件startup_xx.s进行系统并调用复位中断复位服务程序。在复位中断服务程序里调用SystemInit函数,此函数在文件system_stm32f4xx.c里面之后调用编译器封装好的函数__main ,进入到main中执行用户的函数
2.初始化流程
在main函数中的重要初始化HAL_Init函数即HAL库初始化函数,在stm32f4xx_hal.c中进行配置。
在system_stm32f4xx.c中有关于HSE_VALUE的配置,当时钟不匹配时,会导致串口通信异常现象,可在此文件中修改,SystemInit也在此处定义。
二、初始化中函数的作用
1、HAL_Init函数的作用:
设置中断分组,
设置滴答计数器的每1ms进入中断
配置Flash的指令预取,(即配置flash,供程序应用)
2、HAL_DInit函数的作用:
复位HAL库和滴答时钟。
复位了APB1,2的时钟以及AHB1,2,3的时钟。
三、关于滴答计数器的1ms为时基解读
1、HAL库不像之前的标准库,在系统启动函数SystemInit里面做了RCC初始化
,HAL库是没有做的,所以进入到main函数后,系统还在用内部高速时钟HSI,
对于F4来说,HSI主频是16MHz。
2、对该函数定义为弱定义,在HAL_Init中被直接调用:
SystemCoreClock该值默认为
uint32_t SystemCoreClock = 16000000;
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/*Configure the SysTick to have interrupt in 1ms time basis*/
HAL_SYSTICK_Config(SystemCoreClock/1000U);//此处16000000/1000之后,得到16000/(16mhz)=0.001s,即1ms的时间
/*Configure the SysTick IRQ priority */
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);//该处是配置滴答定时器进入中断时的中断优先级
/* Return function status */
return HAL_OK;
}
四、Systick(滴答计数器)的相关函数的分析作用
1、函数HAL_IncTick在滴答定时器中断里面被调用,
实现一个简单的计数功能,
因为一般滴答定时器中断都是配置的1ms,
所以计数全局变量uwTick每毫秒加1。
2、函数HAL_GetTick用于获取全局变量uwTick当前的计数。
3、函数HAL_GetTickPrio用于获取滴答时钟优先级。
4、函数HAL_SetTickFreq和HAL_GetTickFreq是一对,
前者用于设置滴答中断频率,后再用于获取滴答中断频率。
5、 函数HAL_Delay用于阻塞式延迟,默认单位是ms。
6、 函数HAL_SuspendTick和HAL_ResumeTick是一对,
前者用于挂起滴答定时器,后者用于恢复。
五、对于stm32f4xx_hal_rcc.c 文件中配置系统相关的时钟:
首先:
1、系统上电复位后,通过内部高速时钟**HSI运行(主频16MHz**),
Flash工作在0等待周期,所有外设除了SRAM、Flash、JTAG 和 PWR,**时钟都是关闭的**。
2、AHB和APB**总线无分频**,
所有挂载这两类总线上的外设都是**以HSI频率运行**。
3、所有的**GPIO**都是**模拟模式**,除了JTAG相关的几个引脚。
其次:
系统上电复位后,用户需要完成以下工作:
1.选择用于驱动系统时钟的时钟源。
配置系统时钟频率和Flash设置。
配置分频器。
使能外设时钟,
配置外设时钟源,部分外设的时钟可以不来自系统时钟(I2S, RTC, ADC, USB OTG FS/SDIO/RNG)
最后:
理解PCLK1、2对应的是APB总线APB1,APB2时钟。 HCLK对应的AHB总线。同时HCLK一般可以等同于SYSCLK(系统时钟) 。
需要注意
HSI内部高速时钟,精确度不高(16mhz)。
LSI内部低俗时钟,和RTC,看门狗时钟源相关。
HSE外部高速时钟,经过倍频可提供系统时钟源。
LSE外部低俗时钟,和RTC相关。
CSS (Clock security system) 时钟安全系统,
一旦使能后,如果HSE启动失败(不管是直接作为系统时钟源还是通过PLL输出后做系统时钟源),
系统时钟将切换到HSI。如果使能了中断的话,将进入不可屏蔽中断NMI。
对于MCO1和MCO2都是对外部提供时钟,属于输出时钟源。
MCO1 (micro controller clock output) 可以在PA8引脚
输出 SYSCLK、PLLI2SCLK、HSE和PLLCLK。
MCO2 (micro controller clock output) 可以在PC9引脚
输出LSE、HSE、HSI和PLLCLK。
HAL_RCC_DeInit在stm32f4xx_hal_rcc_ex.c里,
此函数用于RCC复位函数,主要实现如下功能:
HSI 打开作为系统时钟。
HSE和PLL关闭。
AHB, APB1和APB2总线无分频 。
CSS, MCO1 和 MCO2 关闭。
所有中断关闭。
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct);
配置配置HSE、HSI、LSI、LSE和PLL等参数
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency);
配置HCLK、SYSCLK、PLCK1和PLCK2。
第1个参数是RCC_ClkInitTypeDef类型的结构体变量。
第2个参数是Flash的延迟设置。
此函数会更新全局变量SystemCoreClock的主频值,
并且会再次调用函数HAL_InitTick更新系统滴答时钟
void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv);
MCO引脚输出时钟的时候,直接调用即可。
第1个形参用于选择输出的引脚,
第2个形参用于选择输出的时钟源
第3个参数用于设置输出分频
五、在文件stm3f4xx_hal_cortex.c 中主要是NVIC与SysTick配置相关的函数:
这些是对SysTick的配置函数
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb);
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource);
void HAL_SYSTICK_IRQHandler(void);
void HAL_SYSTICK_Callback(void);
和中断相关配置的则是:
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority);
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn);