聲明:本文由個人學習過程中整理而成,轉載請註明出處。
1、什麼是時鐘?SoC爲什麼需要時鐘?
(1)生活中時鐘是用來記錄時間的,而在SOC中時鐘代表了一種同步的節拍。
(2)SOC中的各部件在時鐘系統的作用下協同工作。
2、時鐘一般如何獲得
(1)外部輸入時鐘信號,SOC通過引腳從外部輸入時鐘信號。
(2)外部晶體振盪器+內部時鐘發生器產生時鐘信號。
(3)外部晶體振盪器+內部時鐘發生器+內部PLL產生高頻時鐘+內部分頻器(各部件都有自己的分頻器)產生各種頻率時鐘。
3、時鐘設置步驟:
(1)、暫不使用PLL。
(2)、設置鎖定時間,使用默認值即可。
(3)、設置PLL倍頻後的目標值。
(4)、設置分頻
(5)、設置各種PLL的MUX,使用PLL。
4、彙編代碼實現
#define ELFIN_CLOCK_POWER_BASE0xE0100000
#define APLL_LOCK_OFFSET0x00
#define MPLL_LOCK_OFFSET0x08
#define APLL_CON0_OFFSET0x100
#define APLL_CON1_OFFSET0x104
#define MPLL_CON_OFFSET0x108
#define CLK_SRC0_OFFSET0x200
#define CLK_SRC1_OFFSET0x204
#define CLK_SRC2_OFFSET0x208
#define CLK_SRC3_OFFSET0x20c
#define CLK_SRC4_OFFSET0x210
#define CLK_SRC5_OFFSET0x214
#define CLK_SRC6_OFFSET0x218
#define CLK_SRC_MASK0_OFFSET 0x280
#define CLK_SRC_MASK1_OFFSET 0x284
#define CLK_DIV0_OFFSET0x300
#define CLK_DIV1_OFFSET0x304
#define CLK_DIV2_OFFSET0x308
#define CLK_DIV3_OFFSET0x30c
#define CLK_DIV4_OFFSET0x310
#define CLK_DIV5_OFFSET0x314
#define CLK_DIV6_OFFSET0x318
#define CLK_DIV7_OFFSET0x31c
#define APLL_MDIV 0x7d// 125
#define APLL_PDIV 0x3
#define APLL_SDIV 0x1
#define MPLL_MDIV0x29b// 667
#define MPLL_PDIV0xc
#define MPLL_SDIV0x1
#define set_pll(mdiv, pdiv, sdiv)(1<<31 | mdiv<<16 | pdiv<<8 | sdiv)
#define APLL_VALset_pll(APLL_MDIV,APLL_PDIV,APLL_SDIV)
#define MPLL_VALset_pll(MPLL_MDIV,MPLL_PDIV,MPLL_SDIV)
.global clock_init
clock_init:
ldrr0, =ELFIN_CLOCK_POWER_BASE
// 設置CLK_SRC0寄存器bit[0]選FINPLL
ldrr1, =0x0
strr1, [r0, #CLK_SRC0_OFFSET]
// 設置PLL後,時鐘從輸入源FIN提升到目標頻率時,需要一定的時間。
ldrr1,=0x00000FFF
strr1,[r0, #APLL_LOCK_OFFSET]
str r1, [r0, #MPLL_LOCK_OFFSET]
// 設置APLL_CON0寄存器,FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHz
ldrr1, =APLL_VAL
strr1, [r0, #APLL_CON0_OFFSET]
// 設置MPLL_CON0寄存器,FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz
ldrr1, =MPLL_VAL
strr1, [r0, #MPLL_CON_OFFSET]
// 設置CLK_DIV0寄存器清bit[0~31]。
ldr r1, [r0, #CLK_DIV0_OFFSET]
ldrr2, =0xFFFFFFFF
bicr1, r1, r2
// 設置CLK_DIV0寄存器[0~31]寫相關位。
ldrr2, =((0<<0) | (4<<4) | (4<<8) | (1<<12) | (3<<16) | (1<<20) | (4<<24) | (1<<28))
orrr1, r1, r2
strr1, [r0, #CLK_DIV0_OFFSET]
// 設置CLK_SRC0寄存器。
ldrr1, [r0, #CLK_SRC0_OFFSET]
ldrr2, =((1<<0) | (1<<4) | (1<<8) | (1<<12) | (0<<16) | (0<<20) | (0<<24) | (1<<28))
orrr1, r1, r2
strr1, [r0, #CLK_SRC0_OFFSET]
movpc, lr
參考資料:《ARM裸機全集---朱有鵬老師》