- 论坛徽章:
- 0
|
这些天在做触摸屏驱动,编译通过后加载模块老是报错,经过加打印信息后,基本可以确定是在进行if(!pendown(ts))后,执行pendown(wm97xx_ts_t *ts)函数时有错误,应该是ts->codec->codec_read(ts->codec, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN 这句话有问题:ddddddddddd
CPU 0 Unable to handle kernel paging request at virtual address 00000028, epc == c006b70c, ra == c006b708
Oops[#1]:
Cpu 0
$ 0 : 00000000 10003c00 0000000f 00000001
$ 4 : 00000000 00001f8e 00001f8e 8050ced1
$ 8 : 00001f8e 00000034 00001f8e 80670000
$12 : 80670000 80670000 ffff7c00 ffffffff
$16 : c006e218 10003c01 8012ee0c c006b654
$20 : 80130000 00200200 00000001 80550000
$24 : ffffffdf 80361fe4
$28 : 8714c000 8714dbe8 806740ec c006b708
Hi : 000000fa
Lo : e1468c00
epc : c006b70c wm97xx_acq_timer+0xb8/0x3b4 [ac97_plugin_wm97xx]
Not tainted
ra : c006b708 wm97xx_acq_timer+0xb4/0x3b4 [ac97_plugin_wm97xx]
Status: 10003c03 KERNEL EXL IE
Cause : 00808408
BadVA : 00000028
PrId : 04030202 (Au1250)
Modules linked in: ac97_plugin_wm97xx(+)
Process insmod (pid: 879, threadinfo=8714c000, task=87144d70, tls=00000000)
Stack : 870168c8 00001f7f 00001f7f 8050ced1 08d4b80d 0000000a 80671a80 8714dc38
00000100 c006b654 805a0000 00200200 00000001 80550000 8013a758 8714dd84
8010a62c 00000033 fffffff1 87275740 8714dc38 8714dc38 00000040 00000100
80671938 00000004 0000000a 80670000 80134c10 ffff7fff 8714de0c 00000039
80160da8 80160d88 10003c01 80143870 10003c00 00000000 806714d1 3b9aca00
...
Call Trace:
[<c006b70c>] wm97xx_acq_timer+0xb8/0x3b4 [ac97_plugin_wm97xx]
[<8013a758>] run_timer_softirq+0x188/0x234
[<80134c10>] __do_softirq+0xb0/0x15c
[<80134d50>] do_softirq+0x94/0x9c
[<80100604>] ret_from_irq+0x0/0x4
[<8012ed44>] vprintk+0x368/0x430
[<8012ee30>] printk+0x24/0x30
[<c0071128>] wm97xx_ts_init_module+0x128/0x258 [ac97_plugin_wm97xx]
[<8010984c>] do_one_initcall+0x3c/0x1f4
[<8015d6a0>] sys_init_module+0xb0/0x1b8
[<80102390>] stack_done+0x20/0x3c
现把程序贴出来,求各位大神指点一个,怎么修改,万分感激!!
#include <linux/module.h>
#include <linux/version.h>
。。。。。。
struct ac97_codec {
// Linked list of codecs
struct list_head list;
// AC97 controller connected with
void *private_data;
char *name;
int id;
int dev_mixer;
int type;
u32 model;
int modem:1;
struct ac97_ops *codec_ops;
// controller specific lower leverl ac97 accessing routines.
// must be re-entrant safe
u16 (*codec_read) (struct ac97_codec *codec, u8 reg);
void (*codec_write) (struct ac97_codec *codec, u8 reg, u16 val);
// Wait for codec-ready. Ok to sleep here.
void (*codec_wait) (struct ac97_codec *codec);
// callback used by helper drivers for interesting ac97 setups
void (*codec_unregister) (struct ac97_codec *codec);
struct ac97_driver *driver;
void *driver_private; // Private data for the driver
spinlock_t lock;
// OSS mixer masks
int modcnt;
int supported_mixers;
int stereo_mixers;
int record_sources;
// Property flags
int flags;
int bit_resolution;
// OSS mixer interface
int (*read_mixer) (struct ac97_codec *codec, int oss_channel);
void (*write_mixer)(struct ac97_codec *codec, int oss_channel,
unsigned int left, unsigned int right);
int (*recmask_io) (struct ac97_codec *codec, int rw, int mask);
int (*mixer_ioctl)(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
// saved OSS mixer states
// //unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
// Software Modem interface
int (*modem_ioctl)(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
};
。。。。。。。
/*
* Is the pen down ?
*/
static inline int pendown (wm97xx_ts_t *ts)
{
printk("ddddddddddd\n"
return ts->codec->codec_read(ts->codec, AC97_WM97XX_DIGITISER_RD) & WM97XX_PEN_DOWN;
}
/*
* X,Y coordinates and pressure aquisition function.
* This function is run by a kernel timer and it's frequency between
* calls is the touchscreen polling rate;
*/
static void wm97xx_acq_timer(unsigned long data)
{
wm97xx_ts_t* ts = (wm97xx_ts_t*)data;
unsigned long flags;
static long x, y, x0, y0;
static int p0=0, penup=0; //pendown flag
TS_EVENT event;
spin_lock_irqsave(&ts->lock, flags);
printk("0000000000000\n"
/* are we still registered ? */
if (!ts->is_registered) {
spin_unlock_irqrestore(&ts->lock, flags);
// return; /* we better stop then */
}
printk("1111111111111\n"
//by xhhe.
/* read coordinates if pen is down */
//if (!pendown(ts))
// goto acq_exit;
if (!pendown(ts))
{ //pen is not down now.
printk("2222222222222222222"
if(penup == 0xFF) //ALready has a pne up event;
{
printk("33333333333333"
goto acq_exit;
}
if(penup < 2)
{//Waite 2 timer to create a steady pen UP event.
penup++;
goto acq_exit;
}
p0 |= 1; //penup should equal 2.
}
else
{
p0 = penup = 0;
}
if(p0 == 0) { //read the data, 由于数据会出现歧点,可考虑加入滤波算法.by xhhe.
/* polling mode */
if (!wm97xx_poll_read_adc(ts, WM97XX_ADCSEL_X, (u16*)&x0))
goto acq_exit;
if (!wm97xx_poll_read_adc(ts, WM97XX_ADCSEL_Y, (u16*)&y0))
goto acq_exit;
/* only read pressure if we have to */
//if (!five_wire && pil) {
// {
if (!wm97xx_poll_read_adc(ts, WM97XX_ADCSEL_PRES, &event.pressure))
goto acq_exit;
// }
//else
// event.pressure = 0;
printk("org calculate:X=0x%x,Y=0x%x,pressure=0x%x\n",(u16)x0,(u16)y0,event.pressure);
/* calibrate and remove unwanted bits from samples */
event.pressure &= 0x0fff;
if (event.pressure < 100) { //Drop it!
event.pressure = 100;
}
if (event.pressure == 0xfff)
{ //using the old x & y. 或者应该略去此次数据?
event.x = (u16)x;
event.y = (u16)y;
}
else
{
x = x0&0x00000fff;
//x = ((ts->cal.xscale * x) >> + ts->cal.xtrans;
event.x = (u16)x;
y = y0&0x00000fff;
//y = ((ts->cal.yscale * y) >> + ts->cal.ytrans;
event.y = (u16)y;
}
printk("after deal calculate:X=0x%x,Y=0x%x,pressure=0x%x\n",(u16)x,(u16)y,event.pressure);
}
else //!pendown but no penup event, create one. using the old x & y.
{
event.x = (u16)x;
event.y = (u16)y;
event.pressure = 0;
penup = 0xFF;
}
printk("final calculate:X=0x%x,Y=0x%x,pressure=0x%x\n",event.x,event.y,event.pressure);
//printk("----- p=0x%x,x=0x%x,y=0x%x\n", event.pressure, x, y);
//printk("wm97xx_acq_timer X=0x%x, Y=0x%x, pressure=0x%x\n",event.x, event.y, event.pressure);
/* timestamp this new event. */
event.millisecs = jiffies;
/* add this event to the event queue */
ts->event_buf[ts->nextIn++] = event;
if (ts->nextIn == EVENT_BUFSIZE)
ts->nextIn = 0;
if (ts->event_count < EVENT_BUFSIZE) {
ts->event_count++;
} else {
/* throw out the oldest event */
if (++ts->nextOut == EVENT_BUFSIZE) {
ts->nextOut = 0;
ts->overruns++;
}
}
/* async notify */
if (ts->fasync)
kill_fasync(&ts->fasync, SIGIO, POLL_IN);
/* wake up any read call */
if (waitqueue_active(&ts->wait))
wake_up_interruptible(&ts->wait);
/* schedule next acquire */
acq_exit:
ts->acq_timer.expires = jiffies + HZ / 100;
add_timer(&ts->acq_timer);
spin_unlock_irqrestore(&ts->lock, flags);
}
。。。。 |
|