匯編實現(xiàn)時鐘設置代碼理解-創(chuàng)新互聯(lián)

匯編實現(xiàn)時鐘設置代碼理解

10余年的呼圖壁網(wǎng)站建設經(jīng)驗,針對設計、前端、開發(fā)、售后、文案、推廣等六對一服務,響應快,48小時及時工作處理。網(wǎng)絡營銷推廣的優(yōu)勢是能夠根據(jù)用戶設備顯示端的尺寸不同,自動調(diào)整呼圖壁建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“呼圖壁網(wǎng)站設計”,“呼圖壁網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。

下面的筆記是我在看《朱老師物聯(lián)網(wǎng)大講堂》(www.zhulaoshi.org)之后所做的筆記,只是大概根據(jù)自己看了視頻與朱老師上課做的筆記而有的理解記錄下來。

寫了

有代碼的,要把代碼給理解完整。

朱老師的隨堂程序是:clock.s

// 時鐘控制器基地址

#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 CLK_DIV0_MASK0x7fffffff

// 這些M、P、S的配置值都是查數(shù)據(jù)手冊中典型時鐘配置值的推薦配置得來的。

// 這些配置值是三星推薦的,因此工作最穩(wěn)定。如果是自己隨便瞎拼湊出來的那就要

// 經(jīng)過嚴格測試,才能保證一定對。

#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

// 1 設置各種時鐘開關,暫時不使用PLL

ldrr1, =0x0

// 芯片手冊P378 寄存器CLK_SRC:Select clock source 0 (Main)

strr1, [r0, #CLK_SRC0_OFFSET]

// 2 設置鎖定時間,使用默認值即可

// 設置PLL后,時鐘從Fin提升到目標頻率時,需要一定的時間,即鎖定時間

ldrr1,=0x0000FFFF

strr1,[r0, #APLL_LOCK_OFFSET]

str r1, [r0, #MPLL_LOCK_OFFSET]

// 3 設置分頻

// 清bit[0~31]

ldr r1, [r0, #CLK_DIV0_OFFSET]

ldrr2, =CLK_DIV0_MASK

bicr1, r1, r2

ldrr2, =0x14131440

orrr1, r1, r2

strr1, [r0, #CLK_DIV0_OFFSET]

// 4 設置PLL

// FOUT = MDIV*FIN/(PDIV*2^(SDIV-1))=0x7d*24/(0x3*2^(1-1))=1000 MHz

ldrr1, = APLL_VAL

strr1, [r0, #APLL_CON0_OFFSET]

// FOUT = MDIV*FIN/(PDIV*2^SDIV)=0x29b*24/(0xc*2^1)= 667 MHz

ldrr1, = MPLL_VAL

strr1, [r0, #MPLL_CON_OFFSET]

// 5 設置各種時鐘開關,使用PLL

ldrr1, [r0, #CLK_SRC0_OFFSET]

ldrr2, =0x10001111

orrr1, r1, r2

strr1, [r0, #CLK_SRC0_OFFSET]

movpc, lr

(下面就是對這一個代碼的理解)

對clock.s這一個匯編代碼的理解

    這一段代碼的第一部分:設置各種時鐘開關,暫時不用PLL

    在前面的課程里面有對于時鐘框圖的解釋,像在文檔的3.2的Figure3.3的左上角的部分有畫著這么樣的東西,初始時鐘從左邊過來,然后有兩條路走,一條是通過PLL,另一條是直接連到一個MUX開關,所以我們設置初始時鐘而且不用PLL的時候我們做的就是選MUX開關來達到只設置時鐘不通過(繞過)PLL。這樣子的話就要去設置寄存器控制選通位了。

代碼:

ldrr0, =ELFIN_CLOCK_POWER_BASE

ldrr1, =0x0

strr1, [r0, #CLK_SRC0_OFFSET]// 芯片手冊P378 寄存器CLK_SRC:Select clock source 0 (Main)

解釋說到上面的代碼:

上往下數(shù)第一句

這一句是把ELFIN_CLOCK_POWER_BASE這個值賦給r0寄存器,為什么要賦這一個值呢?

可以從這一段匯編函數(shù)開始的更前面看起,這一個“ELFIN_CLOCK_POWER_BASE”是一個宏定義就是相當把ELFIN_CLOCK_POWER_BASE與0xE0100000等值起來了(就是用到ELFIN_CLOCK_POWER_BASE的時候就是相當于在用0xE0100000這個值)。

    為什么要把這個值在前面給宏定義出來呢?

從數(shù)據(jù)手冊的3.7 REGISTER DESCRIPTION看到關于這個時鐘的寄存器地址都是從0xE0100000這個地址開始,這個就是基地址,其他的地址都是相對著這一個地址偏移多少的量,通過一個計算,就是用基址地址加上偏移的量就可以找到我們想要設置的寄存器了,

如何通過上述所說的來給目標寄存器寫東西呢?

代碼的第三句有一個CLK_POWER_BASE,這個東西就是偏移量啦,但這是一堆字母沒看到量啊,其實就是想上面的ELFIN_CLOCK_POWER_BASE一樣,在前面已經(jīng)給宏定義一個值了。這一個值是0x200,因為我們要寫的寄存器是距離0xE0100000有0x200,我們就依據(jù)這個東西來找寄存器,并且寫入東西。寫入的值是0x0.就是這一個寄存器全部寫零。 為什么寫入0xE0100200這一個寄存器呢?

    這個地址所對應的寄存器的名稱是:CLK_SRC0,首先去看一下這個寄存器是干嘛的,在手冊的378頁有這個寄存的介紹與如何設置(3.7.3.1 Clock Source Control Registers)。為什么要設置這個寄存器,首先就要看我們剛開始的目的是什么,我們想干嘛。我們是想“設置各種時鐘開關,暫時不用PLL”,那么我們怎么去實現(xiàn)呢,那就要看一下,哪一個寄存器能夠滿足我們的要求了??匆幌逻@一寄存器的功能是,數(shù)據(jù)手冊上面寫的什么Clock Source Control,就是時鐘源控制的寄存器,我想的是這一個寄存器就是控制時鐘源的來源,從圖上面看的是設置晶振與時鐘發(fā)生器產(chǎn)生的時鐘是否是要經(jīng)過PLL,這樣子就可以滿足我們的目的要求了,我們的目的就是不要PLL,晶振與時鐘產(chǎn)生多少的頻率就向右傳多 少頻率,那么我們就是要使它不使用經(jīng)過PLL的頻率好。

    為什么傳入0x0:

    從手冊上面看到這一個寄存器的初始值(默認值都是選擇0的)就是都是剛開始默認不用PLL倍頻過后的程序。這個的話與上面的目標相符。這里重點看這幾個:

1、VPLL_SEL

2、EPLL_SEL

    3、MPLL_SEL

4、APLL_SEL

這幾個控制位都是賦值零的。就是都選擇FINOUT,這么選,貌似是因為s5pv210這個板子上面只焊了一個時鐘發(fā)生器。這個可供其他使用了,這樣子的話都選擇了0,那么就是都不經(jīng)過PLL的了,這樣的話就是不倍頻了。

代碼最后一段:

這個是按照變址尋址來做的,就是把r1的值寫入到r0+CLK_SRC0_OFFSET這一個地址里面去(因為是統(tǒng)一編址,這個是個寄存器地址)。

到此,設置各種時鐘開關,暫時不用PLL的問題解決了。

第二步:設置鎖定時間,使用默認值即可。

為什么要設置鎖定時間,我的認為,因為鎖相環(huán)(PLL)想要初始時鐘(24MHz)在瞬間完成倍頻到1G是不可能的,它需要低頻率在PLL里面回環(huán)轉,一次次頻率的升高來達到1G這樣子的話就是是需要時間的,所以等一會兒,好了就可以了,在文檔(3.7.2 PLL CONTROL REGISTERS)上面是說當輸入的頻率頻率改變或者分頻的值改變是得鎖定時間。鎖定時間的長短基于PLL的源時鐘,用PLL_LOCK這一個寄存器去設置,

ldrr1,=0x0000FFFF

strr1,[r0, #APLL_LOCK_OFFSET]

str r1, [r0, #MPLL_LOCK_OFFSET]

為什么寫入0x0000FFFF

這個寄存器只有低十六位可以用,大值就是0x0000FFFF,值設置越大,鎖定的時間就越就久。默認值是0x00000FFF,設置這一個大值也沒事,也就是隔久一點而已。時間超過剛好值的話那時候已經(jīng)是好了。

有兩個寄存器,就是鎖好兩個APLL和MPLL兩個倍頻器。就是這樣。

第三步:設置分頻

設置分頻系統(tǒng),由它決定給左邊的分多少倍從而得到右邊的頻率,說得清楚一些就是左邊的頻率除以一個分頻器可以接受的值,然后得到的值輸出到右邊。我們要做的就是設置分頻系數(shù),說清楚些就是設置那一個除數(shù)。設置的寄存器是CLK_DIV

如何設置呢?

視頻上面用說的方式給清楚地說出了如何去設置,在代碼中那個值是什么意思了。

    直接用代碼中的設置值來分析:

ldr r2, =0x14131440

給r2所指代的寄存器寫入0x14131440,從文檔的3.7.4.1 Clock Divider Control Register這一部分看。所寫入的數(shù)據(jù)的第一個1,是30:28位的,在關于這一個寄存器的設置描述欄中寫的是公式PCLK_PSYS = HCLK_PSYS / (PCLK_PSYS_RATIO + 1),我們寫的1,那就相當于給PCLK_PSYS_RATIO的值賦了一個1,這樣子的話下面的除數(shù)就是2.因為1+1等于2,PCLK_PSYS和HCLK_PSYS要從文檔上面3.4 CLOCK GENERATION的那個3.3圖中找,可以找到在右下角的PSYS域中的HCLK_PSYS和PCLK_PSYS,描述欄的公式意思是PCLK_PSYS的時鐘頻率是通過HCLK_PSYS的頻率除以2得到的。

代碼的理解:

  ldr r1, [r0, #CLK_DIV0_OFFSET]

  ldrr2, =CLK_DIV0_MASK

  bicr1, r1, r2

  ldrr2, =0x14131440

  orrr1, r1, r2

  strr1, [r0, #CLK_DIV0_OFFSET]

//忽然發(fā)現(xiàn)我理解不了,方法是往哪個寄存器寫東西?為什么往那里寫,為什么寫//0x14131440?(漫長)

第四步:設置PLL

這個地方也是要學會看文檔。(可見有會看文檔的功力也是很重要的)

講的是APLL和MPLL,這兩個PLL我們可以在文檔的361頁可以看到圖。

要對它做什么?

對他設置合適的參數(shù),然后lock,然后等待輸出。

怎么設置參數(shù):

找文檔,現(xiàn)在設置的是APLL,找啊找,在文檔的372,上面有個APLL_CON0,看這一頁的寄存器位的介紹,首先要看一個公式:

 FOUT = MDIV X FIN / (PDIV × 2^(SDIV-1))

這個公式是與寄存位的介紹配合起來看的,想知道在公式上面的變量怎么設置看寄存器位的介紹表中的MDIV[25:16]、PDIV[13:8]、SDIV[2:0]這幾位。這幾個很重要。

公式中的MDIV值就是設置寄存器中的25:26位的值,F(xiàn)IN的值是左邊的頻率進PLL的值,比如在文檔上面“3.4 CLOCK GENERATION”部分的那個圖中看左上角的APLL地方的左邊寫著有PLL這就是FIN。FOUT同理可以理解。PDIV就是我們設置的PDIV(所在寄存器的位是13:8)的值,SDIV是就是設置的SDIV所在寄存器的位是(2:0)的值。

例:在文檔中給定的初始值是:MDIV是0xc8(對應的10進制是200),PDIV是0x3(對應的10進制是3),SDIV是0x1(對應的10進制是1),對于APLL的話FIN是24MHz把這些值代入上式得FOUT=24*200/3*2^0=1600,這是文檔上面一個想不到的東西,因為我們要設置的是1GHz,但是按照這一個初值來設置的話就變成了1.6GHz了。在程序中的數(shù)值與上述的數(shù)值不一樣的是MDIV的值,這個值應該設置成0x7d(對應的10進制是125)。關于這些經(jīng)典值可以到文檔的357頁的3.3.1RECOMMENDED PLL PMS VALUE FOR APLL可以得到三星給的推薦值。

但是在程序中計算FOUT的值有點讓人眼前一新(自己沒有碰到過的,在朱老師的C高級里面有講位運算):

#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)

下面要講的是MPLL:

MPLL的設置方法與APLL是一樣的,只是公式不一樣而已。

第五步:設置各種時鐘開關,使用PLL

從代碼來看:

ldrr1, [r0, #CLK_SRC0_OFFSET]

ldrr2, =0x10001111

orrr1, r1, r2

strr1, [r0, #CLK_SRC0_OFFSET]

這里要理解的是0x10001111的問題,在CLK_SRC0寄存器中寫入這一個值,為什么要寫入這一個值。

這里又要配合著文檔上面的《3.7.3.1 Clock Source Control Registers》這一部分來查看開了使用了哪一個東西,之后去配合《3.4 CLOCK GENERATION》這一部分的圖后,結合之前學過的xPLL與DIV的使用原理,可以算出在CLK_SRC0之后,頻率經(jīng)過什么樣的路徑,最后到達使用的部件的頻率是多少。

剛剛才入ARM裸機這水,還不深,其中肯定會有疏忽和錯誤,如果看了這篇筆記發(fā)現(xiàn)了錯誤,請指出,謝謝。

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

網(wǎng)頁題目:匯編實現(xiàn)時鐘設置代碼理解-創(chuàng)新互聯(lián)
網(wǎng)頁鏈接:http://muchs.cn/article10/dsijdo.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、網(wǎng)站策劃、全網(wǎng)營銷推廣、標簽優(yōu)化、App設計、品牌網(wǎng)站建設

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站建設