uboot中timer定时器的设置(二)

2014-11-24 07:13:30 · 作者: · 浏览: 3
都有外部引脚引出,而第五个timer4不同与他们,第一个就是它没有TCMPB寄存器,具体的区别可以看看这个文档或是datasheet:
2、s3c24x0_get_base_timers()函数返回的就是timer寄存器空间的起始地址0x51000000
[cpp]
static inline struct s3c24x0_timers *s3c24x0_get_base_timers(void)
{
return (struct s3c24x0_timers *)S3C24X0_TIMER_BASE;
}
3、
[cpp]
/* use PWM Timer 4 because it has no output */
/* prescaler for Timer 4 is 16 */
这个注释是不是有问题呢,我怎么查不到timer4预分频器是16位的,都是8位。是不是要表达计数器是16位的呢?
4、writel(0x0ff,&timers->TCFG0)的作用是什么呢?在arch/arm/include/asm/io.h文件中既然有3处定义了这个函数,考察了一下只有下面被编译:
[cpp]
#define writel(v,a) __arch_putl(v,a)
[cpp]
#define __arch_putl(v,a) (*(volatile unsigned int *)(a) = (v))
分析:就是往a寄存器写入v.
这里就是往寄存器TCFG0写入0x0ff,先看下TCFG0寄存器信息:
将timer0、1的预分频器的值写ff就是255,
其值N为: 0~255
输出频率为:PCLK ÷(N+1)
这时候N = 255,结合这篇文档http://blog.csdn.net/sonbai/article/details/8687858知道PCLK的频率是101.25MHz,输出频率就出来了,这时候最低,同时没有用到他们,所以不考虑了。t只考虑imer4,这时候N = 0,输出频率最大就是PCLK。为什么要设最大,先放着
5、timer_load_val是一个全局变量,顾名思义它是装入TCNTB4寄存器的值。看下面的注释:
[cpp]
/*
* for 10 ms clock period @ PCLK with 4 bit divider = 1/2
* (default) and prescaler = 16. Should be 10390
* @33.25MHz and 15625 @ 50 MHz
*/
它的意思是如果要将timer4的时钟周期设置为10ms的话,要通过PCLK、分配器divider默认的值1/2和prescaler = 16来设置如何设置(?)来看一下下面这个函数
[cpp]
/* return PCLK frequency */
ulong get_PCLK(void)
{
struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
return (readl(&clk_power->CLKDIVN) & 1) get_HCLK() / 2 : get_HCLK();
}
看看结构s3c24x0_clock_power
[cpp]
/* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */
/* (see S3C2410 manual chapter 7) */
struct s3c24x0_clock_power {
u32 LOCKTIME;
u32 MPLLCON;
u32 UPLLCON;
u32 CLKCON;
u32 CLKSLOW;
u32 CLKDIVN;
#if defined(CONFIG_S3C2440)
U32 CAMDIVN;
#endif
};
涵盖了所有时钟设置的寄存器,s3c24x0_get_base_clock_power();返回的是(struct s3c24x0_clock_power *)0x4C000000也就是时钟设置寄存器的起始地址
[cpp]
return (readl(&clk_power->CLKDIVN) & 1) get_HCLK() / 2 : get_HCLK();
判断一下CLKDIVN是不是被设置成了1,如果是说明PCLK = 1/2HCLK,不在去看get_HCLK了。前面我已经说过PCLK = 101.25MHz,至于timer_load_val = 101.25MHz / (2*16*100);这个公式,分析如下:
我们要设置timer4的时钟周期是T = 10ms;
又 T = [1 /(PCLK / (预分频器的值(prescaler)*分频器的值(div)))] *timer_load_val
已知T、PCLK、perscaler、div,就可以求的
timer_load_val = PCLK / (perscaler * div)
但是这里为什么会有100呢?(暂时不清楚,望大家给我一个解释)
timer_clk下面暂时没有遇到,先不考虑。
6、
[cpp]
/* load value for 10 ms timeout */
lastdec = timer_load_val;
writel(timer_load_val, &timers->TCNTB4);
然后将timer_load_val的值写入TCNTB4寄存器中
7、下面是要配置TCON寄存器,也就是timer控制寄存器
[cpp]
/* auto load, manual update of Timer 4 */
tmr = (readl(&timers->TCON) & ~0x0700000) | 0x0600000;
writel(tmr, &timers->TCON);
先来看看TCON寄存器信息:
TCON现实与(~0x0700000)与运算,即TCON = TCON & F8FFFFF,也就是将TCON的20、21、21这几个位清零,然后TCON = TCON | 0X0600000将位21、20设置为1,对照datasheet知道将timer4设置为自动装载,和手动更新.这就有一个矛盾既然自动转载干嘛还要手动更新呢?看下8就知道了。writel()函数已经介绍过了。
8、你看下面这个代码就很有趣,他和上面的那个代码很类似
[cpp]
/* auto load, start Timer 4 */
tmr = (tmr & ~0x0700000) | 0x0500000;
writel(tmr, &timers->TCON);
起始2440定时器第一次往TCONTB装入初始值是要手动更新的,如果没有