05. 时钟系统编程
1. 时钟概念解析
1)什么是时钟?
① 按一定电压幅度,一定时间间隔连续发出的脉冲信号
② 时钟频率是每秒产生时钟脉冲的个数
③ 注意时钟信号的占空比特性
2)为什么需要时钟?
① 时钟信号是时序逻辑的基础,决定逻辑单元中的状态何时更新
② 时钟是同步工作系统的同步节拍
SoC内部器件(e.g. CPU/DRAM/UART)需要彼此协同工作,因此需要一个同步时钟系统来指挥
3)如何获得时钟?
A. 外部晶振
通过SoC的引脚直接引入外部晶振的时钟信号
B. 外部晶振 + SoC内部CMU(Clock Management Unit)
通过外部晶振 + PLL生成高频时钟,再对高频时钟进行分频,供SoC各模块使用。S5PV210就采用这种方式。
说明1:为什么不采用外部高频晶振直接供SoC使用?
① 高频晶振价格昂贵
② 芯片外部电路不适宜使用过高频率,传导辐射难以控制
说明2:为什么CMU要先倍频再分频?
因为SoC内部各模块使用的频率不同,无法统一供应。因此先通过PLL产生高频时钟,再由各模块根据需要对时钟进行分频使用(有的模块还要分频多次)
4)时钟频率的影响
① 一般SoC的时钟频率均可以通过编程设置
② 采用高频时钟可以获得更好的性能,但是能耗也更大
③ 为降低能耗可以关闭SoC内部不使用的外设,关闭方法就是禁用该模块的时钟
2. S5PV210时钟系统解析
1)S5PV210时钟域简介
S5PV210将所有时钟划分为3个域进行管理,
① MSYS(main system)
包含时钟:Cortex-A8/DMC/3D/iRAM & iROM/INTC
总线最高频率:200MHz
② DSYS(display system)
包含时钟:与显示相关的时钟(e.g. FIMC/JPEG)
总线最高频率:166MHz
③ PSYS(peripheral system)
包含时钟:与外设相关的时钟(e.g. UART/SPI)
总线最高频率:133MHz
说明1:关于总线频率
S5PV210内部的各个模块通过AMBA总线连接,AMBA总线的高频分支为AHB(AXI)总线,低频分支为APB总线。各时钟域中的HCLK_xxx即为该域中AHB总线的频率;PCLK_xxx即为该域中APB总线的频率。
SoC内部的各个外设挂在总线上工作,所以该外设的时钟来自他挂载的总线。例如串口UART挂在PSYS域下的APB总线,因此串口时钟来源为PCLK_PSYS(当然,UART还可以选择其他时钟源)
说明2:为了获得更好的性能,可以将总线频率配置为最高值(e.g. 三星推荐值)
说明3:三个时钟域通过异步桥连接
2)S5PV210 CMU框架
A. CMU的位置
① CMU属于system controller(SYSCON)的一部分
② SYSCON管理CMU和PMU两个模块
B. CMU的输入
① 外部晶振
XXTI:
a. 通常情况下CMU和PLL以XXTI为输入产生其他各种时钟
b. XXTI的可使用频率为12 ~ 50MHz,三星推荐使用24MHz的时钟,因为S5PV210中iROM的设计基于24MHz
XXTI推荐匹配iROM是因为系统刚启动时,各PLL尚未工作,此时使用的时钟就是XXTI;而启动流程代码是从iROM开始运行的。
c. X210开发板就使用了24MHz的XXTI晶振
XUSBXTI:
a. 根据CMU框图,只有XXTI和XUSBXTI可以作为PLL的输入(当然,通常使用XXTI)。
b. XUSBXTI还可以作为输入,供USB PHY产生SCLK48时钟,该时钟可供USB使用。
c. X210开发板使用了24MHz的XUSBXIT晶振
XHDMIXTI:
a. XHDMIXTI可以供给VPLL使用,也可以供给HDMI PHY用于生成SCLK54
b. X210开发板使用了27MHz的XHDMIXTI晶振
补充:XRTCXTI晶振专供RTC使用,该晶振指定为32.768KHz
② USB PHY
以XUSBXTI为输入,产生30MHz和48MHz时钟供USB模块使用
③ HDMI PHY
以XHDMIXTI为输入,产生54MHz时钟供HDMI模块使用
④ PLL
总体来说,各PLL以外部晶振为输入,将其倍频产生高频时钟再作为CMU的输入
具体来说,各PLL的输入和输出如下,
APLL:以FINPLL为输入,产生30MHz ~ 1GHz时钟
MPLL:以FINPLL为输入,产生50MHz ~ 2GHz时钟
EPLL:以FINPLL为输入,产生10MHz ~ 600MHz时钟
VPLL:以FINPLL或SCLK_HDMI27M为输入,产生10MHz ~ 600MHz时钟(但VPLL一般专用于生成54MHz的video clock)
说明:PLL与时钟域的对应关系
a. Cortex-A8和MSYS域时钟使用APLL(e.g. ARMCLK/HCLK_MSYS/PCLK_MSYS)
b. DSYS和PSYS域时钟使用MPLL和EPLL(e.g. / HCLK_DSYS / PCLK_DSYS / HCLK_PSYS /PCLK_PSYS以及其他外设时钟)
但通常使用MPLL
c. video clock使用VPLL
C. CMU的输出
各时钟域的总线时钟以及在此基础上分频产生的各模块时钟(应为special clock)
3)S5PV210时钟关系
A. MUX开关
用于选择时钟源,对应时钟源寄存器的某几个bit位
说明:glitch-free & non-glitch-free clock mux
glitch-free mux:上图中的灰色mux。glitch-free mux在切换时钟时不会导致故障,前提是保证切换涉及的时钟源均在运行。
non-glitch-free mux:上图中的白色mux。non-glitch-free mux在切换时钟时可能出现故障,因此在切换时钟前建议关闭该mux的输出(通过设置CLK_SRC_MASK寄存器实现)。当时钟切换完成后,再使能该mux的输出。
B. DIV分频器
分频器是一个硬件设备,可以对时钟源进行n分频(可用分频系数见上图),分频器在编程时也是对应寄存器的某几个bit位
3. S5PV210时钟初始化代码解析
1)关键寄存器解析
A. xPLL_LCOK
① 锁相环产生稳定时钟需要一段时间,xPLL_LOCK寄存器控制PLL所需的锁定时间。
② 一般编程时采用默认值即可
③ 通过xPLL_CON寄存器的bit[29]可以查询该PLL是否锁定成功
B. xPLL_CONn
① xPLL_CONn寄存器的功能,
a. 打开/关闭PLL电路
b. 查看PLL锁定状态
b. 设置PLL倍频参数
② 为确保PLL工作状态稳定,建议采用三星推荐的M/P/S值
C. CLK_SRCn
① CLK_SRCn寄存器用来设置时钟源,对应时钟关系图中的MUX开关
② APLL_SEL位的初始值位0,所以系统在上电阶段直接使用外部晶振产生的时钟,所以推荐XXTI晶振时钟频率与iROM频率一致(即24MHz)
D. CLK_SRC_MASKn
① 决定MUX开关的输出是否打开,默认各模块时钟都打开。
② 为降低能耗,可以将不使用的时钟关闭
E. CLK_DIVn
① CLK_DIVn寄存器决定各模块的分频系数
② CLK_DIVn寄存器的默认值均为0,即系统上电阶段对所有时钟不予分频。因此在系统上电之后时钟初始化之前,SoC各模块均按外部晶振时钟频率工作(推荐24MHz)
F. CLK_GATE_x
① 类似CLK_SRC_MASK寄存器,根据手册可以根据IP控制模块时钟。
② 具体含义个人并不明确
G. CLK_DIV_STASn & CLK_MUX_STATn
这两类状态寄存器,分别用来查看DIV和MUX的状态。是变化已经完成,还是正在进行中
2)时钟系统初始化代码解析
A. 关闭PLL输出
由于S5PV210时钟体系中存在glitch-free & non-glitch-free mux,为避免故障,在完成时钟系统设置之前,先关闭各PLL输出
B. 设置各PLL的lock time
目前代码中没有采用xPLL_CON寄存器的默认值,而是将其设置为最大值,以此确保PLL锁定成功
C. 设置分频系数
代码中将CLK_DIV0寄存器设置为0x14131440,即按如下方式配置时钟关系,
ARMCLK = MOUT_MSYS / 1
SCLKA2M = SCKLAPLL / 5
HCLK_MSYS = ARMCLK / 5
PCKL_MSYS = HCLK_MSYS / 2
HCLK_DSYS = MOUT_DSYS / 4
PCLK_DSYS = HCLK_DSYS / 2
HCLK_PSYS = MOUT_PSYS / 5
PCLK_PSYS = HCLK_PSYS / 2
D. 设置PLL倍频参数
代码中采用三星推荐值,将APLL设置为1GHz,将MPLL设置为667MHz。由此可得各主要时钟如下,
ARMCLK = MOUT_MSYS / 1 = 1GHz
SCLKA2M = SCKLAPLL / 5 = 200MHz
HCLK_MSYS = ARMCLK / 5 = 200MHz
PCKL_MSYS = HCLK_MSYS / 2 = 100MHz
HCLK_DSYS = MOUT_DSYS / 4 = 166MHz
PCLK_DSYS = HCLK_DSYS / 2 = 83MHz
HCLK_PSYS = MOUT_PSYS / 5 = 133MHz
PCLK_PSYS = HCLK_PSYS / 2 = 66MHz
可见代码中就是按照三星推荐的high-performance方案设置各主要时钟参数
E. 使能各PLL
时钟系统参数设置完成后,打开各PLL,在lock time之后SoC各模块将按照我们设置的值工作
3)模块时钟设置示例
在上述时钟系统初始化完成的基础上,以UART0的时钟设置为例,说明SoC模块的时钟设置方法
A. 在UART端确定采用的时钟源
① 根据UCONn寄存器,UART模块可以使用PCLK或SCLK_UART作为时钟源。
② 如果采用PCLK(此处指PCLK_PSYS),则有之前的时钟初始化即可
③ 如果采用SCLK_UART,还需要配置该时钟
B. 配置SCLK_UART时钟
根据时钟关系图,需要配置MUXuart0 & DIVuart0
说明:总体而言,配置一个时钟的基本步骤就是选择时钟源 + 选择分频系数
4)BL0对时钟系统的设置
iROM中的BL0按以下参数对时钟系统进行设置,
可见BL0中设置的时钟系统频率比我们代码中的频率低,因此在时钟系统初始化之后,LED的闪烁频率应该加快。
实际测试现象与分析一致。