Chinaunix首页 | 论坛 | 博客
  • 博客访问: 132373
  • 博文数量: 64
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-26 18:44
文章分类

全部博文(64)

文章存档

2014年(64)

我的朋友

分类: LINUX

2014-04-26 18:52:03

原文地址:(九)、时钟与定时器 作者:machoe

    对于CPU来说,有一个很重要的指标,这个指标也成为了很多人对CPU的唯一要求,那就是主频,也就是CPU的工作时钟频率(内部脉冲振荡速度)。现在很多人去电脑城配电脑时,都想要CPU主频高的,那么CPU的主频到底是什么东西呢?是不是主频越高,速度越快呢?

主频的确是CPU的性能的重要参数。但主频并不代表CPU的运算速度,这里是很容易让人误解的,现在很多人都认为主频越高,CPU的运算速度越快,其实不然,主频和运算速度没有直接关系。有兴趣的读者请看推荐阅读部分。

本章,我们来学习一下ARM的时钟和定时器。 

、基本概念介绍

S3C2440芯片控制逻辑即可以外接晶振,然后通过内部电路产生时钟源;也可以直接使用外部提供的时钟源,它们通过引脚的设置来选择。时钟控制逻辑给整个芯片提供3种时钟:FCLK用于CPU核;HCLK用于AHB总线上的设备,如CPU核、存储器控制器、中断控制器、LCD控制器、DMAUSB主机模块等;PCLK用于APB总线上的设备,比如WATCHDOGIISIICPWM定时器、MMC接口、ADCUARTGPIORTCSPI

AHBAdvanced High performancs Bus.

APBAdvanced Peripheral Bus.

S3C2440  CPU核的工作电压为1.2V时,主频可以达到300MHz;工作电压为1.3V时,主频可以达到400MHz.

S3C2440有两个PLL(锁相环):MPLLUPLL。其中MPLL用于HCLKFCLKPCLKUPLL专用于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下开始工作。

FCLKHCLKPCLK

FCLKHCLKPCLK三者的比例是可以改变的,设置它们三者的比例,需要设置S3C24404个配置寄存器。

1、 LOCKTIME寄存器:用于设置Lock Time时间的长度。一般采取默认即可。

2、 MPLLCON寄存器:用于设置FCLKFin的倍数。

[1912]的值为MDIV,位[94]的值为PDIV,位[10]的值为SDIV。其中计算公式如下 :

3、  CLKDIVN寄存器:用于设置FCLKHCLKPCLK三者的比例。具体内容如下:

(this.width>500)this.width=500;">

4、 

CAMDIVN寄存器:用于设置Camera的时钟比例,但也会影响其它时钟的比例,一般默认即可。

为了方便配置,下面列出各时钟比例选择表:

注意:

    如果HDIVN的值非0CPU的总线应从“fast bus mode”变为“asynchronous bus mode”。如果HDIVN的值非0,并且仍然工作在fast bus mode,则CPU是以HCLK为时钟输入工作。大家可以利用这个特性在不改变HCLKPCLK的情况下,改变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定时器

S3C2440516位的定时器,其中定时器0123具有PWMPulse Width Modulation)功能,即们它们都有一个输出引脚,可以通过定时器来控制引脚周期性的高、低电平变化;定时器4没有输出引脚。

定时器部件的时钟源为PCLK,首先通过28位的预分频器降低频率:定时器01共用第一个,

定时器234共用第二个预分频器。预分频器的输出将进入第二级分频器,它们输出5种频率的时钟:2分频、4分频、8分频、16分频或者是外部时钟TCLK0/TCLK1

结构图如下图:

1、 TCFG0寄存器

[70][158]分别用于控制预分频器01prescaler value,经过预分频器出来的时钟为:PCLK/(prescaler value +1)

2、 TCFG1寄存器

经过预分频器得到的时钟将被2分频、4分频、8分频、16分频或者是外部时钟TCLK0/TCLK1。其中定时器01外接TCLK0,定时器234TCLK1。该寄存器用来设置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-4TCNTBn中保存定时器的初始计数值,TCMPBn中保存比较值。它们的值在启动定时器时,被传到定时器TCNTnTCMPn中。

注意:没有TCMPB4,因为定时器4没有输出个脚。

4、 TCNTOn寄存器

n0-4,定时器n被启动后,内部寄存器TCNTn在不断减1,这时可以读TCNTOn取出当前的值。

5、 TCON寄存器

其中每4个位决定一个定时器。具体功能如下表,以定时器0为例:

 

  

自动加载

3

0:不自动加载;

1:在定时器0计数到达0时,TCNTBn/TCMPBn寄存器的值自动装入内部寄存器TCNTnTCMPn

输出反转

2

0TOUT0不反转;1TOUT0反转。

手动更新

1

0:无用;

1:将TCNTBn/TCMPBn寄存器的值装入内部寄存器TCNTnTCMPn中。

开启/停止

0

0:停止定时器01:开启定时器0

  在第一次使用定时器时,需要设置“手动更新”位为1以使TCNTBn/TCMPBn寄存器的值装入内部寄存器TCNTnTCMPn中,如果下一次还要使用该位,需要先将它清0

、定时器的工作过程

1、程序初始,设置TCMPBnTCNTBn这两个寄存器,它们表示定时器n的比较值、初始计数值。

2、启动定时器,这时TCMPBnTCNTBn的值将被装入其内部的寄存器TCMPnTCNTn中。这时,定时器n在工作频率下,TCNTn开始减1计数,其值可以通过TCNTOn寄存器读出。

3、当TCNTn的值等于TCMPn的值时,定时器的输出管脚TOUTn反转;TCNTn继续减1计数。

4、当TCNTn的值到达0时,如果在TCON寄存器中将定时器n设为“自动装载”,则TCMPBnTCNTBn寄存器的值被自动装入TCMPnTCNTn寄存器中,下一个计数流程开始。

通过设置TCMPBnTCNTBn的值可以设置管脚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函数调用去掉,并重新设置SDRAMREFRESH寄存器,可以看见LED闪烁的频率要慢得多。

现在大家应该明白了,为什么在U-BOOT下直接烧到SDRAM中运行LEDS的程序,速度最快,因为U-BOOT已经帮我们初始化了时钟。

1.韦东山 《嵌入式LINUX应用开发完全手册》

2.三星  《S3C2440手册》

3.

 

阅读(1093) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~