关于STM32时钟的问题记录

发布时间 2023-10-29 23:25:53作者: 不再熬夜啦
关于STM32时钟的问题
        在读别人建立大型的STM32工程时,会看到主函数中会首先执行一个RCC_Init()的函数,跳转过去之后发现是配置时钟的相关函数。而我自己在写STM32相关代码的时候,似乎从来没有注意过这个问题,我猜想在STM32程序开始执行的时候,也就是复位之后,会首先执行时钟配置的函数,于是我就详细的了解了STM32程序的执行流程。
        首先,STM32从上电复位到main函数的过程。主要有以下步骤:

1.初始化堆栈指针 SP=_initial_sp,初始化 PC 指针=Reset_Handler;

2.初始化中断向量表;

3.配置系统时钟;

4.调用 C 库函数_main 初始化用户堆栈,然后进入 main 函数。

        在学习STM32程序的执行顺序之前,我们需要首先了解STM32的启动方式,这个在STM32的参考手册里有的,如下图:

        一、STM32有三种启动方式:

        1.从主闪存存储器启动:主闪存存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的地址(0x0800 0000)访问它,即闪存存储器的内容可以在两个地址区域访问,0x0000
0000或0x0800 0000。(从STM32内置的Flash启动(0x0800 0000-0x0807 FFFF),一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。)
        2.从系统存储器启动:系统存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的地址(互联型产品原有地址为0x1FFF B000,其它产品原有地址为0x1FFF F000)访问它。(一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的ISP程序中,提供了串口下载程序的固件,可以通过这个ISP程序将用户程序下载到系统的Flash中。)
        3.从内置SRAM启动:只能在0x2000 0000开始的地址区访问SRAM。(从内置SRAM启动(0x2000 0000-0x3FFFFFFF),既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。)(SRAM掉电丢失)
        启动模式只决定程序烧录的位置,加载完程序之后会有一个重映射(映射到0x00000000地址位置);真正产生复位信号的时候,CPU还是从开始位置执行。值得注意的是STM32上电复位以后,代码区都是从0x00000000开始的,三种启动模式只是将各自存储空间的地址映射到0x00000000中。
        二、STM32的启动文件

        每个STM32工程都会有启动文件的,在建立工程的时候,已经将启动文件放在工程内了,这里我查看的是STM32f10x系列的启动文件,接下来我将一段一段的分析启动文件。

        启动文件的名称是“system_stm32f10x.c”。

 1. 这个文件提供了2个函数和1个全局变量:

SystemInit():设置系统时钟(系统时钟源、PLL锁相环(用于倍频)、AHB/APBx预分频器、Flash设置),这个函数被用作复位之后和主程序分支之前。

SystemCoreClock variable:系统内核时钟变量,包含内核时钟,它被用于用户应用程序设置SysTick定时器或配置其他参数。

SystemCoreClockUpdate():更新变量SystemCoreClock和在程序执行期间调用可以更改核心时钟。 

 2. 每个设备复位之后,HSI内部高速时钟(8MHz)被用于系统时钟源。然后在“startup_stm32f10x_xx.s”文件中调用 SystemInit() 函数,以配置分支到主程序之前的系统时钟。

 3. 如果用户选择的系统时钟源启动失败,则SystemInit()  函数将不做任何事情,HSI仍然用作系统时钟源。 用户可以在SetSysClock()函数中添加一些代码来处理这个问题。 

        4. HSE晶振的默认值设置为8 MHz(或25 MHz,开启使用的产品),请参阅“stm32f10x.h”文件中的“HSE_VALUE”定义。当HSE直接或通过PLL用作系统时钟源时,您使用不同的晶体,您必须根据自己的 HSE 值进行调整配置。

        总结一下,复位之后HSI内部高速时钟(8MHz)被用于系统时钟源,然后调用SystemInit() ,通过它配置时钟。