一.什么是时钟系统
时钟是工作中的同步节拍。S5PV210裸机开发中时钟是一个很重要的部分,需要通过一定的频率来控制信号的发送。系统中有很多器件协同工作,就需要这些时钟信号来协调管理。而这些时钟信号就是由时钟系统提供并且管理的。系统时钟一般由外部低频24MHZ晶体振荡器通过控制逻辑PLL倍频器倍频(实际上PLL倍频器的功能就是放大运行频率)产生。然后再时钟系统中就是通过不同的DIV分频器分频,来给不同的部件提供所需要的时钟的。
二.时钟域
因为S5PV210的时钟体系复杂,内部有众多模块,可以把内部的时钟划分为3大类时钟,及划分了3个域,使用四个倍频器(PLL),对应3个域分别是APLL为MSYS域提供使用、MPLL供DSYS使用、EPLL供PSYS使用,而剩余一个VPLL供video等相关的时钟使用。关于时钟域。
-
MSYS 复杂时钟系统中的主要核心的时钟信号又称为主系统时钟。包含CPU处理器内工作的时钟信号,及主频ARMCLK,为DMC0和DMC1使用的高频时钟HCLK_MSYS等,MSYS同时还为dram控制器,IRAM、IROM、中断控制器提供时钟信号。
-
DSYS 是和显示有关的时钟模块,包含高频时钟HCLK_DSYS、低频时钟PCLK_DSYS。
-
PSYS 和各个外围设备有关的时钟模块,比如各种接口。包含高频时钟HCLK_PSYS、低频时钟PCLK_PSYS、SCLK_ONENAND。
各类时钟参考值:
三.时钟源
s5pv210外部有四个晶振接口,我们设计板子硬件时,可以根据需要决定在哪里接入晶振。接了晶振之后,相应的模块就能产生震荡,产生原始时钟,原始时钟因为频率不一不好控制,所以经过一系列的筛选开关进入相应的PLL电路生成倍频后的高频信号,高频信号再经过分频到达芯片内部各个模块上。
四. 初始化时钟系统
是通过start.S中定义好时钟分频寄存器
#define CLKDIVN 0x14800014 /*clock divisor register */
然后对这个时钟分频寄存器经行配置。
/*FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0,=CLKDIVN
mov r1, #3
str r1, [r0]
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*选择是否配置cpu,ifndf是防止重复引用cpu_init_crit函数。*/
bl cpu_init_crit
#endif
然后调用clock_init时钟初始化函数,对时钟相关进行设置。
void clock_init()
{
CLK_SRC0 = 0x0;
// 设置时钟开关,此时未设置好PLL和分频参数所以不能使用。待设置好后重新设置时钟开关。
MPLL_LOCK = 0x0000FFFF;
// 控制PLL锁定周期,设置锁定时间,使用默认值即可 APLL_LOCK = 0x0000FFFF;
CLK_DIV0 = 0x14131440;
//设置分频,及分频器参数设置
APLL_CON0 = APLL_VAL;
MPLL_CON = MPLL_VAL; //打开、关闭PLL电路、设置倍频参数
//设置分频器PLL
CLK_SRC0 = 0x10001111;
//使用PLL设置各种时钟开关
}
以上代码共分5步操作:
-
CLK_SRC0 = 0x0;不适用PLL,设置各种时钟开关,根据时钟设置图, 因为我们需要使用外接的24MHz的晶振,FIN就是最初晶振时钟频率,然后进行倍频操作。如上图可知,我们的APLL和MPLL的时钟源都是由FINPLL决定的,而和FINPLL有关的寄存器就是CLK_SRCO,而我们此时并没有对PLL以及分频参数进行配置,所以不可使用PLL。我们需要手动设置CLK_SRCO完成对时钟开关的设置。
-
MPLL_LOCK = 0x0000FFFF; 设置锁定时间,控制PLL的锁定周期,这里采用的是默认值,因为时钟从Fin状态提升到目标频率时,需要一定的时间,也就是说,刚开始的时钟是不稳定的,不可以使用。而这个时间就是锁定时间。
-
CLK_DIV0 = 0x14131440; CLK_DIV0是和分频有关的寄存器,根据上文给出的时钟设置参考值。DIV就是分频器,因为各个器件要求的时钟频率不同,通过倍频后,还有进行分频才可以被各个器件使用。
以ARMCLK为例,freq(ARMCLK)=1000MHz ,又如上图可知ARMCLK=MOUT_MSYS /(APLL_RATIO + 1) ,如上两式两两结合。
而经过接下来的步骤中MOUT_MSYS 会被设置1000MHz,MOUT_DSYS =667MHz,MOUT_PSYS =667MHz。
ARMCLK = 1000MHz = MOUT_MSYS / (APLL_RATIO + 1),
所以APLL_RATIO=0。
SCLKA2M=200MHz=SCLKAPLL / (A2M_RATIO + 1),
所以A2M_RATIO=4。
HCLK_MSYS=200MHz=ARMCLK / (HCLK_MSYS_RATIO + 1),
所以HCLK_MSYS_RATIO=4。
PCLK_MSYS=100MHz=HCLK_MSYS / (PCLK_MSYS_RATIO + 1),
所以PCLK_MSYS_RATIO=1。
HCLK_DSYS=166MHz=MOUT_DSYS / (HCLK_DSYS_RATIO + 1),
所以 HCLK_DSYS_RATIO=3。
PCLK_DSYS=83MHz=HCLK_DSYS / (PCLK_DSYS_RATIO + 1),
所以PCLK_DSYS_RATIO=1 。
HCLK_PSYS=133Mhz=MOUT_PSYS / (HCLK_PSYS_RATIO + 1),
所以HCLK_PSYS_RATIO=4。
PCLK_PSYS=66Mhz=HCLK_PSYS / (PCLK_PSYS_RATIO + 1),
所以HCLK_PSYS_RATIO=1。
CLK_DIV0中存储的正是如上算出的数。也就是说会把算出的结果对应
图中比特位放入到寄存器中。
所以CLK_DIV0 = 0x14131440。由此设置好分频器的参数。
- APLL_CON0 = APLL_VAL; MPLL_CON = MPLL_VAL;设置PLL。APLL和MPLL的启动是通过设置APLL_CON0和MPLL_CON寄存器来实现的。
关于APLL:
我们已经知道FINPLL=24MHz,而我们需要FOUT=1000MHz。根据计算公式:
FOUT=MDIVFINPLL/(PDIV2^(SDIV-1))= 1000 MHz 。我们就需要设置MDIV、PDIV、SDIV的值来使得结果等于1000MHz。
关于MPLL:
我们需要通过设置使得FOUT=667MHz,而FIN=24MHz。由公式:FOUT=MDIVFIN/(PDIV2^SDIV) = 667 MHz。我们需要配置MDIV和PDIV、SDIV使得等式成立。
对应这上图再把我们配置好的MDIV、SDIV、PDIV的值放入对应比特位中,
- CLK_SRC0 = 0x10001111; 使用PLL设置时钟开关。依然以APLL,MPLL为例,图中的MUX是多选一开关,作用就是用来选择输入的时钟源,对应的寄存器就是CLK_SRC0。
对应如上时钟设置参考图。
APLL_SEL=1,使用 FOUTAPLL
MPLL_SEL=1,使用 FOUTMPLL
EPLL_SEL=1,使用 FOUTEPLL
VPLL_SEL=1,使用 FOUTVPLL
MUX_MSYS_SEL=0,使用 SCLKAPLL
MUX_DSYS_SEL=0,使用 SCLKMPLL
MUX_PSYS_SEL=0,使用 SCLKMPLL
ONENAND_SEL=1,使用 HCLK_DSYS
所以 CLK_SRC0=0x10001111;
五. 总结
总的来说,S5PV210的时钟系统的设计思路是先把由MUX开关选择的晶振产生的固定时钟输入,然后通过各个PLL倍频器把时钟进行倍频放大到一定的频率,然后一部分可以直接成为了时钟域的时钟频率,而另一部分再经过一系列的MUX多选一选择后,然后再经过DIV分频器进行分频后成为各个时钟域的时钟频率。
本博客是网络知识小白理解汇总而来,写得不好,希望大佬们批评指导。