OK6410裸机程序(二)——系统时钟
一、时钟源的选择
时钟源的选择 时钟源的选择 时钟源的选择内部时钟会产生用于外部的时钟源,其说明如表 3-1 所示。当外部复位信号被声明时,OM[4:0]引脚决定了 S3C6410的操作模式。OM[0]引脚选择外部时钟源,例如,如果OM[0]是 0,则 XXTIpll(外部晶体)被选择。否则,XEXTCLK(外部时钟输入)被选择。在OK6410板上是外接12M晶振。如下图所示:
二、锁相环(PLL)
S3C6410 内部的三个PLL,分别是 APLL, MPLL和 EPLL。带有一个参考输入时钟操作频率和相位的同步
输出信号。在这个应用当中,包括基本模块的说明,如图 3-3 所示。电压控制振荡器(VCO)产生的输出频
率成正比,输入到直流电压。通过P,前置配器划分输入频率(FIN)。通过 M,主分频器分割 VCO的输出
频率,用于输入到相位频率检测器,(PFD)。通过 S,post 定标器划分为 VCO 的输出频率。相位差探测
器计算相位差和电荷泵的增加/减少输出电压。每个 PLL的输出时钟频率是可以计算的。如下图所示:
三、PLL 和输入参考时钟之间时钟选择
S3C6410 有三个 PLL,APLL 用于 ARM 时钟操作,MPLL 用于
主时钟操作,EPLL 用于特殊用途。时钟操作被分为三组。第一组是ARM时钟,从 APLL产生。MPLL产生主
系统时钟,用于操作AXI,AHB 和APB总线操作。最后一组是从 EPLL产生的,产生的时钟主要用于外设 IP’
s,例如,UART,IIS 和 IIC 等等,如下图所示。各总路线的外设时钟,就不一一例举了,当我们要用到时可以去手册上查找各自的应用。
四、设置系统时钟相关寄存器
在6410中,跟系统时钟设置相关寄存器有下面一些:
还有一个OTHER的寄存器,需要设置
下面是自己总结的设置时钟的基本流程:
附上C程序和汇编程序:
汇编程序:
.globl clock_init
clock_init:
/* 1.设置LOCK_TIME */
ldr r0, =0x7E00F000 /* APLL_LOCK */
ldr r1, =0x0000FFFF
str r1, [r0]
str r1, [r0, #4] /* MPLL_LOCK */
str r1, [r0, #8] /* EPLL_LOCK */
#define OTHERS 0x7e00f900
@ set async mode /* 当CPU时钟 != HCLK时,要设为异步模式 */
ldr r0, =OTHERS
ldr r1, [r0]
bic r1, #0xc0
str r1, [r0]
loop1: /* 等待,直到CPU进入异步模式 */
ldr r0, =OTHERS
ldr r1, [r0]
and r1, #0xf00
cmp r1, #0
bne loop1
/* SYNC667 */
/* MISC_CON[19] = 0 */
#define ARM_RATIO 0 /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1) */
#define HCLKX2_RATIO 1 /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */
#define HCLK_RATIO 1 /* HCLK = HCLKX2 / (HCLK_RATIO + 1) */
#define PCLK_RATIO 3 /* PCLK = HCLKX2 / (PCLK_RATIO + 1) */
#define MPLL_RATIO 0 /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1) */
ldr r0, =0x7E00F020 /* CLK_DIV0 */
ldr r1, =(ARM_RATIO) | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12)
str r1, [r0]
/* 2.配置时钟 */
/* 2.1 配置APLL */
/* 2.1.1 设置APLL
* 2.1.2 MUXAPLL
* 2.1.3 SYNC667
* 2.1.4 DIVAPLL
*/
#define APLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1))
ldr r0, =0x7E00F00C
ldr r1, =APLL_CON_VAL
str r1, [r0] /* APLL_CON, FOUTAPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */
/* 2.2 配置MPLL */
/* 2.2.1 设置MPLL
* 2.2.2 MUXMPLL
* 2.2.3 SYNCMUX
* 2.2.4 SYNC667
* 2.2.5 HCLKX2_RATIO
* 2.2.6 PCLK_RATIO
*/
#define MPLL_CON_VAL ((1<<31) | (266 << 16) | (3 << 8) | (1))
ldr r0, =0x7E00F010
ldr r1, =MPLL_CON_VAL
str r1, [r0] /* MPLL_CON, FOUTMPL = MDIV * Fin / (PDIV*2^SDIV) = 266*12/(3*2^1) = 532MHz */
/* 3.选择PLL的输出作为时钟源 */
ldr r0, =0x7E00F01C
ldr r1, =0x03
str r1, [r0]
C程序:
/*************************************************************************/
/*名称:系统时钟设置 */
/*参数:ARM_CLK=532 HCLK=133 HCLKX2=266 PCLK=66.5 */
/*************************************************************************/
#define rAPLL_LOCK (*((volatile unsigned long *)0x7E00F000))
#define rMPLL_LOCK (*((volatile unsigned long *)0x7E00F004))
#define rEPLL_LOCK (*((volatile unsigned long *)0x7E00F008))
#define rAPLL_CON (*((volatile unsigned long *)0x7E00F00C))
#define rMPLL_CON (*((volatile unsigned long *)0x7E00F010))
#define rCLK_SRC (*((volatile unsigned long *)0x7E00F01C))
#define rCLK_DIV0 (*((volatile unsigned long *)0x7E00F020))
#define rCLK_DIV1 (*((volatile unsigned long *)0x7E00F024))
#define rCLK_DIV2 (*((volatile unsigned long *)0x7E00F028))
#define rOTHERS (*((volatile unsigned long *)0x7E00F900))
#define ARM_RATIO 0 /* ARMCLK = DOUTAPLL / (ARM_RATIO + 1) */
#define HCLKX2_RATIO 1 /* HCLKX2 = HCLKX2IN / (HCLKX2_RATIO + 1) */
#define HCLK_RATIO 1 /* HCLK = HCLKX2 / (HCLK_RATIO + 1) */
#define PCLK_RATIO 3 /* PCLK = HCLKX2 / (PCLK_RATIO + 1) */
#define MPLL_RATIO 0 /* DOUTMPLL = MOUTMPLL / (MPLL_RATIO + 1) */
#define SDIV 1
#define PDIV 3
#define MDIV 266
#define EN 1 //使能PLL
void Clock_Init()
{
rAPLL_LOCK = 0x0000ffff;
rMPLL_LOCK = 0x0000ffff;
rEPLL_LOCK = 0x0000ffff; //时钟锁存时间设定
rOTHERS &= ~( 3 << 6); //将时钟设置成异步模式
while( (rOTHERS & 0xf00) != 0 );//等待进入异步模式
rCLK_DIV0 = ARM_RATIO | (MPLL_RATIO << 4) | (HCLK_RATIO << 8) | (HCLKX2_RATIO << 9) | (PCLK_RATIO << 12);//设置CLK_DIV0的分频参数
rAPLL_CON = SDIV | (PDIV << 8) | (MDIV << 16) | (EN << 31);//设置FOUT=532M
rMPLL_CON = SDIV | (PDIV << 8) | (MDIV << 16) | (EN << 31);//设置FOUT=532M
rCLK_SRC = 0x03;//时钟源选择}