引言
????????在前幾章實驗中我們都沒有涉及到 I.MX6U 的時鐘和主頻配置操作,全部使用的默認配置,
默認配置下 I.MX6U 工作頻率為 396MHz。但是 I.MX6U 系列標準的工作頻率為 528MHz,有些
型號甚至可以工作到 696MHz。本章學習 I.MX6U 的時鐘系統,學習如何配置 I.MX6U 的
系統時鐘和其他的外設時鐘,使其工作頻率為 528MHz,其他的外設時鐘源都工作在 NXP 推薦
的頻率。
8.1 I.MX6U 時鐘系統詳解
????????I.MX6U 的系統主頻為 528MHz,有些型號可以跑到 696MHz,但是默認情況下內部 boot
rom 會將 I.MX6U 的主頻設置為 396MHz。我們在使用 I.MX6U 的時候肯定是要發揮它的最大性能,那么主頻肯定要設置到 528MHz(其它型號可以設置更高, 比如 696MHz),其它的外設時鐘也要設置到 NXP 推薦的值。
8.1.1 系統時鐘來源
????????打開 I.MX6U-ALPHA 開發板原理圖,開發板時鐘原理圖如圖 8.1.1.1 所示:
圖 8.1.1.1 開發板時鐘原理圖
????????從圖8.1.1.1 可以看出 I.MX6U-ALPHA 開發板的系統時鐘來源于兩部分:32.768KHz 和24MHz 的晶振,其中 32.768KHz 晶振是 I.MX6U 的 RTC 時鐘源,24MHz 晶振是 I.MX6U 內核和其它外設的時鐘源,也是我們重點要分析的。
8.1.2 7路PLL時鐘源
????????I.MX6U 的外設有很多,不同的外設時鐘源不同,NXP 將這些外設的時鐘源進行了分組,
一共有 7 組,這 7 組時鐘源都是從 24MHz 晶振 PLL 而來的,因此也叫做 7 組 PLL,這 7 組 PLL
結構如圖 8.1.1.2 所示:
圖 8.1.2.1 初級 PLLs 時鐘源生成圖
????????圖8.1.2.1 展示了 7 個 PLL 的關系,我們依次來看一下這 7 個 PLL 都是什么做什么的:
????????①、 ARM_PLL(PLL1),此路 PLL 是供 ARM 內核使用的,ARM 內核時鐘就是由此 PLL
生成的,此 PLL 通過編程的方式最高可倍頻到 1.3GHz。
????????②、528_PLL(PLL2),此路 PLL 也叫做 System_PLL,此路 PLL 是固定的 22 倍頻,不可編
程修改。因此,此路 PLL 時鐘=24MHz * 22 = 528MHz,這也是為什么此 PLL 叫做 528_PLL 的
原因。此 PLL 分出了 4 路 PFD,分別為:PLL2_PFD0~PLL2_PFD3,這 4 路 PFD 和 528_PLL
共同作為其它很多外設的根時鐘源。通常 528_PLL 和這 4 路 PFD 是 I.MX6U 內部系統總線的
時鐘源,比如內處理邏輯單元、DDR 接口、NAND/NOR 接口等等。
????????③、USB1_PLL(PLL3),此路 PLL 主要用于 USBPHY,此 PLL 也有四路 PFD,為:
PLL3_PFD0~PLL3_PFD3,USB1_PLL 是固定的 20 倍頻,因此 USB1_PLL=24MHz *20=480MHz。
USB1_PLL雖然主要用于USB1PHY,但是其和四路PFD同樣也可以作為其他外設的根時鐘源。
????????④、USB2_PLL(PLL7,沒有寫錯!就是 PLL7,雖然序號標為 4,但是實際是 PLL7),看名
字就知道此路PLL是給USB2PHY 使用的。同樣的,此路PLL固定為20倍頻,因此也是480MHz。
????????⑤、ENET_PLL(PLL6),此路 PLL 固定為 20+5/6 倍頻,因此 ENET_PLL=24MHz * (20+5/6)
= 500MHz。此路 PLL 用于生成網絡所需的時鐘,可以在此 PLL 的基礎上生成 25/50/100/125MHz
的網絡時鐘。
????????⑥、VIDEO_PLL(PLL5),此路 PLL 用于顯示相關的外設,比如 LCD,此路 PLL 的倍頻可以
調整,PLL 的輸出范圍在 650MHz~1300MHz。此路 PLL 在最終輸出的時候還可以進行分頻,
可選 1/2/4/8/16 分頻。
????????⑦、AUDIO_PLL(PLL4),此路 PLL 用于音頻相關的外設,此路 PLL 的倍頻可以調整,PLL
的輸出范圍同樣也是 650MHz~1300MHz,此路 PLL 在最終輸出的時候也可以進行分頻,可選
1/2/4 分頻。
8.1.3 時鐘樹簡介
????????在上一小節講解了 7 路 PLL,I.MX6U 的所有外設時鐘源都是從這 7 路 PLL 和有些 PLL 的
PFD 而來的,這些外設究竟是如何選擇 PLL 或者 PFD 的?這個就要借助《IMX6ULL 參考手
冊》里面的時鐘樹了,如圖 8.1.3.1 所示:

圖 8.1.3.1 I.MX6U 時鐘樹
????????在圖 8.1.3.1 中一共有三部分:CLOCK_SWITCHER、CLOCK ROOT GENERATOR 和
SYSTEM CLOCKS。其中左邊的 CLOCK_SWITCHER 就是我們上一小節講解的那 7 路 PLL 和
8 路 PFD,右邊的 SYSTEM CLOCKS 就是芯片外設,中間的 CLOCK ROOT GENERATOR 是最
復雜的!這一部分就像“月老”一樣,給左邊的CLOCK_SWITCHER和右邊的SYSTEM CLOCKS
進行牽線搭橋。外設時鐘源是有多路可以選擇的,CLOCK ROOT GENERATOR 就負責從 7 路
PLL 和 8 路 PFD 中選擇合適的時鐘源給外設使用。具體操作肯定是設置相應的寄存器,我們以
ESAI 這個外設為例,ESAI 的時鐘圖如圖 8.1.3.2 所示:

圖 8.1.3.2 ESAI 時鐘????????
????????在圖 8.1.3.2 中我們分為了 3 部分,這三部分如下:
????????①、此部分是時鐘源選擇器,ESAI 有 4 個可選的時鐘源:PLL4、PLL5、PLL3_PFD2 和
pll3_sw_clk 。具體選擇哪一路作為ESAI的時鐘源是由寄存器CCM->CSCMR2的ESAI_CLK_SEL 位來決定的,用戶可以自由配置,配置如圖 8.1.3.3 所示:

圖 8.1.3.3 寄存器 CSCMR2 的 ESAI_CLK_SEL 位
????????②、此部分是 ESAI 時鐘的前級分頻,分頻值由寄存器 CCM_CS1CDR 的 ESAI_CLK_PRED
來確定的,可設置 1~8 分頻,假如現在 PLL4=650MHz,我們選擇 PLL4 作為 ESAI 時鐘,前級
分頻選擇 2 分頻,那么此時的時鐘就是 650/2=325MHz。
????????③、此部分又是一個分頻器,對②中輸出的時鐘進一步分頻,分頻值由寄存器CCM_CS1CDR 的 ESAI_CLK_PODF 來決定,可設置 1~8 分頻。假如我們設置為 8 分頻的話,
經過此分頻器以后的時鐘就是 325/8=40.625MHz。因此最終進入到 ESAI 外設的時鐘就是
40.625MHz。
????????上面我們以外設 ESAI 為例講解了如何根據圖 8.1.3.1 來設置外設的時鐘頻率,其他的外
設基本類似的。
8.1.4 內核時鐘設置
????????I.MX6U 的時鐘系統前面幾節已經分析的差不多了,現在就可以開始設置相應的時鐘頻率
了。先從主頻開始,我們將 I.MX6U 的主頻設置為 528MHz,根據圖 8.1.3.2 的時鐘樹可以看到
ARM 內核時鐘如圖 8.1.4.1 所示:

圖 8.1.4.1 ARM 內核時鐘樹????????
????????在圖 8.1.4.1 中各部分如下:
????????①、內核時鐘源來自于 PLL1,假如此時 PLL1 為 996MHz。
????????②、通過寄存器 CCM_CACRR 的 ARM_PODF 位對 PLL1 進行分頻,可選擇 1/2/4/8 分頻,
假如我們選擇 2 分頻,那么經過分頻以后的時鐘頻率是 996/2=498MHz。
????????③、大家不要被此處的 2 分頻給騙了,此處沒有進行 2 分頻(我就被這個2分頻騙了好久,
主頻一直配置不正確!)。
????????④、經過第②步 2 分頻以后的 498MHz 就是 ARM 的內核時鐘,也就是 I.MX6U 的主頻。
經過上面幾步的分析可知,假如我們要設置內核主頻為 528MHz,那么 PLL1 可以設置為
1056MHz,寄存器 CCM_CACRR 的 ARM_PODF 位設置為 2 分頻即可。同理,如果要將主頻設
置為 696MHz,那么 PLL1 就可以設置為 696MHz,CCM_CACRR 的 ARM_PODF 設置為 1 分
頻即可。現在問題很清晰了,寄存器 CCM_CACRR 的 ARM_PODF 位很好設置,PLL1 的頻率
可以通過寄存器 CCM_ANALOG_PLL_ARMn 來設置。接下來詳細的看一下 CCM_CACRR 和
CCM_ANALOG_PLL_ARMn 這兩個寄存器,CCM_CACRR 寄存器結構如圖 8.1.4.2 所示:
圖 8.1.4.2 寄存器 CCM_CACRR
????????寄存器 CCM_CACRR 只有 ARM_PODF 位,可以設置為 0~7,分別對應 1~8 分頻。如果要
設置為2分頻的話CCM_CACRR就要設置為1。再來看一下寄存器CCM_ANALOG_PLL_ARMn,
此寄存器結構如圖 8.1.4.3 所示:
圖 8.1.4.3 寄存器 CCM_ANALOG_PLL_ARMn
????????在寄存器 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 可選擇的
時鐘源如圖 8.1.4.4 所示:
圖 8.1.4.4 PLL1 時鐘開關
????????①、pll1_sw_clk 也就是 PLL1 的最終輸出頻率。
????????②、此處是一個選擇器,選擇 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 調整完成以后
再切換回來。
????????③、此處也是一個選擇器,選擇 step_clk 的時鐘源,由寄存器 CCM_CCSR 的 STEP_SEL 位來決定 step_clk 是選擇 osc_clk 還是 secondary_clk。一般選擇 osc_clk,也就是 24MHz 的晶振。這里我們就用到了一個寄存器 CCM_CCSR,此寄存器結構如圖 8.1.4.5 所示:
圖 8.1.4.5 寄存器 CCM_CCSR 結構圖
????????寄存器 CCM_CCSR 我們只用到了 STEP_SEL、PLL1_SW_CLK_SEL 這兩個位,一個是用
來選擇 step_clk 時鐘源的,一個是用來選擇 pll1_sw_clk 時鐘源的。
????????到這里,修改 I.MX6U 主頻的步驟就很清晰了,修改步驟如下:
????????①、 設置寄存器 CCSR 的 STEP_SEL 位,設置 step_clk 的時鐘源為 24M 的晶振。
????????②、設置寄存器 CCSR 的 PLL1_SW_CLK_SEL 位,設置 pll1_sw_clk 的時鐘源為
step_clk=24MHz,通過這一步我們就將 I.MX6U 的主頻先設置為 24MHz,直接來自于外部的
24M 晶振。
????????③、設置寄存器 CCM_ANALOG_PLL_ARMn,將 pll1_main_clk(PLL1)設置為 1056MHz。
????????④、設置寄存器 CCSR 的 PLL1_SW_CLK_SEL 位,重新將 pll1_sw_clk 的時鐘源切換回
pll1_main_clk,切換回來以后的 pll1_sw_clk 就等于 1056MHz。
????????⑤、最后設置寄存器 CCM_CACRR 的 ARM_PODF 為 2 分頻,I.MX6U 的內核主頻就為
1056/2=528MHz。????????