相关概念

时钟脉冲信号是数字电路时序逻辑的基础,它是按一定的电压幅度,一定的时间间隔连续发出的脉冲信号。时钟信号由晶振和锁相环PLL产生,单位为Hz,表示每秒名时钟信号的个数。由石英晶体产生的时钟信号频率一般较小,需要配合PLL进行倍频,再进行分频之后供给各个模块使用。使用PLL具有更加灵活的特点,通过配置PLL的相关寄存器,可以在一个晶振时钟源上获得多个时钟频率。

时钟体系

学习一款处理器的时钟体系,需要关注以下几点:

  1. 外部晶振的频率
  2. 几个PLL
  3. PLL分频出了几个时钟信号
  4. 产生的时钟信号的用途

S3C2440

Alt text
晶振频率:12MHz
2个PLL:MPLL、UPLL
MPLL产生了3个时钟信号:FCLK、HCLK、PCLK
UPLL产生了1个时钟信号:UCLK

各个时钟信号的用途:

Alt text

S3C6410

Alt text
晶振频率:12MHz
3个PLL:APLL MPLL EPLL
产生了四个时钟信号:ACLK HCLK PCLK SCLK

各个时钟信号的用途:
Alt text

S5PV210

Alt text

晶振频率:24MHz
4个PLL:APLL MPLL EPLL VPLL
产生了三类时钟体系:主系统时钟体系(MSYS)、显示相关的时钟(DSYS)、外围设备的时钟(PSYS)
各个时钟信号的用途:
Alt text

时钟初始化流程

Alt text

初始化流程如下:

  1. 上电几毫秒后,晶振输出稳定,FCLK=晶振频率,nRESET信号恢复高电平后,CPU开始执行指令
  2. 启动MPLL,设置MPLL的寄存器
  3. 在设置MPLL的寄存器后,需要等待一段时间(Lock Time),MPLL的输出才稳定。在这段时间内,FCLK停振,CPU停止工作。Lock Time的长短由寄存器LOCKTIME设定。
  4. Lock Time之后,MPLL输出正常,CPU重新工作在新的FCLK下。

TODO:

  1. 配置Lock Time
  2. 配置FCLK HCLK PCLK的分频系数
  3. 配置FCLK
  4. HDIVN不为0时,需要执行指定的指令,将CPU设置成异步总线模式(FCLK不等于HCLK时为异步总线模式)

初始化代码

S3C2440

设置Lock Time

Alt text
Lock Time一般采用默认值即可。

设置分配系数

Alt text

参考2440的uboot代码,分频系数选择1:4:8,即HDIVN=2, PDIVN=1。这需要设置CLKDIVN寄存器:
Alt text

代码:

#define CLKDIVN 0x4C000014
ldr r0, =CLKDIVN
mov r1, #0x5
str r1, [r0]

设置CPU为异步总线模式

Alt text
代码如下:

mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #0xc0000000   @这个值需要参考ARM9核心手册,查看nF位和iA位是第几位
mcr p15, 0, r0, c1, c0, 0

设置FCLK

Alt text

选择输出频率为405MHz,则MDIV=127, PDIV=2, SDIV=1,相关寄存器为MPLLCON:
Alt text

代码如下:

#define MPLLCON 0x4c000008
#define MPLL_405MHZ (127<<12)|(2<<4)|(1<<0)
ldr r0, =MPLLCON
mov r1, #MPLL_405MHZ
str r1, [r0]

S3C6410

设置Lock Time

Alt text
保持Lock Time时间为默认值。

设置分频系数

Alt text

由此可知,系统产生时钟信号的过程如下:
Alt text

相关寄存器的值配置方法如下:
Alt text
Alt text

计算方法如下:
ARMCLK = APLLOUT / (DIVARM + 1)
HCLKX2 = MPLLOUT / (DIVHCLKX2 + 1)
HCLK = HCLKX2 / (DIVHCLK + 1)
PCLK = HCLKX2 / (DIVPCLK + 1)

参考uboot代码,在smdk6410.h中有如下定义:
Alt text

在APLL和MPLL都是533MHz的情况下,分配系数应该配置成:
DIVARM = 0
DIVHCLKX2=1
DIVHCLK=1
DIVPCLK=3
根据以上频系数求得的各时钟频率是:
ARMCLK=533MHZ
HCLKX2=266MHZ
HCLK=133MHZ
PCLK=66MHZ

设置代码如下:

#define CLK_DIV0 0x7E00F020
#define DIV_VAL ((0x0 << 0) | (0x1 << 9) | (0x1 << 8) | (0x3 << 12))
clock_init:
    ldr r0, =CLK_DIV0
    ldr r1, =DIV_VAL
    str r1, [r0]

设置CPU为异步总线模式

将6410设为异步总线模式只需要设置OTHERS寄存器的第7位即可,描述如下:
Alt text

设置代码如下:

#define OTHERS 0x7e00f900
ldr r0, =OTHERS
ldr r1, [r0]
bic r1, 1, 0xc0      @11000000,清除第6位的作用是让MPLL成为HCLK和PCLK的时钟源
str r1, [r0]

设置FCLK

只需设置好APLL和MPLL的输出频率即可,参考芯片手册:
Alt text
Alt text

设置代码如下:

#define APLL_CON 0x7e00f00c
#define MPLL_CON 0x7e00f010
#define PLL_VAL ((0x1 << 31) | (266 << 16) | (3 << 8) | (1 << 0))
    ldr r0, =APLL_CON
    ldr r1, =PLL_VAL
    str r1, [r0]
    
    ldr r0, =MPLL_CON
    ldr r1, =PLL_VAL
    str r1, [r0]

选择时钟源

对于6410,还需要设置一下时钟源选择器,选择从PLL产生的时钟,而不是外部的时钟,相关寄存器是CLK_SRC:
Alt text
Alt text

代码如下:

#define CLK_SRC 0x7e00f01c
    ldr r0, =CLK_SRC
    mov r1, #0x3
    str r1, [r0]

S5PV210

Alt text

设置Lock Time

Alt text

采用默认值即可。

设置分频系数

设置分频系数相关的寄存器是CLK_DIV0,以下是描述:
Alt text

分频系数的设置可以参考uboot源代码smart210.h中关于分频系数的设置。

设置CPU为异步总线模式

210不需要这一步设置。

设置ARMCLK

设置APLL和MPLL的输出时钟即可,相关寄存器是APLL_CON0和MPLL_CON0,它们有相同的格式。
Alt text
Alt text

选择时钟源

这一步和6410是一样的,设置的寄存器是CLD_SRC0的APLL_SEL位,将其设置成1。

  • 无标签