下图是S3C2440芯片的整体架构图:

s3c2440架构 s3c2440芯片图_默认值

其中,

AHB BUS为高速设备的总线,H即为high的意思。

APB BUS为低速设备的总线,P为英文单词peripheral(外围设备)。

不同的总线,挂载在上面的设备运行的频率肯定是不一样的,在我们这款S3C2440芯片中:

s3c2440架构 s3c2440芯片图_s3c2440架构_02

Fclk就是CPU的运行频率,最高可达400MHz

Hclk为高速设备的运行频率,最高可达136MHz

Pclk为低速设备的运行频率,最高可达68MHz

那么这三种时钟频率是怎么得到的,他们又是什么关系呢?

        S3C2440这款芯片的时钟源为一个12M的晶振,再配合PLL(锁相环)就可以获得相应的频率。这里我们不对PLL的工作原理做详细,有兴趣的可以自查(好吧,我承认我不会)。下面给出一个时钟频率生成的结构图:

s3c2440架构 s3c2440芯片图_s3c2440架构_03

图中有些名词我们先解释一下:

  1. OSC是晶振的意思
  2. OM为选择器,可以设置它选择不同的时钟源                                                        其中,OM[3:2]的设置可以获得不同的时钟来源,晶振(crystal)或者外部的时钟源(EXTCLK)
  3. MPLL:main PLL
  4. UPLL:USB PLL(用于usb设备)

上面的时钟频率生成图虽然看起来画了很多的东西,但是我们可以总结为一个简单的流程,就是:

 

晶振 ->  MPLL  -> FCLK  -> CPU

      |            |

      |            |(HDIV) -> HCLK ->AHB总线->nand flash控制器、

      |            |

      |            |(PDIV)->PCLK ->APB总线->I2C、GPIO、SPI等

      |

      | -> UPLL -> USB  

 

        我们可以得到,Fclk是由晶振和MPLL得到的,而Fclk是用于CPU运行的频率。Fclk再经过分频器(HDIV和PDIV)之后就可以得到Hclk和Pclk。

        下面我大概说明一下获得Fclk的一个过程:

s3c2440架构 s3c2440芯片图_晶振_04

当power变成高电平,也就是上电后:

  1. 复位引脚nRESET先维持一段时间(n代表低电平有效),等各种状态稳定后,才被拉高
  2. 上电后初始阶段,FCLK=晶振频率
  3. nRESET被拉高后,CPU开始运行,PLL锁存OM[3:2]的值
  4. 在lock time期间,CPU停止运行。PLL开始工作
  5. Lock time后,FCLK等于PLL输出的新时钟,CPU也开始工作

       到这里,我们就大概知道这三种频率是怎么来的,以及他们的关系是什么样的了。虽然原理讲了一大堆,但是在实际的编程中,也就是设置一些寄存器的工作,了解原理只是为了我们更好的读懂芯片手册并设置寄存器。

       这里我们举个例子,看一下怎么去设置寄存器,得到我们想要的时钟频率。假如我们想得到的时钟频率比是:

                                             FCLK:HCLK:PCLK = 400MHz : 100MHz : 50MHz

(1)

时钟频率比为1:4:8,所以我们要设置CLKDIVN寄存器为b0101=0x5(默认CAMDIVN[9]=0)

s3c2440架构 s3c2440芯片图_晶振_05

(2)

由芯片给出的Fclk计算公式是:

s3c2440架构 s3c2440芯片图_s3c2440架构_06

Mpll就是我们要求的Fclk,Fin是晶振的频率12MHz,那么MDIV、PDIV和SDIV的值怎么得到呢?我们看下面的表格可以看出来,要得到12MHz的输入和400MHz的输出时,MDIV=92, PDIV=SDIV=1。那么MOLLCON寄存器的值就是(92<<12) | (1<<4) | (1<<0)

s3c2440架构 s3c2440芯片图_默认值_07

s3c2440架构 s3c2440芯片图_默认值_08

(3)

至于locktime的设置,我们用默认值就好了(一般不确定怎么设置的时候。用默认值就好了)

s3c2440架构 s3c2440芯片图_s3c2440架构_09

 

根据上面的三个步骤,我们汇总一下可以到下面的代码:

/* 2.设置时钟 */
	/*设置MPLL, FCLK:HCLK:PCLK = 400MHz : 100MHz : 50MHz*/
	/*为了保险先初始化一下locktime*/
	ldr r0, =0x4C000000
	ldr r1, =0xFFFFFFFF
	str r1, [r0]

	/*设置CLKDVIN:
	  *HDIVN[2:1] :    10  -  HCLK=FCLK/4
	  *PDVIN[0]    :     1   -   PCLK=HCLK/2
	  */
	ldr r0, =0x4C000014
	ldr r1, =0x5
	str r1, [r0]

	/*设置CPU为异步模式*/
	mrc p15,0,r0,c1,c0,0
	orr r0,r0,#0xc0000000  //R1_nF:OR:R1_iA 
	mcr p15,0,r0,c1,c0,0

	/*
	  *Mpll = (2 * m * Fin) / (p * 2S) 
	  *m = (MDIV + 8), p = (PDIV + 2), s = SDIV
	  *当Fin=12MHz,若要 Mpll=400MHz,则有MDIV=92, PDIV=SDIV=1
	  */
	ldr r0, =0x4C000004
	ldr r1, =(92<<12) | (1<<4) | (1<<0)
	str r1, [r0]

	/*一旦设置了PLL,就会锁定locktime直到PLL输出稳定
	  *然后CPU工作于新的频率
	  */