主要参照《iMX6ULL参考手册》中第10章:Clock and Power Management(时钟和电源管理)。第18章:Clock Controller Module (CCM)(时钟控制器模块)。
时钟生成和管理子系统的集中组件由以下模块实现:
1、CCM(时钟控制模块):CCM模块提供对主(源级)和次(根级)时钟产生、划分、分布、同步和粗级门禁的控制。有关CCM架构、功能描述和编程模型的信息,请参阅时钟控制器模块(CCM)。
2、LPCG(低功率时钟门控):该模块将时钟分配到SoC中的所有块,并处理块级软件可控和自动时钟门控。有关LPCG架构和功能描述,请参见时钟控制器模块(CCM)。
PMU(电源管理单元)、GPC(通用电源控制器)负责管理电源,不属于时钟控制部分,不进行讨论。
iMX6ULL 系统时钟总结:
1、外部晶振通过时钟脉冲振荡器生成时钟,并输入到时钟控制模块(CCM)。
2、时钟控制模块中时钟根生成器生成根时钟,并输出时钟到低功耗时钟门控模块(LPCG)。
3、低功耗时钟门控模块生成模块时钟,输入到各个模块中。
时钟产生和管理系统是围绕CCM和LPCG模块构建的。
SoC环境下时钟管理系统的高层框图如下图所示。
时钟生成的高级框图如下图所示。
晶体振荡器模块由高频振荡器(典型频率为24 MHz)和低频实时时钟振荡器(典型频率为32.768 KHz)组成。每一个振荡器都实现为一个偏置放大器,当与合适的外部石英晶体和外部负载电容器结合时,就实现了一个振荡器。
时钟生成部分包括 7 个PLL。为了产生额外的频率,其中 2 个 PLL 配备 4 个PDF。
此路 PLL 是供ARM内核使用的,通过编程器输出频率可达 1.3 GHz。
此路 PLL 是固定的 22 倍频,不可编程修改。因此,此路 PLL时钟=24MHz * 22 = 528MHz。此 PLL 分出了 4 路 PFD,分别为:PLL2_PFD0~PLL2_PFD3,这 4 路 PFD 和 528_PLL共同作为其它很多外设的根时钟源。通常 528_PLL 和这 4 路 PFD 是 I.MX6U 内部系统总线的时钟源,比如内处理逻辑单元、DDR接口、NAND/NOR接口等等。
此路 PLL 是固定的20倍频,因此USB1_PLL=24MHz *20=480MHz。此 PLL 也有四路 PFD,为:PLL3_PFD0~PLL3_PFD3。PLL3 要用于USB1PHY,但是其和四路PFD同样也可以作为其他外设的根时钟源。
此路 PLL 用于音频相关的外设,此路 PLL的倍频可以调整,PLL 的输出范围同样也是 650MHz~1300MHz,此路 PLL 在最终输出的时候也可以进行分频,可选 1/2/4 分频。
此路 PLL 用于显示相关的外设,比如LCD,此路 PLL 的倍频可以调整,PLL 的输出范围在 650MHz~1300MHz。此路 PLL 在最终输出的时候还可以进行分频, 可选 1/2/4/8/16 分频。
此路 PLL 固定为 20+5/6 倍频,因此 ENET_PLL=24MHz * (20+5/6) = 500MHz。此路 PLL 用于生成网络所需的时钟,可以在此 PLL 的基础上生成 25/50/100/125MHz的网络时钟。
此路PLL是给USB2PHY使用的。同样的,此路PLL固定为20倍频,因此也是480MHz。
这个子块提供了控制大部分次级时钟源编程的寄存器,包括主时钟源选择和时钟分频器。时钟根是核心、系统总线(axis、AHB、IPG)和所有其他SoC外围设备的每个独立时钟,其中包括串行时钟、波特时钟和特殊功能时钟。大多数时钟根是特定于每个模块的。
LPCG块从CCM接收根时钟,并将它们分割为每个块的时钟分支。时钟分支是单独的门控时钟。
下图显示了CCM的时钟树配置和时钟根。
时钟树分 3 部分,分别是 CLOCK SWITCHER、CLOCK ROOT GENERATOR 和 SYSTEM CLOCKS。
时钟切换器(CCM_CLK_SWITCHER)子模块接收 PLL 输出时钟和 PLL 旁路时钟。
时钟根生成器(CCM CLK Root GEN)子模块生成根时钟,并下发到LPCG。
这个 PLL 从 24 MHz 参考时钟合成一个低抖动时钟。这个锁相环的时钟输出频率范围从650 MHz到1.3 GHz。输出频率由7位寄存器域CCM_ANALOG_PLL_ARM[DIV_SELECT]选择。
DIV_SELECT 在 CCM_ANALOG_PLL_ARMn寄存器中。
DIV_SELECT 描述:PLL 分频器。有效值范围:54-108。计算公式:Fout = Fin * div_select/2.0.
举例说明:PLL1 配置成 996MHz,因为晶振为 24 MHz,所以 Fin = 24MHz。996 = 24 * div_select/2,计算后 div_select = 83。
PLL2 不可配置,只能工作在 528MHz。但 4 路 PDF 可配置。
PLL3 不可配置,只能工作在 480MHz。但 4 路 PDF 可配置。
DIV_SELECT 在 CCM_ANALOG_PLL_AUDIOn 寄存器中,DIV_SELECT 可配置值范围:27~54。
NUM 为 CCM_ANALOG_PLL_AUDIO_NUM 寄存器低 30 bit。
DENOM 为 CCM_ANALOG_PLL_AUDIO_DENOM 寄存器低 30 bit。
DIV_SELECT 在 CCM_ANALOG_PLL_AUDIOn 寄存器中,DIV_SELECT 可配置值范围:27~54。
NUM 为 CCM_ANALOG_PLL_VIDEO_NUM 寄存器低 30 bit。
DENOM 为 CCM_ANALOG_PLL_VIDEO_DENOM 寄存器低 30 bit。
通过设置 CCM_ANALOG_PLL_ENET[DIV_SELECT] 可编程到 25、50、100 和 125MHz。
通过设置 CCM_ANALOG_PLL_ENET[DIV_SELECT] 可编程到 25、50、100 和 125MHz。
固定为 25MHz。
PLL7 不可配置,只能工作在 480MHz。
设置 PLL2 的 4 路 PFD频率,用到寄存器是CCM_ANALOG_PFD_528n。
设置 PLL3 的 4 路 PFD频率,用到寄存器是CCM_ANALOG_PFD_480n。
PFD0_FRAC:PLL2_PFD0 的分频数,PLL2_PFD0 的计算公式为 528 * 18/PFD0_FRAC,此为可设置的范围为 12~35 。 如 果 PLL2_PFD0 的频率要设置为 352MHz 的话 PFD0_FRAC=528*18/352=27。
PFD0_STABLE:此位为只读位,可以通过读取此位判断 PLL2_PFD0 是否稳定。
PFD0_CLKGATE:PLL2_PFD0 输出使能位,为 1 的时候关闭 PLL2_PFD0 的输出,为 0 的时候使能输出。
PFD1_FRAC:PLL2_PFD1 的分频数,PLL2_PFD1 的计算公式为 528 * 18/PFD1_FRAC,此为可设置的范围为 12~35 。 如 果 PLL2_PFD1 的频率要设置为 594MHz 的话 PFD1_FRAC=528*18/594=16。
PFD1_STABLE:此位为只读位,可以通过读取此位判断 PLL2_PFD1 是否稳定。
PFD1_CLKGATE:PLL2_PFD1 输出使能位,为 1 的时候关闭 PLL2_PFD1 的输出,为 0 的时候使能输出。
PFD2_FRAC:PLL2_PFD2 的分频数,PLL2_PFD2 的计算公式为 528 * 18/PFD2_FRAC,此为可设置的范围为 12~35 。 如 果 PLL2_PFD2 的频率要设置为 400MHz 的话 PFD2_FRAC=528*18/400=24。
PFD2_STABLE:此位为只读位,可以通过读取此位判断 PLL2_PFD2 是否稳定。
PFD2_CLKGATE:PLL2_PFD2 输出使能位,为 1 的时候关闭 PLL2_PFD2 的输出,为 0 的时候使能输出。
PFD3_FRAC:PLL2_PFD3 的分频数,PLL2_PFD3 的计算公式为 528 * 18/PFD3_FRAC,此为可设置的范围为 12~35 。 如 果 PLL2_PFD3 的频率要设置为 297MHz 的话 PFD3_FRAC=528*18/297=32。
PFD3_STABLE:此位为只读位,可以通过读取此位判断 PLL2_PFD3 是否稳定。
PFD3_CLKGATE:PLL2_PFD3 输出使能位,为 1 的时候关闭 PLL2_PFD3 的输出,为 0 的时候使能输出。
PFD0_FRAC:PLL3_PFD0 的分频数,PLL3_PFD0 的计算公式为 480 * 18/PFD0_FRAC,此为可设置的范围为 12~35 。 如 果 PLL3_PFD0 的频率要设置为 720MHz 的话 PFD0_FRAC=480 * 18/720=12。
PFD0_STABLE:此位为只读位,可以通过读取此位判断 PLL3_PFD0 是否稳定。
PFD0_CLKGATE:PLL3_PFD0 输出使能位,为 1 的时候关闭 PLL3_PFD0 的输出,为 0 的时候使能输出。
PFD1_FRAC:PLL3_PFD1 的分频数,PLL3_PFD1 的计算公式为 480 * 18/PFD1_FRAC,此为可设置的范围为 12~35 。 如 果 PLL3_PFD1 的频率要设置为 540MHz 的话 PFD1_FRAC=480 * 18/540=16。
PFD1_STABLE:此位为只读位,可以通过读取此位判断 PLL3_PFD1 是否稳定。
PFD1_CLKGATE:PLL3_PFD1 输出使能位,为 1 的时候关闭 PLL3_PFD1 的输出,为 0 的时候使能输出。
PFD2_FRAC:PLL3_PFD2 的分频数,PLL3_PFD2 的计算公式为 480 * 18/PFD2_FRAC,此为可设置的范围为 12~35 。 如 果 PLL3_PFD2 的频率要设置为 508.2MHz 的话 PFD2_FRAC=480 * 18/508.2=17。
PFD2_STABLE:此位为只读位,可以通过读取此位判断 PLL3_PFD2 是否稳定。
PFD2_CLKGATE:PLL3_PFD2 输出使能位,为 1 的时候关闭 PLL3_PFD2 的输出,为 0 的时候使能输出。
PFD3_FRAC:PLL3_PFD3 的分频数,PLL3_PFD3 的计算公式为 480 * 18/PFD3_FRAC,此为可设置的范围为 12~35 。 如 果 PLL3_PFD3 的频率要设置为 454.7MHz 的话 PFD3_FRAC=480 * 18/454.7=19。
PFD3_STABLE:此位为只读位,可以通过读取此位判断 PLL3_PFD3 是否稳定。
PFD3_CLKGATE:PLL3_PFD3 输出使能位,为 1 的时候关闭 PLL3_PFD3 的输出,为 0 的时候使能输出。
1、内核时钟源来自于 PLL1,假如此时 PLL1 为 996MHz。
2、通过寄存器 CCM_CACRR 的 ARM_PODF 位对 PLL1 进行分频,可选择 1/2/4/8 分频,假如我们选择 2 分频,那么经过分频以后的时钟频率是 996/2=498MHz。
3、经过第 2 步 2 分频以后的 498MHz 就是ARM的内核时钟,也就是 I.MX6U 的主频。
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(PLL1)的频率进行调整的话,比如我们要设置 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 的晶振。
1、设置寄存器 CCSR的 STEP_SEL 位,设置 step_clk 的时钟源为 24M 的晶振。
2、设置寄存器 CCSR 的 PLL1_SW_CLK_SEL 位,设置 pll1_sw_clk 的时钟源为step_clk=24MHz,通过这一步我们就将 I.MX6U 的主频先设置为 24MHz,直接来自于外部的 24M晶振。
3、设置寄存器 CCM_ANALOG_PLL_ARMn,将 pll1_main_clk(PLL1)设置为 1056MHz。
4、设置寄存器 CCSR 的 PLL1_SW_CLK_SEL 位,重新将 pll1_sw_clk 的时钟源切换回 pll1_main_clk,切换回来以后的 pll1_sw_clk 就等于 1056MHz。
5、最后设置寄存器 CCM_CACRR 的 ARM_PODF 为 2 分频,I.MX6U 的内核主频就为 1056/2=528MHz。
上图给出了大多数外设的根时钟设置范围,AHB_CLK_ROOT 最高可以设置 132MHz,IPG_CLK_ROOT 和 PERCLK_CLK_ROOT 最高可以设置66MHz。
那我们就将 AHB_CLK_ROOT、 IPG_CLK_ROOT 和 PERCLK_CLK_ROOT 分别设置为 132MHz 、 66MHz 、 66MHz 。
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的 PERIPH_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 分频,如果想要 AHB_CLK_ROOT=132MHz 的话就应该设置为 3 分频:396/3=132MHz。图中虽然写的是默认 4 分频,但是 I.MX6U的内部 boot rom将其改为了 3 分频!
4、通过CBCDR的 IPG_PODF 位来设置 IPG_CLK_ROOT 的分频值,可以设置 1~4 分频,IPG_CLK_ROOT 时钟源是 AHB_CLK_ROOT,要想 IPG_CLK_ROOT=66MHz 的话就应该设置 2 分频:132/2=66MHz。
从图中可 以 看 出 , 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位来设置分频,如果要设置PERCLK_CLK_ROOT为 66MHz 的话就要设置为 1 分频。
PERIPH_CLK2_PODF:periph2 时钟分频,可设置 0~7,分别对应 1~8 分频。
PERIPH2_CLK_SEL:选择 peripheral2 的主时钟,如果为 0 的话选择 PLL2,如果为 1 的话选择 periph2_clk2_clk。修改此位会引起一次与 MMDC 的握手,所以修改完成以后要等待握 手完成,握手完成信号由寄存器 CCM_CDHIPR 中指定位表示。
PERIPH_CLK_SEL:peripheral 主时钟选择,如果为 0 的话选择 PLL2,如果为 1 的话选择 periph_clk2_clock。修改此位会引起一次与MMDC的握手,所以修改完成以后要等待握手完 成,握手完成信号由寄存器 CCM_CDHIPR中指定位表示。
AXI_PODF:axi 时钟分频,可设置 0~7,分别对应 1~8 分频。
AHB_PODF:ahb 时钟分频,可设置 0~7,分别对应 1~8 分频。修改此位会引起一次与MMDC 的握手,所以修改完成以后要等待握手完成,握手完成信号由寄存器CCM_CDHIPR中 指定位表示。
IPG_PODF:ipg 时钟分频,可设置 0~3,分别对应 1~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 时钟分频设置,可设置 0~7,分别对应 1~8 分频。
PERIPH2_CLK2_PODF:periph2_clk2 的时钟分频,可设置 0~7,分别对应 1~8 分频。
LCDIF1_PODF:lcdif1 的时钟分频,可设置 0~7,分别对应 1~8 分频。
PRE_PERIPH2_CLK_SEL:pre_periph2 时钟源选择,00 选择 PLL2,01 选择 PLL2_PFD2,10 选择 PLL2_PFD0,11 选择 PLL4。
PERIPH2_CLK2_SEL:periph2_clk2 时钟源选择, 00 的时候选择 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。