分类: LINUX
2014-04-26 18:52:03
原文地址:(九)、时钟与定时器 作者:machoe
主频的确是CPU的性能的重要参数。但主频并不代表CPU的运算速度,这里是很容易让人误解的,现在很多人都认为主频越高,CPU的运算速度越快,其实不然,主频和运算速度没有直接关系。有兴趣的读者请看推荐阅读部分。
本章,我们来学习一下ARM的时钟和定时器。
、基本概念介绍S3C2440芯片控制逻辑即可以外接晶振,然后通过内部电路产生时钟源;也可以直接使用外部提供的时钟源,它们通过引脚的设置来选择。时钟控制逻辑给整个芯片提供3种时钟:FCLK用于CPU核;HCLK用于AHB总线上的设备,如CPU核、存储器控制器、中断控制器、LCD控制器、DMA和USB主机模块等;PCLK用于APB总线上的设备,比如WATCHDOG、IIS、IIC、PWM定时器、MMC接口、ADC、UART、GPIO、RTC和SPI。
AHB:Advanced High performancs Bus.
APB:Advanced Peripheral Bus.
S3C2440 CPU核的工作电压为1.2V时,主频可以达到300MHz;工作电压为1.3V时,主频可以达到400MHz.
S3C2440有两个PLL(锁相环):MPLL和UPLL。其中MPLL用于HCLK、FCLK、PCLK。UPLL专用于USB设备。
、时钟初始化的过程上电时,PLL没有被启动,FCLK等于外部输入时钟,Fin。若要提高系统时钟,需要软件来启动PLL,为了提高系统的性能,应尽快设置好时钟。下图为启动过程:
1、 上电几毫秒后,晶振(OSC)输出稳定,FCLK=Fin(晶振频率),nRESET信号恢复高电平后,CPU开始执行指令。
2、 为了使程序效率提高,就在程序的开始处尽快设置好时钟,需设置MPLL寄存器,待设置好后需要等待一段时间(Lock Time),MPLL的输出才会稳定。在这段时间内FCLK停振,CPU不工作。Lock Time的长短由寄存器LOCKTIME决定。
3、 经过Lock Time之后,MPLL输出稳定,CPU在新的FCLK下开始工作。
、FCLK、HCLK和PCLKFCLK、HCLK、PCLK三者的比例是可以改变的,设置它们三者的比例,需要设置S3C2440的4个配置寄存器。
1、 LOCKTIME寄存器:用于设置Lock Time时间的长度。一般采取默认即可。
2、 MPLLCON寄存器:用于设置FCLK与Fin的倍数。
位[19:12]的值为MDIV,位[9:4]的值为PDIV,位[1:0]的值为SDIV。其中计算公式如下 :
3、 CLKDIVN寄存器:用于设置FCLK、HCLK、PCLK三者的比例。具体内容如下:
4、
CAMDIVN寄存器:用于设置Camera的时钟比例,但也会影响其它时钟的比例,一般默认即可。为了方便配置,下面列出各时钟比例选择表:
注意:
如果HDIVN的值非0,CPU的总线应从“fast bus mode”变为“asynchronous bus mode”。如果HDIVN的值非0,并且仍然工作在fast bus mode,则CPU是以HCLK为时钟输入工作。大家可以利用这个特性在不改变HCLK和PCLK的情况下,改变CPU的频率。
注意:S3C2440不支持“synchronous bus mode”。
总线从“fast bus mode”变为“asynchronous bus mode”的指令如下:
MMU_SetAsyncBusMode
mrc p15,0,r0,c1,c0,0
orr r0,r0,#R1_nF:OR:R1_iA
mcr p15,0,r0,c1,c0,0
PWM定时器S3C2440有5个16位的定时器,其中定时器0、1、2、3具有PWM(Pulse Width Modulation)功能,即们它们都有一个输出引脚,可以通过定时器来控制引脚周期性的高、低电平变化;定时器4没有输出引脚。
定时器部件的时钟源为PCLK,首先通过2个8位的预分频器降低频率:定时器0、1共用第一个,
定时器2,3,4共用第二个预分频器。预分频器的输出将进入第二级分频器,它们输出5种频率的时钟:2分频、4分频、8分频、16分频或者是外部时钟TCLK0/TCLK1。 结构图如下图:
1、 TCFG0寄存器
[7:0]和[15:8]分别用于控制预分频器0、1的prescaler value,经过预分频器出来的时钟为:PCLK/(prescaler value +1)。
2、 TCFG1寄存器
经过预分频器得到的时钟将被2分频、4分频、8分频、16分频或者是外部时钟TCLK0/TCLK1。其中定时器0,1外接TCLK0,定时器2、3、4接TCLK1。该寄存器用来设置5个定时器工作在哪个频率中。这样,定时器n的工作频率要么是外接的TCLK0/TCLK1,要么可以用下面的公式计算:
工作频率= PCLK/(prescaler value +1)/(divider value)
其中:prescaler value=0~255;
divider value=2,4,8,16
3、 TCNTBn/TCMPBn寄存器(COUNT BUFFER REGISTER/COMPARE BUFFER REGISTER)
n只是0-4。TCNTBn中保存定时器的初始计数值,TCMPBn中保存比较值。它们的值在启动定时器时,被传到定时器TCNTn、TCMPn中。
注意:没有TCMPB4,因为定时器4没有输出个脚。
4、 TCNTOn寄存器
n为0-4,定时器n被启动后,内部寄存器TCNTn在不断减1,这时可以读TCNTOn取出当前的值。
5、 TCON寄存器
其中每4个位决定一个定时器。具体功能如下表,以定时器0为例:
功 能 |
位 |
设 置 |
自动加载 |
3 |
0:不自动加载; 1:在定时器0计数到达0时,TCNTBn/TCMPBn寄存器的值自动装入内部寄存器TCNTn、TCMPn。 |
输出反转 |
2 |
0:TOUT0不反转;1:TOUT0反转。 |
手动更新 |
1 |
0:无用; 1:将TCNTBn/TCMPBn寄存器的值装入内部寄存器TCNTn、TCMPn中。 |
开启/停止 |
0 |
0:停止定时器0;1:开启定时器0 |
在第一次使用定时器时,需要设置“手动更新”位为1以使TCNTBn/TCMPBn寄存器的值装入内部寄存器TCNTn、TCMPn中,如果下一次还要使用该位,需要先将它清0。
、定时器的工作过程1、程序初始,设置TCMPBn、TCNTBn这两个寄存器,它们表示定时器n的比较值、初始计数值。
2、启动定时器,这时TCMPBn、TCNTBn的值将被装入其内部的寄存器TCMPn、TCNTn中。这时,定时器n在工作频率下,TCNTn开始减1计数,其值可以通过TCNTOn寄存器读出。
3、当TCNTn的值等于TCMPn的值时,定时器的输出管脚TOUTn反转;TCNTn继续减1计数。
4、当TCNTn的值到达0时,如果在TCON寄存器中将定时器n设为“自动装载”,则TCMPBn和TCNTBn寄存器的值被自动装入TCMPn和TCNTn寄存器中,下一个计数流程开始。
通过设置TCMPBn、TCNTBn的值可以设置管脚TOUTn输出信号的占空比,这就是所谓的可调制脉冲(PWM)。
WATCHDOG定时器看门狗定时器可以像一般的16位定时器一样用于产生中断,也可以用于发出复位信号以重启失常的系统。它的结构和PWM定时器类似,它的8位预分频器将PCLK分频后,被再次分频得到4种频率:16分频、32分频、64分频、128分频。WTCNT寄存器按照工作频率不断减1,当达到0时,可以产生中断信号,可以输出复位信号。在第一次使用WATCHDOG定时器时,需要往WTCNT寄存器中写入初始计数值,以后在计数值到达0时自动从WATDAT寄存器中装入,重新开始下一个计数周期。
使用WATCHDOG定时器时,在正常的程序中,必须不断的重新设置WTCNT寄存器使得它不为0,这样可以保证系统不被重启,这个过程就称为“喂狗”。当程序崩溃时,不能正常“喂狗”,计数值达到0后系统将被重启,这样程序将重新运行。
看门狗定时器由3个寄存器控制,WTCON寄存器、WTDAT寄存器、WTCNT寄存器。这三个寄存器的功能和PWM很类似,请读者自行参考手册进行学习。
本章程序由head.S init.c interrupt.c interrupt.h main.c s3c24xx.h Makefile timer.lds等文件组成。其中入口程序为head.S,本章程序和前几章十分相似,只是增加了时钟模块和定时器模块。
程序首先设置栈指针,然后调用禁看门狗程序、初始化时钟、初始化SDRAM、代码搬运、初始化LED、初始化定时器、初始化并打开中断。其子程序均在init.c interrupt.c文件中实现。
这里要注意的是当初始化时钟后,SDRAM的自刷新寄存器的值有所变化,具体的,我已经程序中注释,请查看。
make后,将生成的BIN文件烧到TQ2440后,可以看到LED 1S闪烁一次。再将head.S中对clock_init函数调用去掉,并重新设置SDRAM的REFRESH寄存器,可以看见LED闪烁的频率要慢得多。
现在大家应该明白了,为什么在U-BOOT下直接烧到SDRAM中运行LEDS的程序,速度最快,因为U-BOOT已经帮我们初始化了时钟。
1.韦东山 《嵌入式LINUX应用开发完全手册》
2.三星 《S3C2440手册》
3.