WINCE6.0+S3C6410主要时钟控制

时间:2022-04-28 18:04:55

********************************LoongEmbedded*****************
作者:LoongEmbedded(kandi)
时间:2011.06.19

类别:WINCE驱动开发
********************************LoongEmbedded*****************

 

备注:S3C6410ARM内核时钟(ARMCLK)官方推荐的稳定的533MHz

DMC:动态内存控制器

 

S3C64103PLL,分为为APLLMPLLEPLL,其中APLL提供ARMCLK提供时钟给CPUMPLL分别提供HCLKAXI/AHB总线设备与提供PCLK时钟给APB总线设备外,EPLL提供SCLK给外设,特别是用于音频相关的时钟。

PLL最主要的意义在于输出比输入更高频率的时钟,这是系统在工作工作时候所需要的时钟,但我们可以通过外部提供的时钟源(EXTCLK)来提供慢速时钟ARMCLKHCLKPCLK来降低系统功耗。也可以通过软件来控制每个外设的时钟信号的启用或者禁止来控制系统功耗。下面就来开始学习系统是如何管理时钟的。

 

1.     APLLMPLLEPLL输出时钟及ARMCLKHCLKPCLKSCLK的确定

我们先来看

WINCE6.0+S3C6410主要时钟控制

1

1阐明了时钟产生逻辑:APLL用于ARM内核时钟操作,MPLL用于主时钟操作,EPLL用于特殊用途。操作系统分为三组,第一组是APLL产生的ARM时钟,第二组是MPLL产生的时钟,该时钟用于AXIAHBAPB总线操作,最后一组是EPLL产生的时钟,主要用于外设IPs,比如是UARTIISIIC等。

 

1.1 APLLMPLL输出频率的确定

根据图1,APLL,MPLL和EPLL的输出时钟,是如何确定呢?结合下图来理解

WINCE6.0+S3C6410主要时钟控制

图2

从图2对寄存器的描述可知APLL_CON/MPLL_CON寄存器的MDIV、PDIV和SDIV可以确定APLL及MPLL的输出时钟,再结合下图就可以知道如何设置MDIV、PDIV和SDIV了。

WINCE6.0+S3C6410主要时钟控制

图3

根据图3推荐的几组值,我们的系统选择FOUT=533MHZ这一组,那代码中是在哪里如何体现的呢?在src/oal/oallib/starup.s中下面的代码对MDIV、PDIV和SDIV设置

WINCE6.0+S3C6410主要时钟控制

图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输出的时钟呢?我们看下面这个表

WINCE6.0+S3C6410主要时钟控制

图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输出频率的推荐值

WINCE6.0+S3C6410主要时钟控制

图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所示

WINCE6.0+S3C6410主要时钟控制

图7

1.3改变PLL的输出频率

上面描述了对APLL、MPLL和EPLL输出频率寄存器的设置,先是比较之前的这些寄存器的值是否和现在要设置的一致,如果不一致,就要让现在的设置生效,这是通过调用PLL_NeedToConfigure函数来实现的,下面就来学习这个函数

WINCE6.0+S3C6410主要时钟控制

图8

下面我们来学习这个函数

1)       关闭APLL、MPLL和EPLL时钟输出

为什么要做这个动作呢?因为接下来要改变PLL的时钟输出,而PLL输出的时钟在PLL的lock-time时间之后才能给系统提供稳定的时钟,所以先采用FIN作为输入时钟,结合图1可更好理解,这个动作就是下面的代码来实现的

bic        r1, r1, #0x7

对CLK_SRC[0:2]位清零,下图对CLK_SRC[0:2]位的描述

WINCE6.0+S3C6410主要时钟控制

图9

2)       通过设置CLK_DIV0寄存器的设置来控制系统系统和具体的时钟,也就是确定ARMCLK、HCLK*2、HCLK和PCLK,我们先来看CLK_DIV0寄存器的相关位描述

WINCE6.0+S3C6410主要时钟控制

图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的

WINCE6.0+S3C6410主要时钟控制

图11

 

3)       设置PLL的lock time

APLL_LOCK,MPLL_LOCK和EPLL_LOCK寄存器用于设置对应的PLL的lock time,下面看这几个寄存器的描述

WINCE6.0+S3C6410主要时钟控制

图12

我们再来看看下面的描述可以更好去理解。

WINCE6.0+S3C6410主要时钟控制

图13

4)       设置PMS的值,可参考图4到图7之间的内容描述。

到此对PLL_NeedToConfigure函数的描述已经完成了。

 

1.4    检查CLK_DIV0寄存器是否和要设置的内容一致,如果不一致就要按照现在要配置的

内容来配置,实现的代码如下:

WINCE6.0+S3C6410主要时钟控制

图14

可见上面第2)部分的描述,下面来看看CLKDIV_NeedToConfigure函数的实现,

WINCE6.0+S3C6410主要时钟控制

图15