lzj13151558266 发表于 2011-1-21 21:15:12

tq2440裸奔程序4-系统时钟与定时器中断

第三章 系统时钟和定时器
第一节系统时钟
S3c2440的时钟控制逻辑即可接外接晶振,然后通过内部电路产生时钟源,也可直接使用外部提供的时钟源,时钟控制逻辑给整个芯片提供3种时钟,FCLK用于CPU核,HCLK用于AHB总线上的,比如存储控制器、中断控制器、LCD控制器,DMA和USB主机模块,PCLK用于APB总线上的设备,比如WATCHDOG、IIS、I2C等
S3c2440CPU核工作电压为1.2V时,主频可达200M,工作电压为2.0V时,主频可达400m,为降低电磁干扰,降低板间布线的要求,外接频率通常很低,一般外接12M。
S3c2440有两个PLL,MPLL和UPLL,UPLL专用于USB设备,MPLL用于设置FCLK、HCLK、PLCK。
时钟过程:
上电后,PLL未启用,此时CPU频率为外接频率Fin=12m,nRESET信号恢复高电平,CPU开始执行指令。
当程序启用MPLL时,即设置MPLL寄存器后,需要一段等待时间(lock time),MPLL才能稳定输出,在该时间段内,      FCLK停振,CPU停止工作,lock time时间由寄存器LOCKTIME设定。
lock time时间后,MPLL输出正常,CPU工作在新的FCLK下。
FCLK、HCLK、PCLK的比例为可调,可以通过寄存器设置它们的比例。

通过对以下寄存器的设置,可以确定系统时钟。
LOCKTIME:用于设置lock time时间,其中位用于UPLL,用于MPLL,一般而言,使用它的默认值即可,S3C2440中的默认值为0xffffffff
MPLLCON:用于设置FCLK与外接频率Fin的倍数。值位值称MDIV,位值称PDIV,位值称SDIV,FCLK与Fin之间有如下计算公式。
MPLL(FCLK)=(2*(MDIV+8)*Fin)/((PDIV+2)*2^SDIV)
可令MDIV=92 PDIV=1 SDIV=1,则FCLK=400M
MPLLCON=0x5c<<12+0x1<<4+0x1
CLKDIVN:用于设置FCLK\HCLK\PCLK三者的比例。对于S3C2440而言,还需设置一个寄存器CAMDIVN。对CLKDIVN而言,为HDIVN,为PDIVN
HCLK4_HALF\HCLK3_HALF分别为CAMDIVN的位和。
在本程序中,我们设置其比例为1:4:8即 MPLL=400M HCLK=100M FCLK=50M
刚其值为0x2<<1+0x1=0x5
如果HDIVN非0,CPU总线模式应从“fast bus mode”变为“asynchronous bus mode”,否则CPU的工作频率将自动变为HCLK而不是FCLK。
因此改变时钟频率代码如下:
;改变总线模式
mrc p15,0,r0,c1,c0,0      
orr r0 ,r0,#0xc000000      
mcr p15,0,r0,c1,c0,0

ldr r0,=LOCKTIME            ;设置LOCK频率改变时的锁定时间
ldr r1,=0xfffffff
str r1,

;FCLK=(2*(92+8)*12)/((1+2)*2^1)=400M
ldr r0,=MPLLCON            
ldr r1,=(0x5c<<12+0x1<<4+0x1)
str r1,
;HCLK=1:4=100M FCLK=1:8=50M
ldr r0,=CLKDIVN            
ldr r1,=(0x2<<1+0x1)               
str r1,

第二节PWM定时器
S3C2440具有5个16位的定时器。其中0:3有输出引脚功能,可通过定时器来控制引起周期性的高、低电平变化,
定时器部件的时钟源为PCLK(本例中为50M),首先通过两个8位预分频降低频率,预分频器的输出进入第二个分频器,输出5种频率时钟即2、4、8、16分频和外接时钟。
定时器内部控制逻辑:
1、程序初设TCMPBn、TCNTBn两相寄存器,它们表示定时器n的比较值和初始值。
2、随之设置TCON寄存器启动定时器n,这是TCMPBn、TCNTBn的值将被装入内部寄存器。在定时器n的工作频率下,TCNTn开始减1计数。其值可以读取TCNTOn寄存器得知。
3、当TCMPn、TCNTn值相等时,定时器输出管脚TOUTn反转,TCNTn继续减1计数。
4、当TCNTn值为0时,定时器输出管脚TOUTn再次反转,并产生中断。如TCON寄存器中将定时器设为自动加载,则TCMPBn、TCNTBn的值将被装入内部寄存器,则下一轮计算开始。
定时器寄存器设置
1、TCFG0:、分别控制预分频器0,1,其值范围为0-255。
2、TCFG1:经过预分频的时钟将被2、4、8、16分频或按外部时钟TCLK1上
经过分频后,定时器频为
定时器频率=PCLK/(prescalser value+1)/()
    其中:prescalser value=0-255
divider value=2、4、8、16
3、      TCNTBn/TCMPBn:设置定时器n的初始值和比较值,只用了位。
4、      TCNTOn:定时器n启动后,其内容计数值可通过读取该寄存器得知。
5、      TCON:用于控制定时器的启动、停止、信号反转等
   第一次启动定时器n将手动加载TCNTBn/TCMPBn的值到内部寄存器
   启动、停止定时器n
       定时器n计算结束时是否自动加载
   决定定时器n输出信号TOUTn是否反转
   TCON寄存器分别控制0-4定时器
   每个定时器控制位如下:
   0:0停止1启用
   1:0保留1将TCNTBn/TCMPBn的值手动加载至内部寄存器
   2:0TOUTn不反转1TOUTn反转
   3:0不自动加载1自动加载TCNTBn/TCMPBn的值至内部寄存器
如图可以表示:
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_612692UD9A7L.jpg
(原文件名:定时器.jpg)

可见,要启用一个定时器
1设置TCFG0和TCFG1的值,确定定时器频率
   2设置TCMPBn和TCNTBn的初值
   3手动加载
   4确定信号是否反转、是否自动加载,开始启用或停止定时器
定时器0中断(每0.5秒产生一次中断)
硬件说明:INT_TIMER0为第10位中断
主要程序说明:
;设置定时器频率
ldr r0,=TCFG0
ldr r1,=99
str r1,
      
ldr r0,=TCFG1;16分频
ldr r1,=0x03   
str r1,
      ;设置定时器初始值
现在我们来看看定时器的的初始值是如何得来的,我们要求0.5s产生一次中断,
定时器频率为50M/(99+1)/16=31250hz,那么每一次计数所需时间为1000ms/31250。0.5s=500ms时间可以计数次数为500ms/(1000ms/31250)=31250/2=15625

ldr r0,=TCNTB0
ldr r1,=15625
str r1,
      ;手动加载
ldr r0,=TCON
ldr r1,=2
str r1,      
;开启定时器中断
ldr      r0,=INTMSK      ;开启定时器0,,
ldr      r1,=0xfffffbff
str      r1,

ldr r0,=TCON
ldr r1,=0x9         ;开启定时器并自动加载
str r1,      

特别注意:
在程序中,我们定义了一个变量T_Flag并用以下指令进行读取:
T_Flag DCD 0
Ldr r0,=T_Flag;得到变量的地址
Ldr r1,      ;得到变量的值r1=T_Flag
Str r1,   ;将r1的值给变量T_Flag=r1
在此需要说明的是:根据反汇编程序我们得知,对变量T_Flag编译器分配了两个地址空间,一个为变量数据0存放的空间,另一个是指向存放数据0的地址。而指向存放数据0的地址地址由编译器根据RO决定,是一个绝对地址值,因此,当我们用默认RO=0X30000000时,其地址为0X30000???显然,我们将其下载到NAND中运行时,程序将无法正确到0X00000???读取T_Flag的初始值0。在第一章我们讨论LDR PC,XXXX指令的情况是相同的情况,故在使此类指令时应特别注意。
点击此处下载 ourdev_612693WPAUW8.rar(文件大小:16K) (原文件名:Time.rar)

LK9286 发表于 2012-1-12 00:52:49

mark

maimaige 发表于 2013-12-11 22:59:24

楼主,你好,汇编很牛啊,tq2440 系列文章,有后续吗
页: [1]
查看完整版本: tq2440裸奔程序4-系统时钟与定时器中断