三、s3c2440 裸機 系統時鐘和定時器的設置

三、系統時鐘和定時器的設置

⑴系統時鐘原理分析

時鐘決定2440執行速度,2440可以使用外部提供的時鐘源,也可以使用外部的晶振然後通過內部的晶振獲得時鐘頻率;具體選擇使用哪一個時鐘源看下圖:


開發板一般吧引腳M2和M3連接的GND,所以說全部使用的是晶振(crystal)

除此之外,2440提供了3個時鐘源FCLK(用於cpu核),HCLK(advancedhigh performance bus,用於AHB總線設備,比如cpu核,dma,usb等),PCLK(advanced performance bus,用於外圍設備,比如看門狗,pwm定時器,adc等等),對於鎖相環,2440擁有兩種PLL其中一個爲UPLL,其專用於usb設備,還有一個是MPLL用於設置fclk,hclk,pclk。

假如不設置PLL此時FCLK爲Fin 也就是外部晶振爲12M。

設置PLL後,就是設置相應的寄存器來得到所需要的值,S3C2440使用了三個倍頻因子MDIV、PDIV和SDIV來設置倍頻,通過寄存器MPLLCON和UPLLCON可設置倍頻因子。其中MPLLCON寄存器用於設置處理器內核時鐘主頻FCLK,其輸入輸出頻率間的關係爲


  FCLK=MPLL=(2*m*Fin)/(p*2^s)

其中m=(MDIV+8), p=(PDIV+2), s=SDIV。

其中UPLLCON寄存器用於產生48MHz或96MHz,提供USB時鐘(UCLK),其輸入輸出頻率間的關係爲

UCLK=UPLL=(m *Fin) / (p * 2^s)

其中m=(MDIV+8), p=(PDIV+2), s=SDIV。

上面的MPLLCON和UPLLCON與MDIV,PDIV,SDIV的關係爲:


也就PLLCON的01位是SDIV,4-9位是PDIV,12-19位MDIV。

爲了方便,2440的芯片手冊給出了參考設置PLL的數值:

假設晶振爲12M,可以參考上圖的藍色加深部分的設置數值。上圖的48M和96M是設置UPLLCLK使用的。

通過表可以完成FCLK的設置,正如前面所說的,除了FCLK還有HCLK和PCLK需要設置,接下來就可以設置HCLK和PCLK,此時需要兩個寄存器:

對於CLKDIVN


通過此寄存器可以得到相應的HCLK和PCLK。但是由於在設置HDIVN(也就是CLKDIVN的1、2位)的時候需要用到CAMDIVN的第8位和第9位,CAMDIVN寄存器爲:


結合在上面的這兩個寄存器可以得到頻率。通過上面的兩個表格可以得到四個值:HDIVN ,PDIVN,HCLK3_HALF和 HCLK4_HALF,爲了方面描述它們的關係,可以參考表:

 

下手冊的後面有對時鐘的如下注釋:


這是說假如HDIVN不是0的話要加上:

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

 

通過上面的設置可以完成設置FCLK、HCLK、PCLK,實際上2440在設置時鐘前後的運行狀態是這樣的:(下面再給出設置MPLL的過程圖(UPLL類似))

 

 

 

通過上圖可以看到,在上電一段是時間後,等待nRESET信號(復位信號)恢復高電平後,然後可以執行PLL有關寄存器的操作了。其中OSC爲晶振的頻率大小爲12M,VCO爲輸出頻率。還可以看到在設置完PLL需要等待一段時間纔可以輸出設定頻率,這個等待時間是可以通過LOCKTIME寄存器來設置,這個時間是需要滿足一定的最小值的,使用默認值就可以。該寄存器說明見下圖:

 

 

總結:

設置時鐘相對來說比較簡單,這裏給出的其設置流程:

1、  設置cpu由新的時鐘頻率到舊的頻率下的間隔時間 設置LOCKTIME(默認值即可)

2、  設置FCLK、HCLK、PCLK頻率比例,可以通過設置寄存器CLKDIVN 輔助CAMDIVN

3、  /* 如果CLKDIVN 中的HDIVN非0,CPU的總線模式應該從“fast bus mode”變爲“asynchronousbus mode” */

_asm__(

 "mrc    p15, 0, r1, c1, c0,0\n"        /* 讀出控制寄存器 */

 "orr    r1, r1,#0xc0000000\n"          /* 設置爲“asynchronous bus mode” */

 "mcr   p15, 0, r1, c1, c0, 0\n"       /* 寫入控制寄存器 */

 );

4、  根據個人要求設置FCLK時鐘 可以通過設置MPLLCON來設置

5、  假如有需要,設置UCLK時鐘,可以通過設置UPLLCON來設置

 

測試設定代碼:

void mpll_init(void )

{

//1      設置cpu由新的時鐘頻率到舊的頻率下的間隔時間設置LOCKTIME(默認值即可)

 

 

//2      設置FCLKHCLKPCLK頻率比例,可以通過設置寄存器CLKDIVN  CAMDIVN

//若設置FCLK爲400M HCLK=100M   PCLK=50M

//hdivn=2  pdivn=1

rCLKDIVN |= (2<<1) | 1;

rCAMDIVN &=~(1<<9);

 

//3       /*如果CLKDIVN中的HDIVN0CPU的總線模式應該從“fast bus mode”變爲“asynchronous bus mode” */

__asm{

  mrc    p15, 0, r1, c1, c0, 0      /* 讀出控制寄存器 */

  orr    r1, r1, #0xc0000000          /* 設置爲“asynchronous bus mode” */

  mcr    p15, 0, r1, c1, c0, 0        /* 寫入控制寄存器 */

 };

 

//  MMU_SetAsyncBusMode();

 

//4      根據個人要求設置FCLK時鐘可以通過設置MPLLCON來設置

 // FCLK=MPLL=(2*m*Fin)/(p*2^s)

 // 其中m=(MDIV+8), p=(PDIV+2), s=SDIV

 // MDIV=0X5C PDIV=1  SDIV=1  FCLK=400M

 //

rMPLLCON=((0x5c<<12) | (1<<4) | 1);

 

//5      假如有需要,設置UCLK時鐘,可以通過設置UPLLCON來設置

}

 

⑵定時器原理分析

s3c2440擁有Timer0,1,2,3,4五個16位定時器,其中Timer0,1,2,3具有Pulse Width Modulation (PWM)功能,Timer4引腳沒有輸出,Timer0比較特殊,擁有適用於大電流的死區生成器。

定時器0 和1 共享一個8 位的預分頻器(預定標器),定時器2,3,4 共享另一個8 位預分頻器,其構造圖如圖所示:


可以看出,定時器的時鐘源爲PCLK,首先經過預分頻器降低頻率後,進入第二個分頻.可以生成5 種不同的分頻信號(1/2,1/4,1/8,1/16 和外部時鐘TCLK0、TCLK1。

這兩個預分頻器可以使用TCFG0寄存器來設置,其功能如圖:


 

可以看到,TCFG0的0-7位設置分頻器0,用來控制定時器0和定時器1,8到15位用來設置預分頻器1,用來控制定時器2、3、4。其頻率的計算公式就是:

定時器的時鐘頻率 = PCLK / {prescaler value+1 } /{divider value}

prescaler value的大小就是上面的寄存器設置每個8位大小是0到255 ,divider value的大小通過TCFG1來設置可以取值2、4、8、16,看下圖:

 

通過上面兩個寄存器設置完時鐘之後,就可以來控制定時器了,包括是否打開定時器,定時器的時間等等。

首先,需要看到的是TCON,用來控制定時器的打開與關閉,是否自動重新裝入初值:



通過上表可實現對5個定時器的控制,其中在人工裝入定時器值的時候需要注意,每次重新寫入初值的時候需要清零後再寫。以timer3爲例,介紹一下每一位作用:

Timer 3 auto reload on/off   這是說定時器是是否自動載入定時時間,或者定時器是否是週期性的。

Timer 3 output inverter on/off 這是說是否開啓反轉模式,開通與否的效果爲:


Timer 3 manualupdate該爲設置爲1是手工把數據裝入TCNTB3 & TCMPB3(下面會介紹這兩個寄存器)。

Timer 3 start/stop 打開或者關係定時器3.

在打開定時器之前,還需要給定時器裝入初值,以確定定時器觸發的時間,這裏需要兩個寄存器:TCMPBn,TCNTBn,這裏以定時器0爲例,接掃一下,先看寄存器介紹:

 

通過上表可以看出,TCMPBn用來設置比較值,TCNTBn用來設置初值。設定好這兩個寄存器後,定時器就會在規定的頻率下,TCNTBn開始減去1計數,直到減小到TCMPBn設定的比較值,此時可以通過讀取TCNTOn來觀察TCNTBn的值。

 

使用定時器設置如下:

1、  選定timer0-5定時器,設置預分頻器 TCFG0  和分頻器TCFG1

2、  給定時器設定定時時間,也就是給TCNTB0裝入初值 和 裝入TCMPBn寄存器比較器(默認0)

3、  設置定時時間載入方式及其打開定時器 使用寄存器TCON  

定時器設置參考代碼:

/*

void timer0_init()

{

 

//1、選定timer0-5定時器,設置預分頻器TCFG0 分頻器TCFG1

    //定時器的時鐘頻率 = PCLK / {prescaler value+1 } / {divider value}

// PCLK=50m    {prescaler value+1} / {divider value}

   rTCFG0 &= ~(0xFF) ;

     rTCFG0 |= 99 ;  //預分頻係數爲99

     rTCFG1 &= ~(0xf);

     rTCFG1 |= 0x03;  //16分頻

    

     //定時器的時鐘頻率=50000000/100/16=31250

//2     給定時器設定定時時間,也就是給TCNTB0裝入初值裝入TCMPBn寄存器比較器(默認0

 

     rTCNTB0=31250;//每秒一次

//TCMPBn取默認值0

 

//3     設置定時時間載入方式及其打開定時器使用寄存器TCON

     rTCON |=  (1 << 1) ; //TCNTB0TCMPB0裝入內部的TCNT0TCMP0

     rTCON &=~(0xf);

     rTCON |= 0x09 ;  //自動重載並且打開定時器0

    

    

     rINTMSK&=~(1<<10);//打開定時器0 中斷

     timer0_service_Init();//中斷服務函數初始化

 

}

參考:

http://www.cnblogs.com/idle_man/archive/2011/03/01/1968168.html

http://blog.csdn.net/mr_raptor/article/details/6555734 

http://www.cnblogs.com/hnrainll/archive/2011/06/28/2092292.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章