学习uboot前奏之hardware-clock[s3c2440]

来源:互联网 发布:js tr td 编辑:程序博客网 时间:2024/06/10 14:48

本节我们来讲下嵌入式系统中时钟的概念,时钟为系统工作提供了基本的时间秩序。作为S3C2440可以直接使用外部晶振,或者直接通过内部电路产生时钟源。

关于时钟有三个名词我们需要理解:
FCLK:用于CPUC核的时钟
HCLK:用于AHB总线上的设备,比如CPU核、存储器控制器、中断控制器、DMA和USB主机模块
PCLK:用于APB总线上的设备 比如WATCHDOG、IIS、SPI等。

对于S3C2440主要有两个PLL:MPLL和UPLL,我们这里主要说明MPLL,MPLL主要用于设置FCLK、HCLK、PCLK。以下图开始来说下MPLL的设置过程:

这里写图片描述

  • 上电伊始的时候,PLL还没有设置,FCLK还是等于外部输入的时钟,相等于上图中OSC,当nRESET信号恢复高电平后,CPU开始执行指令。

  • 当设置PLL后,需要等待一段时间后,MPLL的输出才稳定,这段等待时间成为LockTime,由LOCKTIME设定。

  • MPLLCON:用于设置FCLK与Fin的倍数,对于不同的芯片有不同的计算方式

  • CLKDIVN:用于设置FCLK、HCLK、PCLK。

主要通过设置MPLLCON和CLKDIVN寄存器来设置FCLK、HCLK、PCLK的频率。

下面来说下S3C2440的PWM定时器:

这里写图片描述

从上图可以看出S3C2440共有5个16位定时器,其中定时0、1、2、3有PWM功能,即它们都有一个输出引脚,定时器4没有输出引脚。

定时器部件的时钟为PCLK,首先通过2个预分频器降低频率:定时器0、1共用第一个预分频器,定时器2、3、4共用第二份分频器。预分频器的输出将进入第二级分频器,它们输出5种频率的时钟:2分频、4分频,8分频,16分频或者外部时钟TCLK0\TCLK1,每个分频器的工作时钟可以从这5种频率种选择。具体如何设置和选择请参看2440的技术手册

下面来说下S3C2440的看门狗定时器:

WATCHDOG定时器可以像一般16定时器一样产生周期性中断,也可以用于发出复位信号以重启失常的系统。

这里写图片描述

从上图可以PCLK经过8位预分频后,也是有4种分频可以选择的,都是WTCON寄存器来控制
WTCNT寄存器按照工作频率减1计数,到达0时,可以产生中断信号。第一次使用WATCHDOGD定时器时,需要往WTCNT寄存器中写入初始计数值,以后计数值到达0后时自动从WATDAT寄存器中装入,重新进入下一个周期。

下面以程序重点讲下MPLL的使用

#define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))/* * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV * 有如下计算公式: *  S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s) *  S3C2410: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s) *  其中: m = MDIV + 8, p = PDIV + 2, s = SDIV * 对于本开发板,Fin = 12MHz * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4, * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */void clock_init(void){    // LOCKTIME = 0x00ffffff;   // 使用默认值即可    CLKDIVN  = 0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1    /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus 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"        /* 写入控制寄存器 */    );    /* 判断是S3C2410还是S3C2440 */    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))    {        MPLLCON = S3C2410_MPLL_200MHZ;  /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */    }    else    {        MPLLCON = S3C2440_MPLL_200MHZ;  /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */    }       }

设置完成时钟以后,就可以用新的HCLK来初始化SDRAM,初始化定时器了。