嵌入式Linux裸机开发笔记8(IMX6ULL)主频和时钟配置实验(2)
设置类似,频率计算公式都是 528*18/PFDX_FRAC(X=1~3) ,因此。I.MX6U 的时钟系统还是很复杂的。发生握手信号以后需要等待握手完成,寄存器 CCM_CDHIPR。和一些总线时钟的设置,关于具体的外设时钟设置我们在学习到的时候在详细的讲解。但是笔者没有找到相应的寄存器,因此目前没法关闭,那也就没法。最后要设置的就是 PERCLK_CLK_ROOT。的握手,所以修改完成以后要等
·
8.1.5 PFD 时钟设置
设置好主频以后我们还需要设置好其他的 PLL 和 PFD 时钟,PLL1 上一小节已经设置了,
PLL2、PLL3 和 PLL7 固定为 528MHz、480MHz 和 480MHz,PLL4~PLL6 都是针对特殊外设
的,用到的时候再设置。因此,接下来重点就是设置 PLL2 和 PLL3 的各自 4 路 PFD,NXP 推
荐的这 8 路 PFD 频率如表 8.1.5.1 所示:
表 8.1.5.1 NXP 推荐的 PFD 频率
先设置 PLL2 的 4 路 PFD 频率,用到寄存器是 CCM_ANALOG_PFD_528n,寄存器结构如
图 8.1.5.1 所示:
图 8.1.5.1 寄存器 CCM_ANALOG_PFD_528n 结构
从图 8.1.5.1 可以看出,寄存器 CCM_ANALOG_PFD_528n 其实分为四组,分别对应
PFD0~PFD3,每组 8 个 bit,我们就以 PFD0 为例,看一下如何设置 PLL2_PFD0 的频率。PFD0
对应的寄存器位如下:
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 的
时候使能输出。
如果我们要设置 PLL2_PFD0 的频率为 352MHz 的话就需要设置 PFD0_FRAC 为 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, 这样 PLL2_PFD2 实际为 396MHz;PLL2_PFD3=297MHz 的话,PFD3_FRAC=32。
接 下 来 设 置 PLL3_PFD0~PLL3_PFD3 这 4 路 PFD 的 频 率 , 使 用 到 的 寄 存 器 是
CCM_ANALOG_PFD_480n,此寄存器结构如图 8.1.5.2 所示:

从图 16.1.5.2 可以看出,寄存器 CCM_ANALOG_PFD_480n 和 CCM_ANALOG_PFD_528n
的结构是一模一样的,只是一个是 PLL2 的,一个是 PLL3 的。寄存器位的含义也是一样的,只
是 频 率 计 算 公 式 不 同 , 比 如 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。
8.1.6 AHB、IPG 和 PERCLK 根时钟设置
7 路 PLL 和 8 路 PFD 设置完成以后最后还需要设置 AHB_CLK_ROOT 和 IPG_CLK_ROOT
的时钟,I.MX6U 外设根时钟可设置范围如图 8.1.6.1 所示:

图 8.1.6.1 外设根时钟可设置范围
图 8.1.6.1 给出了大多数外设的根时钟设置范围,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 的设计如图 8.1.6.2 所示:

图 8.1.6.2 总线时钟图
图 8.1.6.2 就是 AHB_CLK_ROOT 和 IPG_CLK_ROOT 的时钟图,图中分为了部分。
①、此选择器用来选择 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。
②、此选择器用来选择 periph_clk 的时钟源,由寄存器 CCM_CBCDR 的PERIPH_CLK_SEL
位与 PLL_bypass_en2 组成的或来选择。当 CCM_CBCDR 的 PERIPH_CLK_SEL 位为 0 的时候
periph_clk=pr_periph_clk=396MHz。
③、通过 CBCDR 的 AHB_PODF 位来设置 AHB_CLK_ROOT 的分频值,可以设置 1~8 分
频,如果想要 AHB_CLK_ROOT=132MHz 的话就应该设置为 3 分频:396/3=132MHz。图 8.1.6.2 中虽然写的是默认 4 分频,但是 I.MX6U 的内部 boot rom 将其改为了 3 分频!
④、通过 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 时钟频率,其时钟结构图如图 8.1.6.3 所示:

图 8.1.6.3 PERCLK_CLK_ROOT 时钟结构
从图8.1.6.3可以看出 , 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 分频。
在上面的设置中用到了三个寄存器:CCM_CBCDR、CCM_CBCMR 和 CCM_CSCMR1,我
们依次来看一下这些寄存器,CCM_CBCDR 寄存器结构如图 8.1.6.4 所示:

图 8.1.6.4 寄存器 CCM_CBCDR 结构
寄存器 CCM_CBCDR 各个位的含义如下:
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 分频。
接下来看一下寄存器 CCM_CBCMR,寄存器结构如图 8.1.6.5 所示:

寄存器 CCM_CBCMR 各个位的含义如下:
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 时钟源选择为 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,寄存器结构如图 8.1.6.6 所示:

图 8.1.6.6 寄存器 CCM_CSCMR1 结构
此寄存器主要用于外设时钟源的选择,比如 QSPI1、ACLK、GPMI、BCH 等外设,我们重
点看一下下面两个位:
PERCLK_CK_SEL:perclk 时钟源选择,为 0 的话选择 ipg clk,为 1 的话选择 osc clk。
PERCLK_PODF:perclk 的时钟分频,可设置 0~7,分别对应 1~8 分频。
在修改如下时钟选择器或者分频器的时候会引起与 MMDC 的握手发生:
①、mmdc_podf
②、periph_clk_sel
③、periph2_clk_sel
④、arm_podf
⑤、ahb_podf
发生握手信号以后需要等待握手完成,寄存器 CCM_CDHIPR 中保存着握手信号是否完成,
如果相应的位为 1 的话就表示握手没有完成,如果为 0 的话就表示握手完成,很简单,这里就
不详细的列举寄存器 CCM_CDHIPR 中的各个位了。
另外在修改 arm_podf 和 ahb_podf 的时候需要先关闭其时钟输出,等修改完成以后再打开,
否则的话可能会出现在修改完成以后没有时钟输出的问题。本教程需要修改寄存器
CCM_CBCDR 的 AHB_PODF 位来设置 AHB_ROOT_CLK 的时钟,所以在修改之前必须先关闭
AHB_ROOT_CLK 的输出。但是笔者没有找到相应的寄存器,因此目前没法关闭,那也就没法
设置 AHB_PODF 了。不过 AHB_PODF 内部 boot rom 设置为了 3 分频,如果 pre_periph_clk 的
时钟源选择 PLL2_PFD2 的话,AHB_ROOT_CLK 也是 396MHz/3=132MHz。
至此,I.MX6U 的时钟系统就讲解完了,I.MX6U 的时钟系统还是很复杂的。本章我们也只是讲解了如何进行主频、 PLL、PFD 和一些总线时钟的设置,关于具体的外设时钟设置我们在学习到的时候在详细的讲解。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐
所有评论(0)