Linux.ChinaUnix.net
ChinaUnix | Linux首页 | 新闻 | 博客 | 文章 | 专栏 | 新手 | 方案 | 图书 | 下载 | 人才 | 手册 | wiki | 搜索     
Linux论坛
  会员: 密码: 免费注册 | 忘记密码 | 会员登录 | 搜索



自己修改的ADC0809驱动,Godbach和版主请看看
首页 » CU论坛 » Linux » 汇总贴列表 » 驱动开发 »  
[打印] [订阅] [收藏] [本帖文本页] [推荐此主题给朋友,立即获积分]
ady2002
精灵



CU编号: 682681
注册:2008-3-27
最后登录: 2009-06-21
帖子:153
精华:0

可用积分:228 (白手起家)
信誉积分:0
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[个人空间] [短信] [博客]


1楼 发表于 2008-11-18 11:08 
我根据自己的需要对之前发的那个adc0809的驱动进行了修改
目的:利用2410的timer0做一个定时中断,比如10ms中断一次,
获取数据并对一个阈值进行判读,最后置为0,1,再吧之前获取的数据和刚获取的对比 不同则加1
最后再read函数输出这个累加值

但是不解编译可以,安装insmod的时候会出现0oops错误  不解啊·~~~~~~
麻烦帮我看看啊 感激不及啊~~~~

/* driver/char/adc0809.c
*  this is a adc0809 char device driver.
* Any problem pls contact [email]support@hhcn.com[/email]
*/

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/io.h>

#include "adc0809_ioctl.h"

MODULE_LICENSE("GPL");

#define ADC0809_MAJOR 231
/*define the adc0809 major node is 231*/


#define adc0809_sle (*(volatile unsigned long *)ADC_GPACON)
#define adc0809_sle_data (*(volatile unsigned long *)ADC_GPADATA)


unsigned long ADC_GPACON, ADC_GPADATA;
static unsigned long ADC_0, ADC_1, ADC_2, ADC_3, ADC_4, ADC_5, ADC_6, ADC_7;
unsigned long ADC_DATA;
static unsigned int r_TCFG0,r_TCFG1,r_TCNTB1,r_TCMPB1,r_TCON,r_GPCCON;

//unsigned long adc_write_addr;
//unsigned long adc_read_addr;
int * adc_read_addr,* adc_write_addr;


devfs_handle_t devfs_adc;

void adc0809_interrupt(int,void *,struct pt_regs *);

int  adc0809_open(struct inode *, struct file *);
int  adc0809_release(struct inode *, struct file *);
//int  adc0809_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
ssize_t adc0809_read(struct file *, char * , size_t , loff_t *);
ssize_t adc0809_write(struct file *, const char *, size_t , loff_t *);

static struct file_operations adc0809_fops = {
       // ioctl:          adc0809_ioctl,   //根据参数确定读取的引脚;
        open:           adc0809_open,                //选中片选NGCS2(初始化ADC0809的管脚配置),初始化adc_read_addr;
        read:           adc0809_read,
        write:          adc0809_write,
        release:        adc0809_release,
};

//struct timer_list timer_ForData;  // 定时器

char data; //变量类型不同也会出错,之前使用unsigned long所得是一连串八位数字要么是-1
unsigned long addr;

int adc0809_sum=0;
/*------------中断处理函数------------------*/
void adc0809_interrupt(int irq,void *d,struct pt_regs *regs)
{
        char adc0809_v=0,adc0809_u=0;
/*clear interrupt register for INT_TIMER0*/
        SRCPND &= (~0x00000800);    //bit11
        INTPND = INTPND;
[b]/*---下面这一段使自己加的--------*/[/b]
          data = (*(volatile unsigned long *) adc_read_addr);
        if(data<200){adc0809_v=0;}
                else adc0809_v=1;
        if(adc0809_v<adc0809_u){adc0809_sum=adc0809_sum+1;}
                else adc0809_sum=adc0809_sum;
        adc0809_u=adc0809_v;
printk("data:%d\n",data);
printk("adc0809_u:%d\n",adc0809_u);
printk("adc0809_v:%d\n",adc0809_v);
printk("adc0809_sum:%d\n",adc0809_sum);
}

/*------- Open/close code for raw IO.-----*/
int adc0809_open(struct inode *inode, struct file *filp)
{
          adc_read_addr = ADC_DATA;
        adc_write_addr = ADC_1;     
        (*(volatile unsigned char *) adc_write_addr) = (char) 0;       
        printk("open ok\n");
          return 0;
}
/*------------read()----------------*/
ssize_t adc0809_read(struct file *filp, char * buf,
                 size_t size, loff_t *offp)
{       
        char key;
       
       
        key =adc0809_sum;
        printk("key_driver:%d\n",key);
        copy_to_user(buf,&key,1);//put_user(key,buf);
        //printk("adc0809_read:adc_read_addr=0x%x\n",adc_read_addr);
        return 1;
}
/*------------------write()-------------------------------*/
ssize_t adc0809_write(struct file *filp, const char *buf,
                  size_t size, loff_t *offp)
{
   char key;
   if (get_user(key, buf))
               return -EFAULT;
   printk("adc0809_write:adc_write_addr=0x%x; key = %c\n",adc_write_addr,key);

        (*(volatile unsigned char *) adc_write_addr) = key;
   //put_user(key,buf);
   return 1;
}

/*----------------release()---------------------*/
int adc0809_release(struct inode *inode, struct file *filp)
{
        printk("release ok\n");
        return 0;
}

[b]/*---这里我吧ioctl函数给删除了 就是不使用它,而是在初始化函数中来选着引脚并赋值[/b]
  Deal with ioctls against the raw-device control interface, to bind
  and unbind other raw devices.

int adc0809_ioctl(struct inode *inode,          //octl选着待测的引脚 并触发中断
                        struct file *flip,                //就是给 是0809的寄存器 一旦这个引角得到一个触发信号
                        unsigned int command,        //那么相应的管脚就工作,然后才能输出ADC_DATA
                        unsigned long arg)               
{
      int err = 0;
      switch (command) {
        case IOCTRL_ADC_0:
          adc_write_addr = ADC_0;
          //printk("adc0809_ioctl: adc addr: %x\n",adc_write_addr);
          /* start collect and convert
          (*(volatile unsigned char *) adc_write_addr) = (char) arg;
         
          return 0;
        case IOCTRL_ADC_1:  //通道选择 因为ADC0809工作通道选择是由ADDC,ADDB,ADDA来实现的.
          adc_write_addr = ADC_1;     
          (*(volatile unsigned char *) adc_write_addr) = (char) arg;
          return 0;
        default:
          err = -EINVAL;
      }
      // adc_read_addr = ADC_DATA;
      //adc_write_addr = ADC_2;
          //(*(volatile unsigned char *) adc_write_addr) = (char) arg;
            
      return err;               
}

/*-------------------iormap()--地址影射函数---*/
static int address_map(void)
{
           r_TCFG0 = ioremap(0x51000000,4); //定时器配置寄存器0
            r_TCFG1 = ioremap(0x51000004,4); //定时器配置寄存器1
            r_TCNTB1 = ioremap(0x51000018,4);
           r_TCMPB1 = ioremap(0x5100001C,4);
            r_TCON = ioremap(0x51000008,4);
            r_GPCCON = ioremap(0x56000020,4);

        ADC_GPACON = (unsigned int)ioremap(0x56000000,4);  //物理寄存器的影射,个人认为这里都是指CPLD的物理寄存器
          ADC_GPADATA = ioremap(0x56000004,4);
          ADC_0 = ioremap(0x10000010,4);
          ADC_1 = ioremap(0x10002010,4);
          ADC_2 = ioremap(0x10004010,4);
          ADC_3 = ioremap(0x10006010,4);
          ADC_4 = ioremap(0x10008010,4);
          ADC_5 = ioremap(0x1000a010,4);
          ADC_6 = ioremap(0x1000c010,4);
          ADC_7 = ioremap(0x1000e010,4);  
          ADC_DATA = ioremap(0x10000020,4);
            return 0;

}
/*--------------------------------------------------------------------------*/
int __init adc0809_init(void)
{
  static int result;
// unsigned long gpfup;
  //volatile unsigned int bankcon2;       
  address_map();
  printk("*********************adc0809_init**************\n");
                 adc_write_addr = ADC_0;              [b] //ioctl函数的功能放到初始化函数中[/b]
         (*(volatile unsigned char *) adc_write_addr) = (char) arg;

  

// bankcon2=(volatile unsigned int)ioremap(0x4800000c,4);
// *(volatile unsigned int*)bankcon2 |= 3<<13;  //
  /* select NGCS2 */
  adc0809_sle |= 0x2000;
  adc0809_sle_data &= (~0x2000);


[b]/*-----------初始化S3C2410的时钟timer0-------------原驱动没有的后来添加的-------------*/[/b]
        (*(volatile unsigned int *)r_TCFG0) &= 0x11111100;//prescaler=0
        (*(volatile unsigned int *)r_TCFG1) &= (~0x000000F0);//MUX1=1/2
//        (*(volatile unsigned int *)r_TCFG1) &= (~0x000000D0);//MUX1=1/8  时间T=r_TCNTB1/625000(s)
        (*(volatile unsigned int *)r_TCNTB1) = 25000;         //时间为10ms
            (*(volatile unsigned int *)r_TCMPB1) = 0x00000000;
            (*(volatile unsigned int *)r_TCON) |= 0x00000E00;
           (*(volatile unsigned int *)r_TCON) &= (~0x00000200);
           (*(volatile unsigned int *)r_TCON) |= 0x00000100;

        disable_irq(IRQ_TIMER1);
            enable_irq(IRQ_TIMER1);

        result=request_irq(IRQ_TIMER1,&adc0809_interrupt,SA_INTERRUPT,"adc0809",NULL);
        if (!result)
        {
                printk("Get assigned irq %d,result=%d\n",IRQ_TIMER1,result);
//                return result;
        }

        printk("***********Init ok!!***********\n");
       

        
  devfs_adc =
        devfs_register(NULL,"adc0809",DEVFS_FL_DEFAULT,
                       ADC0809_MAJOR, 0,
             S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
                       &adc0809_fops,NULL);
        return 0;
}

int __init adc0809_exit(void)
{
        (*(volatile unsigned int *)r_TCON) &= (~0x00000100);
             disable_irq(IRQ_TIMER1);
        free_irq(IRQ_TIMER1, adc0809_interrupt);
             printk("exit ok\n");
//free_irq(IRQ_EINT2, adc0809_interrupt);
  devfs_unregister(devfs_adc);
  return 0;
}

/*
__initcall(adc0809_init);
*/
module_init(adc0809_init);
module_exit(adc0809_exit);

[ 本帖最后由 ady2002 于 2008-11-18 11:34 编辑 ]



您对本贴的看法:鲜花[0] 臭蛋[0]
版主 Godbach (To be 千里马!)
版主-大法师


CU奥运火炬传递手2008
CU编号: 534931
注册:2007-3-9
最后登录: 2009-07-05
帖子:8560
精华:12

可用积分:22755 (巨富豪门)
信誉积分:112
专家积分:114 (本版:10)
空间积分:2
推广积分:17

状态:...保密...

[个人空间] [短信] [博客]


2楼 发表于 2008-11-18 11:22 
版主让你用code括起来,是发帖的时候那个有个工具是插入代码,而不是手写上这个,而且括号还是中文字符的。

OOPS一般都是你操作了非法指针。



您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

明犯我强汉天威者,穷搜天下,万里追杀,覆其巢,断其苗裔,戮其身,追其魂,屠其魄,虽远必诛!
----------------------------------
一尺之槌,日取其半,万世不竭!
----------------------------------
欢迎光临Godbach的博客交流技术问题:
http://blog.chinaunix.net/u/33048/
----------------------------------
版主 Godbach (To be 千里马!)
版主-大法师


CU奥运火炬传递手2008
CU编号: 534931
注册:2007-3-9
最后登录: 2009-07-05
帖子:8560
精华:12

可用积分:22755 (巨富豪门)
信誉积分:112
专家积分:114 (本版:10)
空间积分:2
推广积分:17

状态:...保密...

[个人空间] [短信] [博客]


3楼 发表于 2008-11-18 11:22 
把你对原先程序修改过的地方有比较明显的字体和颜色标示出来。



您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

明犯我强汉天威者,穷搜天下,万里追杀,覆其巢,断其苗裔,戮其身,追其魂,屠其魄,虽远必诛!
----------------------------------
一尺之槌,日取其半,万世不竭!
----------------------------------
欢迎光临Godbach的博客交流技术问题:
http://blog.chinaunix.net/u/33048/
----------------------------------
ady2002
精灵



CU编号: 682681
注册:2008-3-27
最后登录: 2009-06-21
帖子:153
精华:0

可用积分:228 (白手起家)
信誉积分:0
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[个人空间] [短信] [博客]


4楼 发表于 2008-11-18 11:33 
哦 误解了
主要就是删了ioctl函数 和在中断以及初始化函数中有些改动 其他都没有动
下班了 先去吃饭

期待中。。。。。。



您对本贴的看法:鲜花[0] 臭蛋[0]
ady2002
精灵



CU编号: 682681
注册:2008-3-27
最后登录: 2009-06-21
帖子:153
精华:0

可用积分:228 (白手起家)
信誉积分:0
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[个人空间] [短信] [博客]


5楼 发表于 2008-11-18 12:14 
我也知道说是  非法指针的问题哦
但是 我不解的是驱动中就那么几个指针
我都检查了 还是不知道问题在哪哦
郁闷啊?~~
所以想求助大家的力量帮我看看



您对本贴的看法:鲜花[0] 臭蛋[0]
版主 dreamice
广告杀手-精灵使
言多必失



CU编号: 562632
注册:2007-5-11
最后登录: 2009-07-05
帖子:3895
精华:37

可用积分:6236 (富足长乐)
信誉积分:110
专家积分:70 (本版:0)
空间积分:0
推广积分:31

状态:...离线...

[个人空间] [短信] [博客]


6楼 发表于 2008-11-18 12:53 
回复 #5 ady2002 的帖子

说句实在话,你这个程序和昨天贴那个程序,没有实质性的改进。我建议你还是在昨天那个驱动上面下一番功夫,理解清楚点,加以修改一下。



您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

Nothing is impossible!
ady2002
精灵



CU编号: 682681
注册:2008-3-27
最后登录: 2009-06-21
帖子:153
精华:0

可用积分:228 (白手起家)
信誉积分:0
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[个人空间] [短信] [博客]


7楼 发表于 2008-11-18 13:03 


QUOTE:
原帖由 dreamice 于 2008-11-18 12:53 发表
说句实在话,你这个程序和昨天贴那个程序,没有实质性的改进。我建议你还是在昨天那个驱动上面下一番功夫,理解清楚点,加以修改一下。

我现在就是对昨天那个驱动 里面那几个问题不是很清楚哦。
就是ioctl到底是怎么触发中断函数的,wirter作用是什么一直高不明白哦
郁闷



您对本贴的看法:鲜花[0] 臭蛋[0]
版主 Godbach (To be 千里马!)
版主-大法师


CU奥运火炬传递手2008
CU编号: 534931
注册:2007-3-9
最后登录: 2009-07-05
帖子:8560
精华:12

可用积分:22755 (巨富豪门)
信誉积分:112
专家积分:114 (本版:10)
空间积分:2
推广积分:17

状态:...保密...

[个人空间] [短信] [博客]


8楼 发表于 2008-11-18 13:06 


QUOTE:
原帖由 ady2002 于 2008-11-18 13:03 发表

我现在就是对昨天那个驱动 里面那几个问题不是很清楚哦。
就是ioctl到底是怎么触发中断函数的,wirter作用是什么一直高不明白哦
郁闷

如果你对ioctl里面如果出发中断不理解的话,你可以把这函数加一些调试信息看一下



您对本贴的看法:鲜花[0] 臭蛋[0]

__________________________________

明犯我强汉天威者,穷搜天下,万里追杀,覆其巢,断其苗裔,戮其身,追其魂,屠其魄,虽远必诛!
----------------------------------
一尺之槌,日取其半,万世不竭!
----------------------------------
欢迎光临Godbach的博客交流技术问题:
http://blog.chinaunix.net/u/33048/
----------------------------------
ady2002
精灵



CU编号: 682681
注册:2008-3-27
最后登录: 2009-06-21
帖子:153
精华:0

可用积分:228 (白手起家)
信誉积分:0
专家积分:0 (本版:0)
空间积分:0
推广积分:0

状态:...离线...

[个人空间] [短信] [博客]


9楼 发表于 2008-11-18 13:08 
恩  加那些呢??
现在是 这个驱动不知道问题到底在哪?
god能不能仔细我帮我瞧瞧??????



您对本贴的看法:鲜花[0] 臭蛋[0]
版主 Godbach (To be 千里马!)
版主-大法师


CU奥运火炬传递手2008
CU编号: 534931
注册:2007-3-9
最后登录: 2009-07-05
帖子:8560
精华:12

可用积分:22755 (巨富豪门)
信誉积分:112
专家积分:114 (本版:10)
空间积分:2
推广积分:17

状态:...保密...

[个人空间] [短信] [博客]


10楼 发表于 2008-11-18 13:13 


QUOTE:
原帖由 ady2002 于 2008-11-18 13:08 发表
恩  加那些呢??
现在是 这个驱动不知道问题到底在哪?
god能不能仔细我帮我瞧瞧??????

呵呵,这个因为具体和你的硬件相关。我没法具体帮你看。如果原先的程序是可以触发中断的,那你就根据程序来判断一下中断在哪里触发了。加一些printk打印出相关信息即可。
你知道中断的对应的地址线,关注这个地址的值是么时候变为触发中断的值了。



您对本贴的看法:鲜花[0] 臭蛋[1]

__________________________________

明犯我强汉天威者,穷搜天下,万里追杀,覆其巢,断其苗裔,戮其身,追其魂,屠其魄,虽远必诛!
----------------------------------
一尺之槌,日取其半,万世不竭!
----------------------------------
欢迎光临Godbach的博客交流技术问题:
http://blog.chinaunix.net/u/33048/
----------------------------------

首页 » CU论坛 » Linux » 汇总贴列表 » 驱动开发 »

 


Copyright © 2001-2008 ChinaUnix.net All Rights Reserved     联系我们:

感谢所有关心和支持过ChinaUnix的朋友们    转载本站内容请注明原作者名及出处

京ICP证041476号


清除 Cookies - Linux时代 - Archiver - WAP - TOP

Processed in 0.467868 second(s), 5 queries , Gzip enabled