学习uboot前奏之hardware-clock[s3c2440]
本节我们来讲下嵌入式系统中时钟的概念,时钟为系统工作提供了基本的时间秩序。作为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,初始化定时器了。