JZ2440開發板:修改ARM芯片時鐘(學習筆記)

  想要修改ARM芯片的時鐘,須要去查詢芯片手冊和原理圖,獲取相關的信息(見下方圖片)html

首先來看時鐘的結構圖linux


 

根據結構圖能夠看出,時鐘源有兩種選擇:1. XTIpll和XTOpll所鏈接的晶振 異步

                   2. EXTCLK引腳外接一個時鐘源函數


 

OM[3:2]用來選擇到底使用哪一個時鐘源ui


 

再查看原理圖,能夠發現:OM3和OM2硬件上都是接GND,因此能夠知道:採用12MHz晶振做爲時鐘源spa


 

閱讀芯片手冊,還能夠查詢到其餘寄存器的相關信息,見下圖:.net

 

JZ2440內部使用三種時鐘:3d

            FCLK: 用於ARM920T芯片,即CPUunix

            HCLK:經過AHB總線,提供給ARM920T芯片、內存控制器,中斷控制器,LCD控制器等等code

            PCLK:   經過APB總線,提供給一些外圍設備使用,如WDT,IIS,I2C等等


 

FCLK經過HDIVN分頻獲得HCLK,經過PDIVN分頻獲得PCLK,這裏設置FCLK:HCLK:PCLK=400MHz : 100MHz : 50Hz

   一、修改MPLLCON寄存器中MDIV ,PDIV ,SDIV的值爲92 ,1 ,1,能夠獲得FCLK爲400MHz

   二、修改CLKDIVN中,HDIVN和PDIVN分別爲0b10和1,使得HCLK=FCLK/4 , PCLK=HCLK/2

 


 

閱讀芯片手冊中,晶振做爲時鐘源的時序圖,能夠發現,當配置PLL時,會有一個LOCKTIME時間,用來等待輸出的FCLK頻率穩定


在這裏,不對LOCKTIME進行修改,仍然使用它的默認值0xFFFFFFFF


繼續閱讀芯片手冊,有一個備註信息:

    當HDIVN不是0且CPU工做於快速總線模式的時候,CPU會採用HCLK做爲它的時鐘頻率,

    所以若是想讓HDIVN修改後,CPU採用FCLK,必須添加下方代碼,讓CPU工做於異步模式 

      mrc p15,0,r0,c1,c0,0
      orr r0,r0,#R1_nF:OR:R1_iA                      
      mcr p15,0,r0,c1,c0,0

【代碼  #R1_nF:OR:R1_iA 的意思】———— 點我

對時鐘修改的分析就大體差很少了,接下來寫彙編文件實現要求

.text .global _start _start: /* 關閉看門狗,若是不關閉,系統會自動重啓 */ ldr r0,=0x53000000 ldr r1,=0 str r1,[r0] /* 修改時鐘,FCLK=400MHz,HCLK=100MHz,PCLK=50MHz */
    
    /* 設置配置MPLL時的LOCKTIME時間爲默認值 */ ldr r0,=0x4c000000 ldr r1,=0xFFFFFFFF str r1,[r0] /* 設置FCLK:HCLK:PCLK=8:2:1 */ ldr r0,=0x4c000014 ldr r1,=0x5 str r1,[r0] /* 設置CPU工做於異步模式 ** 若是不做此設置,當HDIVN不是0時,CPU會採用HCLK的頻率而不是採用FCLK的頻率 */ mrc p15,0,r0,c1,c0,0 orr r0,r0,#0xc0000000    // #R1_nF:OR:R1_iA等價於#0xc0000000
    mcr p15,0,r0,c1,c0,0

    /* 設置MPLL的PMS,使得FCLK=400MHz ** m = MDIV+8 = 92+8=100 ** p = PDIV+2 = 1+2 = 3 ** s = SDIV = 1 ** FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400MHz */ ldr r0,=0x4C000004 ldr r1,=(92<<12)|(1<<4)|(1<<0) str r1,[r0] /* 設置好PLL以後,就會鎖定lock time,直到PLL穩定輸出 */
    /* cpu會工做於新的頻率FCLK /* 判斷是nor啓動仍是nand啓動 ** 先把0地址原來的值讀取出來,保存到r0寄存器中 ** 再把0寫入0地址對應的內存單元,以後讀取0地址內存單元的值 ** 若是讀取出來的值與原來的值不一致,說明是nor啓動 ** 若是讀取出來的值與原來的值一致,說明是nand啓動,此時須要修改棧的地址 */ mov r1,#0 ldr r0,[r1] // 讀取原來的值,備份一下
    str r1,[r1]  // 把0寫入0地址
    ldr r2,[r1]  // 讀取0地址新的值
    cmp r2,r0    // 若是r0和r2的值同樣,說明是nand啓動,此時修改sp的值
    
    /* 設置棧:sp */ ldr sp,=0x40000000+4096 // 先默認nor啓動//     moveq sp,#4096    // 若是r2=r1,把4096傳給sp,改成nand啓動
    streq r0,[r1]    // 若是r2=r1,恢復0地址原來的值
    bl main          // 跳轉到main函數
halt: b halt // 不停的跳轉到halt,至關於死循環,方便觀察效果

另外再附上JZ2440開發板3盞LED燈循環點亮的C程序(和按鍵點亮LED燈須要知道的知識差很少,這裏再也不做分析),用來觀察時鐘修改後的效果

#include "s3c2440_soc.h"
void delay(volatile int d)                           //延時函數 
{ while(d--); } int main(void) { /*設置GPFCON的GPF4/5/6,讓它們變成輸出引腳*/ GPFCON &=~((3<<8)|(3<<10)|(3<<12));                        //先讓GPFCON的GPF4/5/6清零
    GPFCON |=((1<<8)|(1<<10)|(1<<12));                        //配置好GPFCON的GPF4/5/6,讓它們變成輸出引腳

    /*循環點亮3盞燈*/
    int val=0,tmp;                                  //val取值範圍0b000~0b111,恰好三盞燈
    while(1) { tmp=~val;                                    //由於val爲0的時候,燈會由亮到滅,因此這裏須要取反,才能讓燈從滅到亮
        tmp &=7;                                     //只須要三位的值就行了
        GPFDAT &=~(7<<4);                            //GPFDAT寄存器先清零,由於是4,5,6位,因此這裏7左移4位就能夠
        GPFDAT |=(tmp<<4); delay(100000);                            //加上一個延時,否則燈切換太快了,看不出來
        val++; if(val==8) { val=0; } } return 0; }

上傳到 linux,編譯獲得 led.bin文件,燒寫到開發板以後,發現LED燈切換得比之前快多了,由於CPU是400MHz了,ARM芯片時鐘修改爲功。

相關文章
相關標籤/搜索