zoukankan      html  css  js  c++  java
  • S3C2440时钟系统详解

    在讲述系统时钟之前,因为这些设备都是挂靠在系统时钟上的,所以必须先说系统时钟,S3C2440的时钟系统如下


    外部时钟源分两种,晶振或者外部频率,由om3-2选择,时钟电路根据两种选择也有两种


    我们来分析时钟图可以得到以下结论:  经过选择的外部时钟进入MPLL,进行锁相环倍频,经过锁相环之后的时钟MPLL_IN分成了三股,分别是FCLK,HCLK,PCLK.这其中HCLKPCLK又是从HCLK分频得到的,最后ARM920T这个系统内核模块得到了两个时钟HCLKFCLKDMA控制器,LCD控制器,内存控制器,总线控制器,外部nand控制器和TIC,摄像头接口都来自于HCLK时钟,LCD控制器,nand控制器,cam摄像头控制器的时钟可以选择从总线上切断开来,IIC WDT IIS PWM SDI GPIO ADC RTC UART012 SPI AC97这些外设都挂接在PCLK总线上,而且除了WDT外,都可以断开和总线的连接,另外USB时钟直接从MPLL_IN倍频得到,生成UCLKUSB主机时钟可以选择UCLK或者HCLKUSB设备时钟可选UCLK或者PCLK,所以,有时候初次接触芯片看图是一个很好的选择,文字偏于细节,看图能很快浏览全貌,通过我们的分析可以得到下面这个再次简化的文档

     

     

    输入时钟

    MPLL

    FCLK

    HCLK

    内存控制器,中断控制器,nand控制器,tic控制器等,系统内核920TDMA控制器

    PCLK

    基本外设RTC,UARTspi等外设

    只供给系统内核,

    USB PLL

    UCLK

    USB主机时钟,usb设备时钟

    这就是系统时钟的基本分布,剩下的细节无非就是如何分频,如何启用时钟停止时钟,锁相环配置等等了,首先关注MPLL


    这是PLL的锁定时间,一般设置小一点查询是否锁定成功就好


    这三个值搭配就可以选择不同的MCLK了,数据手册上有公式,经过MPLL倍频,就成功地获得了系统主时钟FCLK(也就是ARM920T时钟)


    通过这个寄存器进行时钟的使能与切断,要使用外设的时候不要忘记这个寄存器


    该寄存器确认以一种什么样的比例将FCLK分频为HCLKPCLK

    到这里基本上就描述完了系统时钟,只要弄清楚框架其实时钟也挺简单的,分频系数,功率控制,最主要要弄清楚哪个设备用了哪个时钟就OK

     

    接下来展示一段代码用来计算系统时钟(在2440init.s里面就有设置时钟的过程,可以参考)

     

    Clock.c

    #include "clock.h"
    
    #define FIN 	(12000000)	
    
    U32 FCLK;
    U32 HCLK;
    U32 PCLK;
    U32 UCLK;
    
    
    void CalcBusClk(void)    //计算总线频率
    {
    	U32 val,UPLL;
    	U8 m, p, s;
    	val = rMPLLCON;
    	m = (val >> 12) & 0xff;
    	p = (val >> 4) & 0x3f;
    	s = val & 3;
    
    	FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;
    	
    	val = rCLKDIVN;
    	m = (val >> 1) & 3;
    	p = val & 1;	
    	val = rCAMDIVN;
    	s = val >> 8;
    	
    	switch (m) 
    	{
    		case 0:
    			HCLK = FCLK;
    			break;
    		case 1:
    			HCLK = FCLK >> 1;
    			break;
    		case 2:
    			if(s & 2)
    				HCLK = FCLK >> 3;
    			else
    				HCLK = FCLK >> 2;
    			break;
    		case 3:
    			if(s & 1)
    				HCLK = FCLK / 6;
    			else
    				HCLK = FCLK / 3;
    			break;
    	}
    	
    	if(p)
    		PCLK = HCLK >> 1;
    	else
    		PCLK = HCLK;
    		
    	val = rUPLLCON;
    	m = (val >> 12) & 0xff;
    	p = (val >> 4) & 0x3f;
    	s = val & 3;
    	UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
    	UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
    }
    
    //************************[ HCLK, PCLK ]***************************
    void ChangeClockDivider(int hdivn_val,int pdivn_val)
    {
    	int hdivn=2, pdivn=0;
    	
    	// hdivn_val (FCLK:HCLK)ratio hdivn
    	// 11           1:1       (0)
    	// 12           1:2       (1)
    	// 13           1:3       (3) 
    	// 14           1:4       (2)
    	// pdivn_val (HCLK:PCLK)ratio pdivn
    	// 11           1:1       (0)
    	// 12           1:2       (1)
    	switch(hdivn_val) {
    		case 11: hdivn=0; break;
    		case 12: hdivn=1; break;
    		case 13:
    		case 16: hdivn=3; break;
    		case 14: 
    		case 18: hdivn=2; break;
    	}
    	
    	switch(pdivn_val) {
    		case 11: pdivn=0; break;
    		case 12: pdivn=1; break;
    	}
    	
    	rCLKDIVN = (hdivn<<1) | pdivn;
    
    	switch(hdivn_val) {
    		case 16:		// when 1, HCLK=FCLK/8.
    			rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<8); 
    		break; 
    		case 18: 	// when 1, HCLK=FCLK/6.
    			rCAMDIVN = (rCAMDIVN & ~(3<<8)) | (1<<9); 
    		break;
    	}
    	
    	if(hdivn!=0)
    		MMU_SetAsyncBusMode();
    	else 
    		MMU_SetFastBusMode();
    }
    
    
    
    //**************************[ UPLL ]*******************************
    void ChangeUPllValue(int mdiv,int pdiv,int sdiv)
    {
    	rUPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
    }
    
    
    
    //***************************[ MPLL ]****************************
    void ChangeMPllValue(int mdiv,int pdiv,int sdiv)
    {
    	rMPLLCON = (mdiv<<12) | (pdiv<<4) | sdiv;
    }
    
    
    //*************************时钟配置函数*****************************
    void SetClock(u8 mpll)
    {
    	if(mpll == MPLL271)
    	{
    		ChangeMPllValue(173,2,2);	
    	}
    	else if(mpll == MPLL304)
    	{
    		ChangeMPllValue(68,1,1);
    	}
    	else if(mpll == MPLL405)
    	{
    		ChangeMPllValue(127,2,1);
    	}
    	else if(mpll == MPLL532)
    	{
    		ChangeMPllValue(125,1,1);
    	}
    	ChangeClockDivider(14,12);      //设置分频比为1:4:8 fclk hclk pclk 
    									//并设置cpu异步总线模式
    	CalcBusClk();                 //计算总线频率
    
    	
    }
    



    Clock.h

    #ifndef __CLOCK_H_
    #define __CLOCK_H_
    #include "def.h"
    #include "2440addr.h"
    #include "2440slib.h"
    
    #define FIN 	(12000000)	//外部晶振
    #define MPLL271	1	//几个典型的时钟宏定义
    #define MPLL304	2
    #define MPLL405	3
    #define MPLL532	4
    
    void CalcBusClk(void);    //计算总线频率
    void ChangeClockDivider(int hdivn_val,int pdivn_val);//计算分频数值
    void ChangeUPllValue(int mdiv,int pdiv,int sdiv);//配置usb总线
    void ChangeMPllValue(int mdiv,int pdiv,int sdiv);
    void SetClock(u8 mpll);//配置系统时钟
    
    extern U32 FCLK;
    extern U32 HCLK;
    extern U32 PCLK;
    extern U32 UCLK;
    
    
    
    #endif
    
    
    
    
    
    
    



    现在有了几个系统时钟的具体数字,我们就可以很好的进行外设时钟的配置了

     

    注意,设置系统时钟的时候HCLK如果太大会导致取值SDRAM跟不上,为了解决这个问题,三星说了这样一个方案,大家要注意哦:


     

  • 相关阅读:
    SQL面试积累
    The server does not support version 3.0 of the J2EE Web module specification
    AspectJ报错:error at ::0 can't find referenced pointcut XXX
    maven教程
    sqlMapConfig.xml配置文件详解
    解决eclipse+MAVEN提示One or more constraints have not been satisfied.的问题
    maven常见问题
    Dmaven.multiModuleProjectDirectory system propery is not set.
    maven最齐全配置pom.xml
    serialVersionUID的作用
  • 原文地址:https://www.cnblogs.com/dengxiaojun/p/4279420.html
Copyright © 2011-2022 走看看