当前位置:网站首页>GD32F4(5):GD32F450时钟配置为200M过程分析
GD32F4(5):GD32F450时钟配置为200M过程分析
2022-06-12 07:18:00 【Little Grey Bear】
GD32F450时钟树分析
文章目录
1. 系统环境
系统:win10
IDE:keil5
开发板:GD官方评估板GD32450Z_EVAL
用户手册版本:GD32F4xx_yonghushouce_Rev2.6.pdf
标准库版本:GD32F4xx_Demo_Suites_V2.5.0
2. 时钟树图
对于任何的一款MCU,熟悉它的时钟树,熟悉mcu时钟的配置过程,会修改时钟配置都是非常有必要的。
对于GD32F4来讲,它的时钟控制单元提供了一系列频率的时钟功能,包括:
- 一个外部高速晶体振荡器时钟(HXTAL)。
- 一个外部低速晶体振荡器时钟(LXTAL),一般接32.768K晶振。
- 一个内部48M RC振荡器时钟(IRC48M),这个48M时钟是专门为时钟校准控制器(CTC)和USB提供时钟的。
- 一个内部16M RC振荡器时钟(IRC16M。
- 一个内部32K RC振荡器时钟(IRC32K)。
- 三个锁相环(PLL)、一个HXTAL时钟监视器(CKM)、时钟预分频器、时钟多路复用器和时钟门控电路。
GD32F4系列MCU的时钟树如下图:
AHB、APB1、AHB2和Cortex-M4时钟都源自系统时钟(CK_SYS),系统时钟的时钟源可以选择IRC16M、 HXTAL或PLL。
系统时钟的最大运行时钟频率可以达到240MHz,但数据手册显示GD32F450最高可达到200M,GD32F470最高到达240M。
独立看门狗定时器有独立的时钟源(IRC32K),实时时钟(RTC)使用IRC32K、 LXTAL或HXTAL的分频(通过配置RCU_CFG0寄存器的RTCDIV位)作为时钟源。
3. GD32F450的时钟配置函数
首先我们先简要的叙述GD32F450的启动过程,关于GD32F450编译和启动过程的详细分析,我将另外写一篇文章,本文重点是记录官方带的demo程序是如何将GD32F450时钟配置到200M的。
在startup_gd32f450.s文件中,有如下一段汇编代码:
;/* reset Handler */
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit ;将SystemInit函数地址加载到R0寄存器
BLX R0 ;执行SystemInit进行时钟设置,执行完后返回
LDR R0, =__main ;将__main函数地址加载到R0寄存器
BX R0 ;执行__main函数,不再返回,__main会再调用用户的main函数,从此进入用户编写的程序
ENDP
和STM32的启动过程一样,芯片上电先调用Reset_Handler,Reset_Handler会调用两个函数,一个是SystemInit配置系统时钟,另一个是__main,本章重点介绍SystemInit函数;
时钟的配置,由3个函数来完成,SystemInit执行会调用system_clock_config,system_clock_config执行在调用system_clock_200m_25m_hxtal,最后完成200M时钟的配置,具体的时钟配置函数和内部代码逻辑如下:
3.1 SystemInit函数
void SystemInit (void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)//默认不开起
//浮点运算相关设置
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
//其实这个CP10、CP11并不是真正的寄存器,它其实是协处理器的名字,ARM拥有16个协处理器,常被命名为CP0—CP15,其中CP0—CP7由厂家定义协处理功能,而CP8—CP15预留给ARM使用,CP15提供一些系统控制功能,这包括体系结构和特征识别,以及控制、状态信息和配置支持,还提供了性能监视器寄存器。CP14主要提供debug系统的控制、Thumb执行环境、字节码执行。CP10、CP11 两个协处理器一起,提供了浮点运算和向量操作,以及高级的 SIMD 指令扩展。协处理器8、9、12和13预留给ARM将来使用。因为协处理器是协助内核的,16个协处理器共提供出16*32位,基本每个位都有其相应的功能(不使用的位除外),我们平时都接触不到,因此我们平时都忽略它。
#endif
/* Reset the RCU clock configuration to the default reset state ------------*/
/* Set IRC16MEN bit */
//选择内部16M时钟
RCU_CTL |= RCU_CTL_IRC16MEN;
//将时钟进行2分频,等待时钟稳定,这里会等待的久一点,
RCU_MODIFY
//上面程序的目的是设置当前系统内核的时钟,此时系统的时钟为8M
//下面的Reset都是关闭操作,将各种时钟模块的使能全部关闭,变成失能
/* Reset CFG0 register */
RCU_CFG0 = 0x00000000U;
/* Reset HXTALEN, CKMEN and PLLEN bits */
//关闭外部高速时钟、高速时钟时钟监视器(CKM)、PLL锁相环使能
RCU_CTL &= ~(RCU_CTL_PLLEN | RCU_CTL_CKMEN | RCU_CTL_HXTALEN);
/* Reset PLLCFGR register */
RCU_PLL = 0x24003010U;
/* Reset HSEBYP bit */
RCU_CTL &= ~(RCU_CTL_HXTALBPS);
/* Disable all interrupts */
RCU_INT = 0x00000000U;
/* Configure the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings ----------------------------------*/
//进入时钟配置,重新配置系统相关时钟
system_clock_config();
}
3.2 system_clock_config函数
static void system_clock_config(void)
{
...
#elif defined (__SYSTEM_CLOCK_200M_PLL_25M_HXTAL)
//利用外部高速时钟(评估板带的是25M晶振),配置系统时钟为200M
system_clock_200m_25m_hxtal();
#endif
}
3.3 system_clock_200m_25m_hxtal函数
static void system_clock_200m_25m_hxtal(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
/* enable HXTAL */
//开启外部高速时钟
RCU_CTL |= RCU_CTL_HXTALEN;
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
//等待外部高速时钟稳定,(当外部晶振稳定后,芯片将自动设置相关标志位,软件只需要不断读取这个标志位就可以知道时钟是否稳定)
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
/* if fail */
//若外部高速时钟异常,上面等待超时,则进入这里永远等待,系统会卡在while(1)里面
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(1){
//我感觉这里不合理,按理说外部时钟异常,应该触发相应的中断,并自动切换到内部高速时钟运行,而不是卡在这里。以后我有时间会把这个函数改改,现在先这样用吧。
}
}
//运行到这里,说明外部高速时钟正常启动,下面就要按照时钟树,来配置系统和各个模块的时钟
RCU_APB1EN |= RCU_APB1EN_PMUEN;//使能APB1总线
PMU_CTL |= PMU_CTL_LDOVS;//配置使能内部电压调节器1.2V域供电
//时钟的配置原则应该是从内向外,对照时钟树图,就可以非常清楚的明白时钟配置过程
/* HXTAL is stable */
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;//系统SYS时钟到AHB总线时钟不进行分频
/* APB2 = AHB/2 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;//APB2是AHB的2分频
/* APB1 = AHB/4 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4;//APB1是AHB的4分频
//GD32F450有3个PLL(PLL、PLLI2S、PLLSAI),这里只配置了一个PLL,
//现在外部晶振时钟是25M,通过PSC的25分频,变成1M,然后再PLL内倍频400倍,变成400M,然后再经过P进行2分频,变成200M,传给系统时钟。同时400M还进行了Q的9分频,产生大约48M的CK48M给USB提供时钟去了。
//当更换外部晶振的频率后的时候,通过修改PSC就可以进行匹配了
/* Configure the main PLL, PSC = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */
RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |
(RCU_PLLSRC_HXTAL) | (9U << 24U));
/* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN;//上面配置完了,就要使能PLL
/* wait until PLL is stable */
//等待PLL配置时钟稳定下来
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
}
//在用户手册3.3.4章节,说如果1.2V电源域工作在高频状态下,且打开了多种功能,建议进入高驱动模式。
/* Enable the high-drive to extend the clock frequency to 200 Mhz */
//使能高驱动模式
PMU_CTL |= PMU_CTL_HDEN;
//等待PMU_CS寄存器的HDRF被置位
while(0U == (PMU_CS & PMU_CS_HDRF)){
}
/* select the high-drive mode */
//将LDO切换到高驱动模式
PMU_CTL |= PMU_CTL_HDS;
//等待PMU_CS寄存器的HDSRF被置位。进入高驱动模式
while(0U == (PMU_CS & PMU_CS_HDSRF)){
}
/* select PLL as system clock */
//设置SCS[1:0],将时钟切换到刚配置好的PLL这条系统时钟线路
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLLP;
/* wait until PLL is selected as system clock */
//等待PLL这条系统时钟配置能稳定给系统提供时钟
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
}
//到此处,系统完成了从8M到200M的切换
}
3.4 根据程序中的配置,绘制配置后的时钟路线图
最后,我们来绘制一下程序中配置的路径,其中绿色的是开始配置8M的时钟线路,红色的是配置200M的时钟线路,如下图:
边栏推荐
- RT thread studio learning (VIII) connecting Alibaba cloud IOT with esp8266
- Use case design of software testing interview questions
- paddlepaddl 28 支持任意维度数据的梯度平衡机制GHM Loss的实现(支持ignore_index、class_weight,支持反向传播训练,支持多分类)
- Win10 list documents
- 基于eNSP加防火墙的千人中型校园/企业网络规划与设计(附所有配置命令)
- 8 IO Library
- RT thread studio learning summary
- Nine project management issues that PM should understand
- [image detection] SAR image change detection based on depth difference and pcanet with matlab code
- Stm32cubemx learning (I) USB HID bidirectional communication
猜你喜欢

Recommend 17 "wheels" to improve development efficiency

Day 6 of pyhon

Jackson XML is directly converted to JSON without writing entity classes manually

sql——课程实验考查

新知识:Monkey 改进版之 App Crawler

When SQL server2019 is installed, the next step cannot be performed. How to solve this problem?

Putty installation and use

"I was laid off by a big factory"

RT thread studio learning (VII) using multiple serial ports

Day 5 of pyhon
随机推荐
Nine project management issues that PM should understand
C language sizeof strlen
Construction of running water lamp experiment with simulation software proteus
Day 5 of pyhon
Kali与编程:如何快速搭建OWASP网站安全实验靶场?
Category 7
Test manager defines and implements test metrics
【WAX链游】发布一个免费开源的Alien Worlds【外星世界】脚本TLM
Curry carries the fourth game of the warriors against the Celtics
Study on display principle of seven segment digital tube
esp32 hosted
Recommend 17 "wheels" to improve development efficiency
Junior high school education, less than 3k, to 30k+ monthly salary, how wonderful life is without restrictions
Unable to load bean of class marked with @configuration
企业微信官方 加解密库 PHP7版本报错 mcrypt_module_open 未定义方法 并且被PHP抛弃 解决方法使用 openssl解决
Detailed explanation of TF2 command line debugging tool in ROS (parsing + code example + execution logic)
Explain ADC in stm32
RT thread studio learning (IX) TF Card File System
How to update kubernetes certificates
基于eNSP加防火墙的千人中型校园/企业网络规划与设计(附所有配置命令)