免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1361 | 回复: 0
打印 上一主题 下一主题

[硬件及驱动] 驱动问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-02-27 11:01 |只看该作者 |倒序浏览
这些天在做触摸屏驱动,编译通过后加载模块老是报错,经过加打印信息后,基本可以确定是在进行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);
}

。。。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP