|
想用 timer3 实现 定时器的功能,自己去设置了几个寄存器之后,发现定时器完全没有启动。刚刚学习 TQ3358,对板子还不是和了解,希望有前辈可以帮忙一下。以下是代码清单:
#define TIMER3_IRQ_3358 69
#define TIMER0_BASE 0x44E05000
#define TIMER2_BASE 0x48040000
#define TIMER3_BASE 0x48042000 // 定时器基地址
#define CM_PER 0x44E00000 // clock management
#define CM_DPLL 0x44E00500 // 锁相环,用于倍频
#define CM_WKUP 0x44E0_0400 // Clock Module Wakeup Registers
volatile unsigned long * IRQWAKEEN = NULL;
volatile unsigned long * IRQENABLE_SET = NULL;
volatile unsigned long * IRQENABLE_CLR = NULL;
volatile unsigned long * IRQSTATUS = NULL;
volatile unsigned long * CM_PER_TIMER3_CLKCTRL = NULL;
volatile unsigned long * CLKSEL_TIMER3_CLK = NULL;
volatile unsigned long * TIMET3_TLDR = NULL;
volatile unsigned long * TIMER3_TCLR = NULL;
#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio))
static int timer_init(void);
long motor_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
printk("%s,%d \n",__FUNCTION__,__LINE__);
switch (cmd){
case 0:
printk("cmd = %d\n", cmd);
break;
case 1:
printk("cmd = %d\n", cmd);
break;
}
return 0;
}
/*
* motor open routine.
* do nothing.
*/
int motor_open(struct inode * inode, struct file * file)
{
int ret;
// 1、检测 GPIO 的合法性
ret = gpio_is_valid(GPIO_TO_PIN(1,16));
if(ret < 0) {
printk("failed gpio_is_valid GPIO_TO_PIN(1,16) \n");
return ret;
}
else
printk("valid OK\n");
// 2、注册/申请 GPIO
ret = gpio_request(GPIO_TO_PIN(1, 16),"GPIO_OUT");
if(ret < 0) {
printk("failed gpio_request GPIO_TO_PIN(1,16)\n");
return ret;
}
else
printk("request gpio GPIO_TO_PIN(1,16) OK \n");
// 3、设置为输出,且设置为低电平
gpio_direction_output(GPIO_TO_PIN(1, 16), 0);
if(ret < 0) {
printk("failed gpio_direction_output GPIO_TO_PIN(1,16)\n");
return ret;
}
else
printk("gpio_direction_output(GPIO_TO_PIN(1, 16), 0) OK\n");
// 4、设置 GPIO 为高电平
gpio_set_value(GPIO_TO_PIN(1, 16), 1);
// 定时器 初始化
timer_init();
return 0;
}
/*
* motor close routine.
* do nothing.
*/
int motor_close(struct inode * inode, struct file * file)
{
return 0;
}
int motor_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}
/*
* The various file operations we support.
*/
static struct file_operations motor_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = motor_ioctl,
.open = motor_open,
.write = motor_write,
.release = motor_close
};
static struct miscdevice motor_dev = {
MISC_DYNAMIC_MINOR,
"gpio_motor",
&motor_fops,
};
static irqreturn_t timer_interrupt(int irq,void * dev_id)
{
int step = 0;
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 4097,capture、overflow、match 三种,都是什么定时器
// 当中断发生的时候,就清除中断,
if ( (readl(IRQSTATUS)) & 0x2 ){
// 200 us 到了
writel(~0, IRQENABLE_CLR); // 4099
count++;
step++;
}
gpio_set_value(GPIO_TO_PIN(1, 16), 1);
if( count == 2){
gpio_set_value(GPIO_TO_PIN(1, 16), 0);
count = 0;
}
// 中断函数处理完毕
return IRQ_HANDLED;
}
// 硬件定时器的初始化
// 定时器选用 timer0,timer0 指定了时钟只能是 32KHz
static int timer_init(void)
{
unsigned int val;
int ret;
printk("%s,%d\n",__FUNCTION__,__LINE__);
// timer3 936 开启时钟模式
// 1、允许我们去访问寄存器 ,// CM_PER_TIMER3_CLKCTRL
val = 0x02;
writel(val, CM_PER_TIMER3_CLKCTRL);
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 2、关闭定时器
val = 0x00;
writel(val, TIMER3_TCLR);
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 3、选择、设置、时钟,选择为 32 KHz, // 1035,
val = 0x02;
writel(val, CLKSEL_TIMER3_CLK);
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 4、装载初值 4104,也就是说,周期是 31.25 微秒
// 32 KHz == 0.03125 * 10(-3) 毫秒, 那么 200 us -->> 200 / 31.25= 6.4
// 4104 ,故意设置为 1 S,6.4 X = 1 000 000 ,X->> 32 000
// 这个步骤要不要,貌似应该不用装载了吧,
writel(32000, TIMET3_TLDR); // timer load register,完成数值的加载,
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 4100,中断唤醒使能,
val = 0;
val |= ((1<<2) | (1<<1) | (1<<0));
writel(val, IRQWAKEEN);
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 中断使能 4098
val = 0;
val |= (1<<1); //((1<<2) | (1<<1) | (1<<0));
writel(val, IRQENABLE_SET);
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 5、定时器开始, 4101
val = 0x03;
writel(val, TIMER3_TCLR);
printk("%s,%d\n",__FUNCTION__,__LINE__);
// 注册中断,213
ret=request_irq(TIMER3_IRQ_3358,timer_interrupt,IRQF_SHARED,TIMER_NAME,(void*)&key_event);
if(ret<0)
{
printk("IRQ %d can not request,ret = %d \n",TIMER3_IRQ_3358,ret);
return ret;
}
printk("%s,%d\n",__FUNCTION__,__LINE__);
return 0;
}
static int __init motor_init(void)
{
int ret = 0;
//
//WKUP_TIMER0_CLKCTR = (volatile unsigned long *)ioremap(TIMER2_BASE + 0x10, 4);
// 1、 时钟的使能,936
// 1、 时钟的使能,936
CM_PER_TIMER3_CLKCTRL = (volatile unsigned long *)ioremap(CM_PER + 0x84, 4);
// 定时器的开关 4101
TIMER3_TCLR = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x38, 4);
// 设置时钟,
CLKSEL_TIMER3_CLK =(volatile unsigned long *)ioremap(CM_DPLL + 0x0c, 4);
// 装载 ,要不要
TIMET3_TLDR = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x40, 4);
// 中断请求
IRQWAKEEN = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x34, 4);
// 中断设置
IRQENABLE_SET = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x2c, 4);
IRQSTATUS = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x28, 4);
IRQENABLE_CLR = (volatile unsigned long *)ioremap(TIMER3_BASE + 0x30, 4);
key_event.state = KEY_NONE;
ret = misc_register(&motor_dev);
if(ret)
{
DBG("could not register gpio devices. \n");
return ret;
}
printk("gpio motor driver insmod successful!\n");
return ret;
}
static void __exit motor_exit(void)
{
misc_deregister(&motor_dev);
//free_irq(IRQ_GPIO9, (void*)&key_event);
free_irq(TIMER3_IRQ_3358,(void*)&key_event);
gpio_free(GPIO_TO_PIN(1, 16));
printk("gpio driver exit successful!\n");
}
module_init(motor_init);
module_exit(motor_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("carlos"); |
|