i.MX6ULL终结者时钟系统和原理分析

1 i.MX6ULL时钟系统

iMX6ULL的系统主频为528MHz,有些型号可以跑到696MHz,但是默认情况下iMX6ULL 的主频为396MHz。我们想要让iMX6ULL运行时候达到最大性能,就需要将主频上调至最大528MHz,或者更大,其它的外设时钟也要设置到NXP官方推荐的值。
更多关于芯片的时钟可以查阅 《IMX6ULL参考手册.pdf》的第10章“Chapter 10 Clock and Power Management”和第18章“Chapter 18 Clock Controller Module (CCM)”,这两章有详细的讲解。

系统时钟
我们打开核心板原理图,搜索“RTC_XTALI”即可看到如图 1.1内容:
i.MX6ULL终结者时钟系统和原理分析

图 1.1

这里我们可以看到有两个晶振。32.768KHz的晶振是RTC(实时时钟)的时钟源。24MHz晶振是CPU内核及其他外设的时钟源。

PPL(Phase Locked Loop)时钟源
iMX6ULL系列外设所需要的时钟源,都是由24MHz晶振倍频产生的,一共有7组,如图 1.2所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.2

PPL1(ARM_PLL):这个PPL供内核使用,可编程倍频器,最高可达1.3GHz。注意,此频率高于芯片支持的最大频率1.0 GHz。
PPL2(System_PLL或528_PLL):固定22倍频,产生528MHz。这个PPL还分出4路PFD,即PLL2_PFD0~PLL2_PFD3,
528_PLL和PLL2_PFD0~PLL2_PFD3
为各种总线提供时钟。他们不提供精确的或恒定的频率,可以实现动态调频。通常的,528_PLL和PLL2_PFD0~PLL2_PFD3作为系统内部总线,内部逻辑处理单元,DDR接口,NAND/NOR接口模块等的时钟源。
PPL3(USB1_PLL):用于USBPHY(OTG PHY),固定20倍频,同样分出4路PFD,即PLL3_PFD0~PLL3_PFD3,产生了480MHz的VCO频率和24MHz振荡器。主PPL和4路PFD也可作为其他接口时钟输入。
PPL4(Audio PLL):用于音频外设,提供低抖动和高精度音频时钟,频率范围为650MHz~1300MHz,频率分辨率优于1Hz。可以选择1/2/48/16分频。
PPL5(Video PLL):用于标准视频显示外设,提供低抖动和高精度音频时钟,频率范围为650MHz~1300MHz,频率分辨率优于1Hz。该时钟主要用作显示和视频接口的时钟。可以选择1/2/48/16分频。
PPL6(ENET_PLL):固定为20+5/6倍频,产生500MHz,在此基础上产生25/50/100/125MHz网络时钟。
PPL7(USB2_PLL):用于USB2PHY(OTG PHY),固定20倍频,产生了480MHz的VCO频率和24MHz振荡器。

时钟树
如此多的时钟分支都要一一对应不同的外设。我们要参考《IMX6ULL 参考手册.pdf》里的18.3小结“CCM Clock Tree”,来学习如何选择PPL时钟。
i.MX6ULL终结者时钟系统和原理分析

图 1.3

i.MX6ULL终结者时钟系统和原理分析

图 1.4

时钟树整体分为三个部分:CLOCK SWITCHER、CLOCK ROOT GENERATOR和SYSTEM CLOCKS。其中左边的CLOCK_SWITCHER就是我们上一小节讲解的那7路PLL和8路PFD,右边的SYSTEM CLOCKS就是芯片外设,中间的CLOCK ROOT GENERATOR部分的作用就是选择合适的时钟接入外设接口,负责给CLOCK SWITCHER和SYSTEM CLOCKS连线。就是在7路PLL和8路PFD选择合适时钟源,提供给外设使用。

我们以ESAI外设为例,ESAI时钟图 1.5所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.5

这里的CLOCK ROOT GENERATOR又被分成三部分:
ESAI_CLK_SEL:时钟源选择器,手册中搜索“ESAI_CLK_SELESAI ”可知,有4个可选的时钟源:PLL4、PLL5、PLL3_PFD2和pll3_sw_clk。具体选择哪一路作为ESAI的时钟源是由寄存器CCM->CSCMR2 的ESAI_CLK_SEL 位来决定的,用户可以自由配置。如图 1.6所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.6

1.ESAI_CLK_PRED:一次分频,手册中搜索“ESAI_CLK_PRED”可知,有1~8分频8种选择,分频值由寄存器CCM_CS1CDR的ESAI_CLK_PRED来确定的,假如现在PLL4=650MHz,我们选择PLL4作为ESAI时钟,一次分频选择2分频,那么此时的时钟就是650/2=325MHz。如图 1.7所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.7

2.ESAI_CLK_PODF:二次分频,手册中搜索“ESAI_CLK_PODF”可知,在一次分频的基础上在此分频,有1~8分频8种选择,经过此分频器以后的时钟就是325/8=40.625MHz。因此最终进入到 ESAI 外设的时钟就是40.625MHz。

以上是以外设ESAI为例的设置方式,其他外设可以根据具体需求查看手册去配置。

内核时钟
上一节的时钟树上我们可以查找到ARM 内核时钟如图 1.8所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.8

1.时钟源PPL1,默认为996MHz。
2.寄存器CCM_CACRR的低三位即ARM_PODF位对PLL1进行分频,有07分别对应18分频8种选择。这里选择2分频,经过分频之后就是996/2=498MHz,如图 1.9所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.9

这样,出来的就是ARM的内核时钟,也就是芯片主频(498MHz)。
如果我们要设置528MHz,我们需要设置PPL1为1056MHz,寄存器CCM_CACRR的ARM_PODF位配置为2分频即可。如果我们要设置为696MHz主频。我们需要将PPL1设置为696MHz,那么寄存器CCM_CACRR的ARM_PODF位配置为2分频即可。
我们在来看下如何设置PPL1。PPL1是由寄存器CCM_ANALOG_PLL_ARMn决定的,结构如图 1.10:
i.MX6ULL终结者时钟系统和原理分析

图 1.10

寄存器CCM_ANALOG_PLL_ARMn 中有两个主要位:
ENABLE: 时钟输出使能。1:使能PLL1输出,0:关闭PLL1输出。
DIV_SELECT: 设置PLL1的输出频率,可设置范围为:54~108,PLL1 CLK = Fin *div_seclec/2.0,Fin=24MHz。如果PLL1要输出1056MHz的话,div_select就要设置为88。在修改PLL1时钟频率的时候我们需要先将内核时钟源改为其他的时钟源,PLL1可选择的时钟源如图 1.11所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.11

1.pll1_sw_clk也就是PLL1的最终输出频率。
2.选择器,选择pll1_sw_clk的时钟源,寄存器CCM_CCSR的PLL1_SW_CLK_SEL位决定pll1_sw_clk是选择pll1_main_clk还是step_clk。正常情况下应该选择pll1_main_clk,但是如果要对pll1_main_clk(PPL1)的频率进行调整的话,比如我们要设置PLL1=1056MHz,此时就要先将pll1_sw_clk切换到step_clk上。等pll1_main_clk调整完成以后再切换回来。
3.选择器,选择step_clk的时钟源,由寄存器CCM_CCSR的STEP_SEL位来决定step_clk是选择osc_clk还是secondary_clk。一般选择osc_clk,也就是24MHz 的晶振。

这里我们就用到了一个寄存器 CCM_CCSR,结构如图 1.12所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.12

这个寄存器我们用到两个位:
STEP_SEL:选择setp_clk时钟源。
PLL1_SW_CLK_SEL:选择pll1_sw_clk时钟源。

到此,我们可以简单整理下修改主频思路:
1.设置CCSR的STEP_SEL位,设置step_clk的时钟源为24M。
2.设置CCSR的PLL1_SW_CLK_SEL位,设置pll1_sw_clk的时钟源step_clk=24MHz,通过这一步我们就将I.MX6ULL的主频先设置为24MHz,直接来自于外部的24M时钟晶振。
3.设置CCM_ANALOG_PLL_ARMn,将pll1_main_clk(PPL1)设置为1056MHz。
4.设置CCSR的PLL1_SW_CLK_SEL位,重新将pll1_sw_clk的时钟源切换回pll1_main_clk,切换回来以后的pll1_sw_clk就等于1056MHz。
5.设置CCM_CACRR的ARM_PODF为2分频,内核主频就是1056/2=528MHz。

PFD时钟
我们还需要设置好其他的PLL和PFD时钟,PLL1上一小节已经设置了,其他的PPL时钟有的是固定的(PPL2-528MHz,PPL3-480MHz,PPL7-480MHz),有的暂时可以不需要设置(PPL4,PPL5,PPL6分别对应音视频和网络)。

接下来就是设置PFD时钟。恩智浦有官方推荐数值如下表:
PFD 推荐值(MHz)
PPL2_PFD0 352
PPL2_PFD1 594
PPL2_PFD2 400(实际为396)
PPL2_PFD3 297
PPL3_PFD0 720
PPL3_PFD1 540
PPL3_PFD2 508.2
PPL3_PFD3 454.7

PLL2的4路PFD频率,用到寄存器是CCM_ANALOG_PFD_528n,寄存器结构如图 1.13所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.13

寄存器CCM_ANALOG_PFD_528n分为四组,分别对应PFD0~PFD3,每组8个bit,我们就以PFD0为例,看一下如何设置PLL2_PFD0的频率。

PFD0对应的寄存器位如下:
PFD0_FRAC:PLL2_PFD0的分频数,PLL2_PFD0的计算公式为52818/PFD0_FRAC,可设置的范围为12~35。
PFD0_STABLE:只读位,通过此位判断PLL2_PFD0是否稳定,新分频生效时此位取反。
PFD0_CLKGATE:PLL2_PFD0输出使能位。1表示关闭PLL2_PFD0输出;0表示使能PLL2_PFD0输出
PLL2_PFD0的频率为352MHz,需要设置PFD0_FRAC=528
18/352=27,PFD0_CLKGATE为0。

PLL2_PFD1~PLL2_PFD3
设置类似,频率计算公式都是528*18/PFDX_FRAC(X=1~3),因此PLL2_PFD1=594MHz的话,PFD1_FRAC=16;PLL2_PFD2=400MHz的话,(PFD2_FRAC不能整除,取最近的整数值)PFD2_FRAC=24,实际为396MHz;PLL2_PFD3=297MHz的话,PFD3_FRAC=32。

接下来配置PLL3_PFD0~PLL3_PFD3这4路PFD的频率,使用到的寄存器是CCM_ANALOG_PFD_480n,此寄存器结构如图 1.14所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.14

寄存器CCM_ANALOG_PFD_480n和CCM_ANALOG_PFD_528n的结构是一模一样的,寄存器位的含义也是一样的,只是频率计算公式不同,频率计算公式为PLL3_PFDX=480*18/PFDX_FRAC(X=0~3)
设置PLL3_PFD0=720MHz,PFD0_FRAC=12;
设置PLL3_PFD1=540MHz,PFD1_FRAC=16;
设置PLL3_PFD2=508.2MHz,PFD2_FRAC=17;
设置PLL3_PFD3=454.7MHz,PFD3_FRAC=19。

AHB、IPG和PERCLK根时钟
iMX6ULL外设根时钟可设置范围如图 1.15所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.15

这里给大多数外设的根时钟设置范围,AHB_CLK_ROOT最高可以设置132MHz,IPG_CLK_ROOT和PERCLK_CLK_ROOT最高可以设置66MHz。我们将AHB_CLK_ROOT、IPG_CLK_ROOT和PERCLK_CLK_ROOT分别设置为132MHz、66MHz、66MHz。AHB_CLK_ROOT和IPG_CLK_ROOT的设置如图 1.16所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.16

上图就是AHB_CLK_ROOT和IPG_CLK_ROOT的时钟图,图中分为了4部分:
1.用来选择pre_periph_clk的时钟源,可以选择PLL2、PLL2_PFD2、PLL2_PFD0和PLL2_PFD2/2。寄存器CCM_CBCMR的PRE_PERIPH_CLK_SEL位决定选择哪一个,默认选择PLL2_PFD2,因此默认pre_periph_clk=PLL2_PFD2=396MHz。
2.用来选择periph_clk的时钟源,由寄存器CCM_CBCDR的ERIPH_CLK_SEL位与PLL_bypass_en2组成的或门来选择。当CCM_CBCDR的PERIPH_CLK_SEL位为0的时候periph_clk=pr_periph_clk=396MHz。
3.通过CBCDR的AHB_PODF位来设置AHB_CLK_ROOT的分频值,1~8分频8种,如果想要AHB_CLK_ROOT=132MHz的话就应该设置为3分频(默认):396/3=132MHz。
4.通过CBCDR的IPG_PODF位来设置IPG_CLK_ROOT的分频值,1~4分频4种,IPG_CLK_ROOT时钟源是AHB_CLK_ROOT,要想IPG_CLK_ROOT=66MHz的话就应该设置2分频(默认):132/2=66MHz。

最后要配置PERCLK_CLK_ROOT时钟频率。如图 1.17所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.17

可以看出,PERCLK_CLK_ROOT时钟来源有两个,OSC(24MHz)和IPG_CLK_ROOT,由寄存器CCM_CSCMR1的PERCLK_CLK_SEL决定,如果该位为0,则PERCLK_CLK_ROOT的时钟源是IPG_CLK_ROOT=66MHz,可以通过设置寄存器CCM_CSCMR1的PERCLK_PODF位来配置分频,我们需要66MHz的PERCLK_CLK_ROOT,所以这里配置为1分频。

在上面的设置中用到了三个寄存器。

寄存器CCM_CBCDR结构图如图 1.18:
i.MX6ULL终结者时钟系统和原理分析

图 1.18

该寄存器各位解释如下:
PERIPH_CLK2_PODF:periph2时钟分频,可设置1~8分频8种。
PERIPH2_CLK_SEL:选择peripheral2的主时钟,修改此位会引起一次与MMDC的握手,修改完成以后要等待握手完成,握手完成信号由寄存器CCM_CDHIPR中指定位表示。为0选择PLL2;为1选择periph2_clk2_clk。
PERIPH_CLK_SEL:peripheral主时钟选择,修改此位会引起一次与MMDC的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器CCM_CDHIPR中指定位表示。为0选择PLL2;为1选择periph_clk2_clock。
AXI_PODF:axi时钟分频,可设置1~8分频8种。
AHB_PODF:ahb时钟分频,可设置1~8分频8种。修改此位会引起一次与MMDC的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器CCM_CDHIPR中指定位表示。
IPG_PODF:ipg时钟分频,可设置1~4分频4种。
AXI_ALT_CLK_SEL:axi_alt时钟选择。为0选择PLL2_PFD2;为1选择PLL3_PFD1。
AXI_CLK_SEL:axi时钟源选择。为0选择periph_clk;为1选择axi_alt时钟。
FABRIC_MMDC_PODF:fabric/mmdc时钟分频设置,可设置1~8分频8种。
PERIPH2_CLK2_PODF:periph2_clk2的时钟分频,可设置1~8分频8种。

寄存器CCM_CBCMR结构图图 1.19:
i.MX6ULL终结者时钟系统和原理分析

图 1.19

寄存器各个位的解释如下:
LCDIF1_PODF:lcdif1的时钟分频,可设置1~8分频8种。
PRE_PERIPH2_CLK_SEL:pre_periph2时钟源选择。为00选择PLL2,为01选择PLL2_PFD2,为10选择PLL2_PFD0,为11选择PLL4。
PERIPH2_CLK2_SEL:periph2_clk2时钟源选择。为0选择pll3_sw_clk,为1选择OSC。
PRE_PERIPH_CLK_SEL:pre_periph时钟源选择。为00选择PLL2,为01选择PLL2_PFD2,为10选择PLL2_PFD0,为11选择PLL2_PFD2/2。
PERIPH_CLK2_SEL:peripheral_clk2时钟源选择。为00选择pll3_sw_clk,为01选择osc_clk,为10选择pll2_bypass_clk。

接下来是寄存器CCM_CSCMR1,结构如图 1.20所示:
i.MX6ULL终结者时钟系统和原理分析

图 1.20

该寄存器我们主要用到PERCLK_CLK_SEL和PERCLK_PODF位,解释如下:
PERCLK_CK_SEL:perclk时钟源选择。为0选择ipg clk,为1选择osc clk。
PERCLK_PODF:perclk的时钟分频,可设置1~8分频8种。
这里要注意,我们在修改配置如下时钟选择器或者分频器的时候会引起与MMDC的握手发生:1.mmdc_podf,2.periph_clk_sel,3.periph2_clk_sel,4.arm_podf,5.ahb_podf。在发生握手信号后需等待握手完成,寄存器CCM_CDHIPR中保存着握手信号是否完成,如果相应的位为1的话就表示握手没有完成,如果为0的话就表示握手完成,很简单,这里就不一一列举寄存器CCM_CDHIPR中的各个位了。
在修改arm_podf和ahb_podf时,要先关闭其时钟输出,等修改完成之后再开启,否则的话可能会出现在修改完成以后没有时钟输出的现象。

至此,iMX6ULL的时钟系统就讲解完了,iMX6ULL的时钟系统相对很复杂,大家要结合《I.MX6ULL参考手册.pdf》中时钟相关的结构图来学习。

2 原理分析

本章讲解的iMX6ULL的时钟属于CPU芯片内部设计。i.MX6ULL终结者时钟系统和原理分析