Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1207727
  • 博文数量: 322
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 3276
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-17 09:21
文章分类

全部博文(322)

文章存档

2010年(155)

2009年(167)

我的朋友

分类: 嵌入式

2009-12-19 11:21:07

S3C2410 CPU默认的工作主频为12MHz,使用PLL电路可以产生更高的主频供CPU及外围器件使用。S3C2410有两个PLL:MPLL和UPLL,UPLL专用与USB设备。MPLL用于CPU及其他外围器件。

通过MPLL会产生三个部分的时钟频率:FCLK、HCLK、PLCK。FCLK用于CPU核,HCLK用于AHB总线的设备(比如SDRAM),PCLK用于APB总线的设备(比如UART)。从时钟结构图中可以查看到使用不同时钟频率的硬件。

Figure 7-1. Clock Generator Block Diagram

 

ARM硬件之时钟 - tianwaike1 - 开拓-进取

(注:这里要注意从图中看出,Uart使用的是PCLK)

时钟源选择

7-1描述了模式控制引脚(OM3OM2)和选择时钟源之间的对应关系。OM[3:2]的状态由OM3OM2引脚的状态在nRESET(当振荡器(crystal/oscillatto)时钟输出稳定后,nRESET引脚变为高电平)的上升沿锁存得到。 

 注意:1、尽管MPLL在系统复位的时候就开始产生,但是只有有效的设置好MPLLCON寄存器后才能用于系统时钟。在此之前,外部时钟将直接作为系统时钟。即使不需要改变MPLLCON寄存器的初值,也必须将同样的值写入寄存器。

2、当OM[1:0]11时,OM[3:2]用于决定一种测试模式。

下面介绍MPLL的启动流程:

(注:下面内容部分直接摘录自《s3c2410完全开发流程》,Clock部分写了非常好)

S3c2410 datasheet 224页“Figure 7-4. Power-On Reset Sequence”展示了上电后MPLL启动的过程

 

ARM硬件之时钟 - tianwaike1 - 开拓-进取

 

请跟随FCLK的图像了解启动过程:

1、上电几毫秒后,晶振输出稳定,FCLK=晶振频率,nRESET信号恢复高电平后,CPU开始执行指令。

2、我们可以在程序开头启动MPLL,在设置MPLL的几个寄存器后,需要等待一段时间(Lock Time),MPLL的输出才稳定。在这段时间(Lock Time)内,FCLK停振,CPU停止工作。Lock Time的长短由寄存器LOCKTIME设定。

3、Lock Time之后,MPLL输出正常,CPU工作在新的FCLK下。

 

设置S3c2410的时钟频率就是设置MPLL的几个寄存器:

1、LOCKTIME:设为0x00ffffff

前面说过,MPLL启动后需要等待一段时间(Lock Time),使得其输出稳定。位[23:12]用于UPLL,位[11:0]用于MPLL。使用确省值0x00ffffff即可。

2、CLKDIVN:用来设置FCLK:HCLK:PCLK的比例关系,默认为1:1:1

这里值设为0x03,即FCLK:HCLK:PCLK=1:2:4

CLKDIVN不同的设置及对应的时钟比例关系如下图:

ARM硬件之时钟 - tianwaike1 - 开拓-进取

 

3、MPLLCON:设为(0x5c << 12)|(0x04 << 4)|(0x00),即0x5c0040

对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV。有如下计算公式:

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

其中: m = MDIV + 8, p = PDIV + 2

Fin 即默认输入的时钟频率12MHz。MPLLCON设为0x5c0040,可以计算出FCLK=200MHz,再由CLKDIVN的设置可知:HCLK=100MHz,PCLK=50MHz。

 

 通常我们将如上时钟初始化的过程写成clock_init函数供其他函数调用,代码如下:

void clock_init(void)

{

        /*init clock*/

rLOCKTIME = 0xFFFFFF;

    /*设置FCLK:HCLK:PCLK=1:2:4,这样假设处理器主频为200M,则HCLK为50M,PCLK为25M。ARM920T内核使用FCLK, 内存控制器,LCD控制器等使用HCLK,看门狗、串口等使用PCLK*/

rCLKDIVN  = 0x3;

    /* 设置时钟频率为200M*/

    rMPLLCON = 0x5c0040;

    }

改变2410的PLL频率,具体过程:

1、第一步软件工作: 设置P M S divider control,也就是设置MPLLCON寄存器。

    关于PMS,可以看Figure 7-2.寄存器MPLLCON的设置呢,其实有一定的规则,并非你想要的每个Fclk频率都可以得到。官方推荐了一个表PLL VALUE SELECTION TABLE,要按照这个进行。否则的话,就需要自己按照公式推算,但是mizi公司并不保证你的设置是合适的。所以,如果想要工作在200MHz,还是按照vivi的推荐值即可。

@ step1: set P M S divider control

        mov r1, #CLK_CTL_BASE

         ldr r2, =vMPLLCON_200

        str r2, [r1, #oMPLLCON]

    其中,MDIV=0x5c,PDIV=0x04,SDIV=0x00.公式Mpll(Fclk)=(m×Fin)/(p×(2^s))【m=MDIV+8, p=PDIV+2,s=SDIV】

    2、第二步软件工作:设置CLKDIVN。

    这一步是设置分频系数,即Fclk为cpu主频,Hclk由Fclk分频得到,Pclk由Hclk分频得到。假设Hclk是Fclk的二分频,Pclk是Hclk的二分频,那么分频系数比就是Fclk:Hclk:Pclk=1:2:4.那么Hclk为100MHz,总线时钟周期为10ns。Pclk为50MHz。

@ step2: change clock divider

        mov r1, #CLK_CTL_BASE

        mov r2, #vCLKDIVN

        str r2, [r1, #oCLKDIVN]

    3、第三步软件工作: CLKDIVN的补充设置

  void ChangeClockDivider(int hdivn,int pdivn)

{

     // hdivn,pdivn FCLK:HCLK:PCLK

     //     0,0         1:1:1

     //     0,1         1:1:2

     //     1,0         1:2:2

     //     1,1         1:2:4

    rCLKDIVN = (hdivn<<1) | pdivn;   

    

    if(hdivn)

        MMU_SetAsyncBusMode();

    else

        MMU_SetFastBusMode();

}

If HDIVN = 1, CPU总线模式必须从快速总线模式转变为同步总线模式,采用以下指令

;void MMU_SetFastBusMode(void)

; FCLK:HCLK= 1:1

  EXPORT MMU_SetFastBusMode

MMU_SetFastBusMode

   mrc  p15,0,r0,c1,c0,0

   bic  r0,r0,#R1_iA:OR:R1_nF

   mcr  p15,0,r0,c1,c0,0

   MOV_PC_LR

If HDIVN=1 and CPU总线模式为快速总线模式时, CPU由HCLK提供. 该特性可以在不改变HCLK and PCLK的前提下把CPU的频率减半.

 

;void MMU_SetAsyncBusMode(void)

; FCLK:HCLK= 1:2

   EXPORT MMU_SetAsyncBusMode

MMU_SetAsyncBusMode

   mrc  p15,0,r0,c1,c0,0

   orr  r0,r0,#R1_nF:OR:R1_iA

   mcr  p15,0,r0,c1,c0,0

   MOV_PC_LR

    4、第四步软件工作:等待locktime时间,让新的Fclk生效

@ step4: stay locktime

        mov r1, #CLK_CTL_BASE

         ldr r2, =vLOCKTIME

        str r2, [r1, #oLOCKTIME]

    6、对外设的影响

    在这个实验中,主要是有两个需要改变,一个外设是UART,一个外设是SDRAM。

    (1)UART,它是接在APB总线上,所以对应的时钟信号为Pclk,现在为50MHz。如果想要设置波特率为115200bps,那么根据公式UBRDIV0=(int)(PCLK/(bps*16))-1计算,应该为26。如果放到程序中,那么应该注意形式。具体如下:

UBRDIV0 = ((int)(PCLK/16./UART_BAUD_RATE) -1);

    (2)SDRAM,主要的影响因素为刷新频率。前面在SDRAM中没有具体分析,现在可以详细说明。使用了两片HY57V561620CT-H,查看手册其刷新频率为8192 refresh cycles/64ms,所以刷新周期64ms/8192=7.8125us。看寄存器REFRESH的各个位的设置情况:

    ·REFEN[23]:开启自动模式,设为1

    ·TREFMD[22]:设为Auto refresh模式,设为0

    ·Trp[21:20]:看看RAS precharge Time,查看SDRAM手册,发现-H系列此参数至少为20ns,现在Hclk对应的时钟周期为10ns,所以至少应该为2个clock。可以设为00

    ·Tsrc: Semi Row Cycle Time,也就是RAS Cycle Time,至少65ms,所以至少得6.5clock,按照可选值,应该设置为11

    ·Refresh[10:0]:

    公式refresh period = (2^11 - refresh_count +1)/Hclk,由此推导出refresh_count=2^11+1-refresh period*Hclk。带入数值,计算得出1268=0x04f4,这个数值要用四舍五入,减少误差。

    ·其余的保留值,均设置为0

    由此得出该寄存器的值应该为0x008c04f4。

阅读(705) | 评论(0) | 转发(0) |
0

上一篇:S3C2410时钟部分总结

下一篇:[vi-faq中文版]

给主人留下些什么吧!~~