相關名詞:
oscillator:振蕩器
phase locked loops:鎖相環(PLL)
這篇文章我們只涉及如何初始化APLL以及獲得相應的ARMCLK時鐘,對于其它部分我們放到下一次再進行介紹。
在芯片手冊里,“時鐘管理單元 (Clock Management Unit)“的簡稱為 CMU 。CMU_ XXX 表示“XXX 模塊內的 CMU ”,比如CMU_CPU等。
對于PC來說, CPU 、內存、主板、聲卡、顯卡等,這些功能部件由不同的芯片組成, 在實體上是相互獨立的。在嵌入式系統里,一塊芯片內往往集成了多種功能比如Exynos 4412 上面既有CPU,還有音頻 /視頻接口、 LCD 接口、 GPS 等模塊 這類芯片被稱為 SoC,即 System on Chip,譯為芯片級系統或片上系統。
Exynos4412時鐘體系
不同的模塊往往工作在不同的頻率下,一個芯片上采用單時鐘設計基本是不可能實現的 ,在 SoC設計中采取多時鐘域設計。4412的時鐘域有5個, 如下圖所示:
這 5個時鐘域名如下 (下文中的 BLK 表示 block ,模塊 ):
①CPU_BLK :
內含 Cortex-A9 MPCore處理器、 L2 cache 控制器、CoreSight (調試用 )。CMU_CPU用于給這些部件產生時鐘 。
② DMC_BLK :
內含 DRAM 內存控制器 (DMC)、安裝子系統 (Security sub system )、通用中斷控制器 (Generic Interrupt Controller,GIC) 。CMU_DMC 用于給這些部件產生時鐘。
③ LEFTBUS_BLK 和 RIGHTBUS_BLK:
它們是全局的數據總線,用于在 DRAM 和和其他子模塊之間傳輸數據。
④ 其他BLK : 在上圖中,用畫筆圈起來的模塊 。
CMU_TOP用于給這些模塊產生時鐘。
4412有3個初始時鐘源:
① XRTCXTI引腳 :接 32KHz(32.768KHz)的晶振,用于實時鐘 (RTC) 。
② XXTI引腳 :接12M ~50 MHz的晶振, 用于向系統提供時鐘,也可以不接。
③ XUSBXTI引腳 :接24MHz的晶振 ,該時鐘源提供給USB PHY和PLL(APLL、MPLL、VPLL、EPLL)。
為什么選擇給XUSBXTI引腳接外部晶振?晶振為什么選擇24MHz?
由于一般USB IP核需要直接使用高精度時鐘,所以在XUSBXTI引腳上接24M晶振,XXTI引腳就不需要接了。手冊上說由于iROM代碼是根據24M晶振頻率設計的。
We recommend using a 24 MHz crystal as the iROM design is based on the 24 MHz input clock.
從原理圖上可知, 4412開發板外接24MHz的晶振;但是4412的CPU頻率可達1.4GHz。可以想象,一定有硬件部件把24MHZ的頻率提升為1.4GHZ,這個部件被稱為PLL(鎖相環)。4412內部其他部件也要工作于一定頻率,比 UART 、DDR等,也應該有PLL把24MHZ的頻率提高后供給它們。
PLL
4412有4個PLL,分別為APLL、MPLL、EPLL和VPLL;2個PHY:(USB PHY和HDMI PHY(PHY:物理層,一般指與外部信號接口的芯片))。芯片手冊5.3章節
① APLL:用于 CPU_BLK (可產生高達1.4GHz的頻率);作為 MPLL 的補充,它也可以給 DMC_BLK 、LEFTBUS_BLK 、RIGHTBUS_BLK 和 CMU_TOP 提供時鐘。
② MPLL:(可產生高達1GHz的頻率)用于DMC_BLK 、LEFTBUS_BLK 、RIGHTBUS_BLK 和 CMU_TOP。
③ EPLL :主要給音頻模塊提供時鐘,192MHz
④ VPLL :主要給視頻系統提供54MHz時鐘, 給 G3D(3D圖形加速器 )提供時鐘,或者是1.1V下的440MHz。
⑤ USB PHY :給 USB 子系統提供 30MHz 和 48MHz 時鐘 。
⑥ HDMI PHY :產生 54MHz 時鐘 。
4412時鐘流程
以上圖為例,里面涉及3個概念:
① MUX:多路復用,即從多個輸入源中選擇一個
② PLL:把低頻率的輸入時鐘提高后輸出
③ p:分頻器,把高頻率的輸入時鐘降頻后輸出
左邊深色的:無抖動多路選擇器,無抖動意味著在多路選擇切換的瞬間,下游時鐘就可以穩定下來。需要注意是在切換時要保證上游時鐘已經存在并穩定,不然下游時鐘狀態不確定。
右邊淺色的:有抖動多路選擇器,意味著多路選擇切換后,要經歷一段時間的不穩定時間,但是有穩定后有相應寄存器標志位標示下游時鐘已經穩定,這類指示寄存器器一般以CLK_MUX_STAT開頭。
由APLL的時鐘流程圖可知, 它的時鐘來源可以是 XXTI引腳上接的晶振,也可以是 XUSBXTI 引腳上接的晶振,通過上圖左邊的MUX來選擇,這個MUX的輸出被稱為FINPLL。
通過設置APLL的寄存器 (根據公式選擇參數值 ),可以把FINPLL提高為某個頻率輸出,假設為1.4GHz ,在圖上它被命名為FOUTAPLL。
繼續往右看圖,里面有多個p ,可以設置對應的寄存器把頻率降下來。 CPU可以工作于1.4GHz,但是其他模塊不能工作于這么高的頻率所以要把頻率降下來。
如何設置PLL
設置 PLL 的流程如下: 的流程如下:
(1)設置系統PLL鎖定時間
(2)配置PLL
(3)配置各模塊分頻系數
(4)切換到PLL時鐘
① 設置PLL的 P、M、S值,這是根據期望得到的頻率用公式計算出來
② 設置PLL的其他控制參數
③ 使能PLL
④ PLL會等待一段時間使時鐘穩定
⑤ 設置MUX ,選擇PLL所輸出的時鐘
簡單地說就是: 先設置,再啟動,后使用。
第 5點意味著:如果當前正使用該PLL,那么先設置 MUX 改用其他時鐘源或禁止使用此 PLL,設置完PLL后再設置MUX改回原來所使用的PLL時鐘。
PLL寄存器
4412時鐘控制器地址分布表
以APLL舉例說明。
APLL的地址即是上表中的CMU_CPU,即0x1004_4000 - 0x1004_8000(相關描述見芯片說手冊5.9.1.131 APLL_LOCK之后的說明)。
簡單的說,比如復位后,CPU默認工作頻率在400Hz,現在需要升到1000Hz工作,那么從400-->1000Hz需要一個過程,假設為時間t1,在t1這段時間內,CPU的頻率是變化的,那么CPU的狀態就是不穩定的,此時,就需要把頻率鎖定,設置鎖定時間,直到CPU穩定的輸出頻率。
說明:設置APLL的參數并使能它后, APLL 并不能立刻輸出穩定的時鐘 ,它需要經歷一個鎖定的時間 (lock time) 。APLL的大鎖定時間是: (270 x Pp) 個周期。 所以 APLL_LOCK 設置為 (270 x Pp) 就可以了。(Pp即為PMS中的P值)
APLL_CON0寄存器
注意(Sp默認值應該為0x0而不是0x1):
APLL_CON0的reset value能夠在24MHz的輸入時鐘頻率下產生一個800MHz的時鐘。
Fout = 24 * 200 / (6 * 2^0) = 800MHz
FOUT = SRCCLK* M/(P * 2^S)
根據 M、P、S的值,可以算出APLL的輸出時鐘(芯片手冊的公式中2Sp應該是2的指數):
FOUT = Mp x FIN / (Pp x 2 ^ Sp)
FOUT范圍21.9MHz~1400MHz。
M、P、S的值應從下表中選取
Fout = 24 * 175 / (3 * 1) = 1400
APLL_CON1( 地址 : 0x10044104)(這里只列出了有用的位)
該寄存器用于設置 BYPASS 模式,即APLL是直接輸出FIN時鐘,還是提升頻率后再輸出時鐘;也用于設置AFC(自動頻率控制 )功能,暫時無需理會。該寄存器取默認值即可。
CLK_SRC_CPU (地址 : 0x10044200)
參考上面的APLL時鐘流程圖:
① BIT[0] 控制第1個MUX (即 MUXAPLL) ,用 于選擇是使FIN還是 APLL 的輸出時鐘,這個輸出被稱為 MOUTAPLL。
② BIT[16]控制 第2個 MUX( 即 MUXCORE) ,用于選擇 MOUTAPLL 還是 SCLKMPLL 。其中 SCLKMPLL 由下面的 MUXMPLL 控制。
③ BIT[24]控制第3個MUX( 即 MUXMPLL) ,用于選擇 FINPLL 還是 FOUTMPLL ,這個輸出被稱為SCLKMPLL 。其中, FOUTMPLL來自MPLL 的輸出。
④ BIT[20]控制第4個 MUX( 即 MUXHPM) ,用于選擇 MOUTAPLL還是 SCLKMPLL 。
CLK_MUX_STAT_CPU (地址 : 0x10044400) :
該寄存器全部為只讀寄存器,用于讀取 CLK_SRC_CPU寄存器里所設置的MUX 狀態。
CLK_p_CPU0 (地址 : 0x10044500),CLK_p_CPU1( 地址 : 0x10044504)
參考上面的APLL時鐘流程圖,以 CPU 的工作頻率 ARMCLK 為例,根據上圖計算ARMCLK的頻率:
ARMCLK = MUXCORE的輸出 / pCORE / pCORE2
= MOUTCORE / (CORE_RATIO + 1) / pCORE2
= MOUTCORE / (CORE_RATIO + 1) / (CORE2_RATIO + 1)
MOUTCORE表示MUXCORE的輸出,在MUXAPLL為1、MUXCORE為0時,它等于“Mp x FIN / (Pp x 2 ^ Sp),即APLL的輸出FOUT”
這里需要確認的是如何確定MOUTCORE的具體值,根據CLK_SRC_CPU中的BIT[0]以及BIT[16]確定MUXAPLL即MUXCORE的值。
CLK_p_STAT_CPU0 (地址 : 0x10044600),CLK_p_STAT_CPU1( 地址 : 0x1004 604)
用于判斷設置分頻參數后,分頻器輸出是否已經穩定。
在裸機程序中打印相關寄存器的值,分析一下當前CPU的時鐘。
分析一下該值:
首先APLL_CON0寄存器
Sp=0x0, Mp=0x3, Pp=0x7d=125---> Fout = 24 * 125/ (3 * 1) = 1000MHz--->APLL
APLL_CON1寄存器:BIT[22]=0,BYPASS=0。
CLK_SRC_CPU:0001 0000 0000 0000 0000 0000 0001
MUX_APLL_SEL= 1 ->MOUTAPLLFOUT
MUX_CORE_SEL= 0 ->MOUTAPLL(這兩個決定了當前使用的就是FOUT的時鐘)
CLK_p_CPU0寄存器:BIT[30:28]=0 BIT[2:0]=0
ARM_CLK=MOUTCORE / (CORE_RATIO + 1) / (CORE2_RATIO + 1)
= FOUT/1/1= FOUT=1000MHz
為什么當前的ARM_CLK是1000MHz?而不是1400MHz?
VDD_ARM 電壓是多少?
通過電路原理圖可知VDD_ARM的電壓為1.1V。
經過APLL倍頻后的時鐘路徑
24MHz時鐘路徑
通過配置APLL寄存器,將當前接入的24MHz時鐘倍頻至固定頻率,并通過配置復用器以及分頻器,輸出相應的CPU時鐘ARMCLK。
這里我們略微分析一下配置時鐘的過程。
圖 使用APLL倍頻后的時鐘圖
配置APLL
APLL使一個PLL(鎖相環),在4412中這樣的PLL一共有4個,其他的名為MPLL,EPLL,VPLL,它們主要的功能就是將一個低頻率的輸入時鐘成倍提高,例如通過配置APLL后,可以將24MHz的時鐘提升至(200-1400)MHz,然后經過對應的多路復用器(MUX,從多個輸入源中選擇一個)后,再由相關的分頻器(p,把高頻率的時鐘降頻后輸出)分頻完成后得到相應的ARMCLK。
APLL倍頻的相關公式:
FOUT = FIN* M/(P * 2^S)
FOUT指經過APLL倍頻后的輸出值,在上圖中叫FOUTAPLL,FIN指的是外部輸入時鐘,圖中的FINPLL為24MHz,P、M、S的值為倍頻值,可以通過寄存器(APLL_CON0)進行配置,這里的值好取芯片手冊中固定的那些,如下圖。
例如我們要輸出一個1000MHz的時鐘,相應的計算公式為:
FOUT = 24MHz * 125/(3 * 2^0) = 1000MHz。//其他的時鐘則按照同樣的方式進行計算
圖 配置APLL后
配置MUX多路復用器
這里需要配置MUXAPLL以及MUXCORE兩個,這個由CLK_SRC_CPU寄存器進行配置,對于MUXAPLL為1選擇輸入源為FOUTAPLL,對于MUXCORE為0選擇MOUTAPLL。
圖 配置兩個MUX后
配置p分頻器
這里需要配置pCORE以及pCORE2兩個分頻器,這個由CLK_p_CPU0寄存器進行配置,將CORE_RATIO以及CORE2_RATIO均配置為0,這樣就可以得到1000MHz的ARMCLK。
相應的分頻器的計算公式:
對于pCORE分頻器來說,輸入時鐘源為MOUTCORE(M代表MUX,OUT表示輸出,CORE代表CORE復用器,即MOUTCORE是MUXCORE復用器輸出時鐘),輸出時鐘源為DOUTCORE,計算輸出時鐘源的大小為
DOUTCORE = MOUTCORE/(CORE_RATIO + 1)
對于及pCORE2分頻器來說,輸入時鐘為DOUTCORE,輸出時鐘為ARMCLK,計算輸出時鐘源的大小為
ARMCLK = DOUTCORE/(CORE2_RATIO + 1)
MOUTCORE時鐘就是由APLL倍頻后得到的FOUTAPLL,這樣我們可以獲得整個的時鐘計算公式
ARMCLK = (FIN*M)/(P*2^S*(CORE_RATIO+1)*(CORE2_RATIO+1))
下面介紹一下程序中的流程,相關寄存器不進行介紹,需要閱讀芯片手冊7.9.1章節
寄存器CLK_SRC_CPU更改系統使用時鐘,配置為暫時使用晶振提供時鐘,等我們APLL配置好并且穩定之后再切換回來。
CLK_SRC_CPU = 0x0;
寄存器APLL_LOCK 設置系統PLL鎖定時間,由于倍頻到較高時間,需要一個穩定的過程,這個過程為270*P的時間(P為PMS中的P值)。
APLL_LOCK = 270 * 3;
寄存器APLL_CON0 配置APLL需要的PMS值,并使能APLL。
APLL_CON0 = ((1<<31) | (0x7d<<16) | (0x3<<8) | (0x0));
寄存器CLK_p_CPU0 配置需要的分頻值CORE_RATIO及CORE2_RATIO
CLK_p_CPU0 = ((0<<28) | (2<<24) | (1<<20) | (6<<16) |(7<<12) | (7<<8) | (3<<4) | (0<<0));
寄存器CLK_SRC_CPU 使能APLL輸出。
CLK_SRC_CPU = 0x01000001;
不考慮其他影響,簡配置流程就是上邊的步驟。