********************************LoongEmbedded*****************
作者:LoongEmbedded(kandi)
时间:2011.06.19
类别:WINCE驱动开发
********************************LoongEmbedded*****************
备注:S3C6410的ARM内核时钟(ARMCLK)官方推荐的稳定的533MHz。
DMC:动态内存控制器
S3C6410有3个PLL,分为为APLL、MPLL和EPLL,其中APLL提供ARMCLK提供时钟给CPU,MPLL分别提供HCLK给AXI/AHB总线设备与提供PCLK时钟给APB总线设备外,EPLL提供SCLK给外设,特别是用于音频相关的时钟。
PLL最主要的意义在于输出比输入更高频率的时钟,这是系统在工作工作时候所需要的时钟,但我们可以通过外部提供的时钟源(EXTCLK)来提供慢速时钟ARMCLK、HCLK和PCLK来降低系统功耗。也可以通过软件来控制每个外设的时钟信号的启用或者禁止来控制系统功耗。下面就来开始学习系统是如何管理时钟的。
1. APLL、MPLL和EPLL输出时钟及ARMCLK、HCLK、PCLK和SCLK的确定
我们先来看
图1
图1阐明了时钟产生逻辑:APLL用于ARM内核时钟操作,MPLL用于主时钟操作,EPLL用于特殊用途。操作系统分为三组,第一组是APLL产生的ARM时钟,第二组是MPLL产生的时钟,该时钟用于AXI、AHB和APB总线操作,最后一组是EPLL产生的时钟,主要用于外设IPs,比如是UART、IIS、IIC等。
1.1 APLL和MPLL输出频率的确定
根据图1,APLL,MPLL和EPLL的输出时钟,是如何确定呢?结合下图来理解
图2
从图2对寄存器的描述可知APLL_CON/MPLL_CON寄存器的MDIV、PDIV和SDIV可以确定APLL及MPLL的输出时钟,再结合下图就可以知道如何设置MDIV、PDIV和SDIV了。
图3
根据图3推荐的几组值,我们的系统选择FOUT=533MHZ这一组,那代码中是在哪里如何体现的呢?在src/oal/oallib/starup.s中下面的代码对MDIV、PDIV和SDIV设置
图4
结合图3,我们选择FOUT=533MHZ,所以有MDIV=266,PDIV=3,SDIV=1,这样APLL输出的时钟频率就为667MHZ,这样我们就可以有下面的赋值
APLL_MVAL EQU (266)
APLL_PVAL EQU (3)
APLL_SVAL EQU (1)
这几个值是在PLATFORM/COMMON/SRC/SOC/S3C6410_SEC_V1/OAL/INC/s3c6410.inc中设置的
接下来怎么确定MPLL输出的时钟呢?我们看下面这个表
图5
这样我们就可以确定MPLL输出的时钟为266MHZ,从而结合图3可知MPLL对应的MDIV=266、PDIV=3和SDIV=2,这样我们就可以有下面的赋值
MPLL_MVAL EQU (266)
MPLL_PVAL EQU (3)
MPLL_SVAL EQU (2)
1.2 EPLL输出频率的确定
EPLL输出频率是由EPLL_CON0和EPLL_CON1寄存器的MDIV,PDIV,SDIV和KDIV的值来决定的,下图是EPLL输出频率的推荐值
图6
根据图6的选择可知MDIV=28,PDIV=1,SDIV=2,KDIV=0,从而可以有下面的赋值:
EPLL_MVAL EQU (254)
EPLL_PVAL EQU (9)
EPLL_SVAL EQU (2)
EPLL_KVAL EQU (0)
对EPLL_CON0和EPLL_CON1寄存器的设置也是在在src/oal/oallib/starup.s中设置的,接着图4,这些设置代码如图7所示
图7
1.3改变PLL的输出频率
上面描述了对APLL、MPLL和EPLL输出频率寄存器的设置,先是比较之前的这些寄存器的值是否和现在要设置的一致,如果不一致,就要让现在的设置生效,这是通过调用PLL_NeedToConfigure函数来实现的,下面就来学习这个函数
图8
下面我们来学习这个函数
1) 关闭APLL、MPLL和EPLL时钟输出
为什么要做这个动作呢?因为接下来要改变PLL的时钟输出,而PLL输出的时钟在PLL的lock-time时间之后才能给系统提供稳定的时钟,所以先采用FIN作为输入时钟,结合图1可更好理解,这个动作就是下面的代码来实现的
bic r1, r1, #0x7
对CLK_SRC[0:2]位清零,下图对CLK_SRC[0:2]位的描述
图9
2) 通过设置CLK_DIV0寄存器的设置来控制系统系统和具体的时钟,也就是确定ARMCLK、HCLK*2、HCLK和PCLK,我们先来看CLK_DIV0寄存器的相关位描述
图10
从图5可知ARMCLK=533MHZ,HCLK*2=266MHZ,HCLK=133MHZ,PCLK=66MHZ,也知DOUTapll=533MHZ,MOUTmpll=266MHZ,这样根据图10中的公式就可以算出ARM_RATIO=0,MPLL_RATIO=1,HCLK_RATIO=1,HCLK*2_RATIO=1,PCLK_RATIO=1。这里通过下图来理解HCLK*2IN和HCLK*2以及怎么算出HCLK*2_RATIO的
图11
3) 设置PLL的lock time
APLL_LOCK,MPLL_LOCK和EPLL_LOCK寄存器用于设置对应的PLL的lock time,下面看这几个寄存器的描述
图12
我们再来看看下面的描述可以更好去理解。
图13
4) 设置PMS的值,可参考图4到图7之间的内容描述。
到此对PLL_NeedToConfigure函数的描述已经完成了。
1.4 检查CLK_DIV0寄存器是否和要设置的内容一致,如果不一致就要按照现在要配置的
内容来配置,实现的代码如下:
图14
可见上面第2)部分的描述,下面来看看CLKDIV_NeedToConfigure函数的实现,
图15