我写了一个linux设备驱动来学习远程控制的红外编码。
XINT0(GPIOF0)用于接收红外二极管发出的信号。 Timer0用于在XINT0中断处理程序中进行计数,记录高电平和低电平的周期。
GPIO和Timer的配置合适。 TCNTB中Timer0的初始值为50000,有时电压电平周期是正确的,但有时TCNT0的观察值为50000,这表明定时器工作不正常。
在每个中断循环中,观察值打印如下。
<4>current observation value: 49786
<4>current observation value: 49702
<4>current observation value: 50000
<4>current observation value: 49969
<4>current observation value: 50000
<4>current observation value: 49996
<4>current observation value: 50000
<4>current observation value: 49998
<4>current observation value: 47827
<4>current observation value: 49392
<4>current observation value: 49906
<4>current observation value: 50000
<4>current observation value: 49970
<4>current observation value: 50000
<4>current observation value: 49997
<4>current observation value: 50000
<4>current observation value: 49998
<4>current observation value: 50000
代码如下:
static irqreturn_t gpio_study_irq_handler(int irq, void *wbuf)
{
unsigned int *buf=(unsigned int *)wbuf;
unsigned int temp;
if(0==IrDA_cnt){
timer_setup(&Study_Timer,MAX_CODE_WIDTH);
timer_on(&Study_Timer);
IrDA_cnt++;
return IRQ_RETVAL(IRQ_HANDLED);
}
temp=ioread32(Study_Timer.tcnto);
timer_off(&Study_Timer);
printk("current observation value: %d\n",temp);
*(buf+IrDA_cnt-1)=MAX_CODE_WIDTH-read_timer_cnt(&Study_Timer);
iowrite32(MAX_CODE_WIDTH,Study_Timer.tcntb);
temp=ioread32(Study_Timer.tcon);
iowrite32(temp|0x02,Study_Timer.tcon);
temp=ioread32(Study_Timer.tcon);
iowrite32(temp&(~0x02),Study_Timer.tcon);
timer_on(&Study_Timer);
IrDA_cnt++;
if(IrDA_cnt > CODE_MAX_LEN)
{
wake_up_interruptible(&IrDA_Study_Queue);
return IRQ_RETVAL(IRQ_HANDLED);
}
return IRQ_RETVAL(IRQ_HANDLED);
}
最佳答案
系统函数printk在IRQ服务处理程序中占用了太多时间。最后定时器打开时,中断请求到来,导致观测值恒定。
关于c - 基于S3C2440的linux设备驱动的定时器计数误差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25518427/