下图是S3C2440芯片的整体架构图:
其中,
AHB BUS为高速设备的总线,H即为high的意思。
APB BUS为低速设备的总线,P为英文单词peripheral(外围设备)。
不同的总线,挂载在上面的设备运行的频率肯定是不一样的,在我们这款S3C2440芯片中:
Fclk就是CPU的运行频率,最高可达400MHz
Hclk为高速设备的运行频率,最高可达136MHz
Pclk为低速设备的运行频率,最高可达68MHz
那么这三种时钟频率是怎么得到的,他们又是什么关系呢?
S3C2440这款芯片的时钟源为一个12M的晶振,再配合PLL(锁相环)就可以获得相应的频率。这里我们不对PLL的工作原理做详细,有兴趣的可以自查(好吧,我承认我不会)。下面给出一个时钟频率生成的结构图:
图中有些名词我们先解释一下:
- OSC是晶振的意思
- OM为选择器,可以设置它选择不同的时钟源 其中,OM[3:2]的设置可以获得不同的时钟来源,晶振(crystal)或者外部的时钟源(EXTCLK)
- MPLL:main PLL
- 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的一个过程:
当power变成高电平,也就是上电后:
- 复位引脚nRESET先维持一段时间(n代表低电平有效),等各种状态稳定后,才被拉高
- 上电后初始阶段,FCLK=晶振频率
- nRESET被拉高后,CPU开始运行,PLL锁存OM[3:2]的值
- 在lock time期间,CPU停止运行。PLL开始工作
- Lock time后,FCLK等于PLL输出的新时钟,CPU也开始工作
到这里,我们就大概知道这三种频率是怎么来的,以及他们的关系是什么样的了。虽然原理讲了一大堆,但是在实际的编程中,也就是设置一些寄存器的工作,了解原理只是为了我们更好的读懂芯片手册并设置寄存器。
这里我们举个例子,看一下怎么去设置寄存器,得到我们想要的时钟频率。假如我们想得到的时钟频率比是:
FCLK:HCLK:PCLK = 400MHz : 100MHz : 50MHz
(1)
时钟频率比为1:4:8,所以我们要设置CLKDIVN寄存器为b0101=0x5(默认CAMDIVN[9]=0)
(2)
由芯片给出的Fclk计算公式是:
Mpll就是我们要求的Fclk,Fin是晶振的频率12MHz,那么MDIV、PDIV和SDIV的值怎么得到呢?我们看下面的表格可以看出来,要得到12MHz的输入和400MHz的输出时,MDIV=92, PDIV=SDIV=1。那么MOLLCON寄存器的值就是(92<<12) | (1<<4) | (1<<0)
(3)
至于locktime的设置,我们用默认值就好了(一般不确定怎么设置的时候。用默认值就好了)
根据上面的三个步骤,我们汇总一下可以到下面的代码:
/* 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工作于新的频率
*/