zoukankan      html  css  js  c++  java
  • 全志_ADC驱动

    ADC_驱动


      1 #include <linux/module.h>
      2 #include <linux/fs.h>
      3 #include <linux/platform_device.h>
      4 #include <linux/device.h>
      5 #include <asm/io.h>
      6 #include <asm/uaccess.h>
      7 #include <linux/interrupt.h>
      8 #include <linux/sched.h>
      9 #include <linux/irqreturn.h>
     10 #include <linux/init.h>
     11 #include <linux/slab.h>
     12 #include <linux/gpio.h>
     13 #include <linux/cdev.h>
     14 #include <asm/string.h>
     15 #include <asm-generic/ioctl.h>
     16 #include <linux/kernel.h>
     17 #include <linux/input.h>
     18 #include <linux/list.h>
     19 #include <linux/spinlock.h>
     20 #include <linux/rwsem.h>
     21 #include <linux/timer.h>
     22 #include <linux/err.h>
     23 #include <linux/ctype.h>
     24 #include <linux/sysfs.h>
     25 #include <linux/of.h>
     26 #include <linux/of_gpio.h>
     27 #include <linux/miscdevice.h>
     28 #include <linux/delay.h>
     29 #include <linux/sys_config.h>
     30 
     31 
     32 #define IR_GPIO GPIOH(10)               //外部中断引脚
     33 
     34 
     35 //定义个数据包
     36 struct fsp_event{
     37     int code;         
     38     int value;     
     39 };
     40 
     41 
     42 //面向对象-设备的类型
     43 struct fsp{
     44     //unsigned int major;
     45     dev_t  devno;
     46     struct class * cls;
     47     struct device * dev;
     48     struct cdev  *cdev;
     49     unsigned int irqno;
     50     struct fsp_event event;
     51     int data;
     52 };
     53 struct fsp *fsp_dev;
     54 
     55 
     56 //void __iomem *adc_base;   //必须是void __iomem类型因为偏移地址不一样
     57 
     58 
     59 volatile unsigned long * adc_ctrl;  //ADC控制寄存器
     60 volatile unsigned long * adc_intc;    //ADC中断控制寄存器 
     61 volatile unsigned long * adc_ints;    //ADC中断状态寄存器
     62 volatile unsigned long * adc_dat0;    //ADC数据1寄存器
     63 volatile unsigned long * adc_dat1;    //ADC数据2寄存器
     64 
     65 
     66 wait_queue_head_t adcq;   //等待队列头
     67 int flag = 0;
     68 
     69 
     70 //中断服务函数
     71 irqreturn_t fsp_irq_svc(int irqno,void *id)
     72 {
     73     //开始必须要清中断,内核没有进行清中断我们必须在驱动中手动清中断
     74  //   writel(0,adc_base + 0x18);
     75      //ADC中断状态寄存器设置  (清除中断标志位)
     76     *adc_ints &= ~(0x1f<<0);     //0--4清0
     77     *adc_ints |=   0x1f<<0;      //0---4赋值:00010001
     78  
     79     
     80     //唤醒阻塞(进入中断表明转换完成,唤醒阻塞,读取数据,上报数据)
     81     wake_up_interruptible(&adcq);
     82     flag = 1;
     83     return IRQ_HANDLED;
     84 }
     85 
     86 
     87 
     88 
     89 //open接口            ADC0
     90 int fsp_adc_open(struct inode *inode,struct file *filp)
     91 {
     92     printk("fsp open success !
    ");
     93     
     94     
     95     //ADC控制寄存器设置    (打开ADC,转换速率62.5HZ)
     96     *adc_ctrl &= ~(0x00<<0);     //0 清0
     97     *adc_ctrl |=   0x00<<0 ;     //0 赋值:1
     98     
     99     //ADC中断控制寄存器设置(使能ADC0 中断控制,)
    100     *adc_intc &= ~(0x1f<<0);     //0--4清0
    101     *adc_intc |=   0x1f<<0;      //0---4赋值:11111
    102     
    103     //ADC中断状态寄存器设置  (清除中断标志位)
    104     *adc_ints &= ~(0x1f<<0);     //0--4清0
    105     *adc_ints |=   0x1f<<0;      //0---4赋值:00010001
    106     
    107 /*    
    108     //ADC数据0寄存器设置
    109     *(adc_base+24) &= ~(0xff<<12);     //19--12清0
    110     *(adc_base+24) |= 0x11<<12;        //19---12赋值:00010001
    111     
    112     //ADC数据1寄存器设置
    113     *(adc_base+32) &= ~(0xff<<12);     //19--12清0
    114     *(adc_base+32) |= 0x11<<12;        //19---12赋值:00010001
    115 */    
    116     
    117     return 0;
    118 }
    119 
    120 
    121 //read接口
    122 ssize_t fsp_adc_read(struct file *filp,char __user *ubuf,size_t size,loff_t *off)
    123 {
    124     int ret;
    125     int data;
    126     //开始转换数据
    127     //writel(readl(adc_base) | 1 << 0,adc_base);//转换完成后才会出现中断
    128      *adc_ctrl |=   0x01<<0 ;     //0 赋值:1
    129     
    130     
    131     //阻塞等待一下
    132     wait_event_interruptible(adcq,flag != 0);
    133 
    134     //只有转化完成且中断唤醒阻塞后才能读取数据,直接不能读取数据
    135     //data = readl(adc_base + 0x0c) & 0xfff;
    136     
    137     data = readl(adc_dat0) & 0xfff;
    138     
    139     
    140     ret = copy_to_user(ubuf,&data,sizeof(data));
    141     flag = 0;
    142     
    143     printk("adc :  %d
    ",data);
    144     
    145     return sizeof(data);
    146 }
    147 
    148 
    149 
    150 //close接口
    151 int fsp_adc_close(struct inode *inode, struct file *filp)
    152 {
    153     printk("fsp close success !
    ");
    154     return 0;
    155 }
    156 
    157 
    158 
    159 
    160 //实现FOPS
    161 struct file_operations fops = {
    162     .owner   = THIS_MODULE,
    163     .open    = fsp_adc_open,
    164     .read    = fsp_adc_read,
    165     .release = fsp_adc_close,
    166 };
    167 
    168 
    169 
    170 //初始化函数
    171 static int __init fsp_init(void)   
    172 {
    173     
    174     printk("fsp_init  success !
    ");
    175     
    176     int ret;
    177     fsp_dev = kzalloc(sizeof(struct fsp),GFP_KERNEL);
    178     if(IS_ERR(fsp_dev)){
    179         printk("kzalloc error!
    ");
    180         ret = PTR_ERR(fsp_dev);
    181         return -ENOMEM;
    182     }
    183     
    184 
    185     //动态申请设备号
    186     ret = alloc_chrdev_region(&fsp_dev->devno,0,1,"button_drv");
    187     if(ret < 0){
    188         printk("register_chrdev_region error!
    ");
    189         ret =  -EINVAL;
    190         goto err_kfree;
    191     }
    192 
    193 
    194     //申请cdev的空间
    195     fsp_dev->cdev = cdev_alloc();
    196     if(IS_ERR(fsp_dev->cdev)){        
    197         printk("fsp_dev->cdev error!
    ");
    198         ret = PTR_ERR(fsp_dev->cdev);
    199         goto err_unregister;
    200     }
    201 
    202     //初始化cdev的成员
    203     cdev_init(fsp_dev->cdev,&fops);
    204 
    205     //将cdev加入到内核中----链表
    206     ret = cdev_add(fsp_dev->cdev,fsp_dev->devno,1);
    207 
    208     //创建设备文件
    209     fsp_dev->cls = class_create(THIS_MODULE,"fsp_dev");
    210     if(IS_ERR(fsp_dev->cls)){
    211         printk("class_create error!
    ");
    212         ret = PTR_ERR(fsp_dev->cls);
    213         goto err_cdev_del;
    214     }
    215     
    216     fsp_dev->dev = device_create(fsp_dev->cls,NULL,fsp_dev->devno,NULL,"fsp_EINT");
    217     if(IS_ERR(fsp_dev->dev)){
    218         printk("device_create error!
    ");
    219         ret = PTR_ERR(fsp_dev->dev);
    220         goto err_class;
    221     }
    222     
    223     
    224     
    225     //1.中断申请
    226     fsp_dev->irqno = gpio_to_irq(IR_GPIO);   //中断号
    227     ret = request_irq(fsp_dev->irqno,fsp_irq_svc,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,"eint-keydown",NULL);
    228     if(ret != 0){
    229         printk("request_irq error!
    ");
    230         ret = -EBUSY;
    231         goto err_device;
    232     }
    233 
    234 
    235     //2.地址映射
    236     adc_ctrl = ioremap(0x01c24400,8);//将物理地址映射成虚拟地址
    237     adc_intc = adc_ctrl + 1;
    238     adc_ints = adc_ctrl + 2;
    239     adc_intc = adc_dat0 + 3;
    240     adc_intc = adc_dat1 + 4;
    241 
    242     
    243 //    writel(255 << 6 | 1 << 14 | 1 << 16,adc_base);
    244 //    writel(3,adc_base + 0x1c);
    245 
    246 
    247 
    248     init_waitqueue_head(&adcq);  //初始化等待对列头
    249 
    250     return 0;
    251     
    252 err_device:
    253     device_destroy(fsp_dev->cls,fsp_dev->devno);
    254 err_class:
    255     class_destroy(fsp_dev->cls);
    256     
    257 err_cdev_del:
    258     cdev_del(fsp_dev->cdev);
    259     
    260 err_unregister:
    261     unregister_chrdev_region(fsp_dev->devno,1);
    262     
    263 err_kfree:
    264     kfree(fsp_dev);
    265     return ret;
    266   
    267 }
    268 
    269 
    270 
    271 static void __exit fsp_exit(void)   
    272 {
    273     printk("fsp_init  success !
    ");
    274     
    275     free_irq(fsp_dev->irqno,NULL);
    276     device_destroy(fsp_dev->cls,fsp_dev->devno);
    277     class_destroy(fsp_dev->cls);
    278     cdev_del(fsp_dev->cdev);
    279     unregister_chrdev_region(fsp_dev->devno,1);
    280     kfree(fsp_dev);
    281 }
    282 
    283 
    284 
    285 module_init(fsp_init);
    286 module_exit(fsp_exit);
    287 MODULE_LICENSE("GPL");

    测试:

     1 #include <stdio.h>
     2 #include <sys/types.h>
     3 #include <sys/stat.h>
     4 #include <fcntl.h>
     5 #include <unistd.h>
     6 
     7 
     8 int main(void)
     9 {
    10     int fd;
    11 
    12     fd = open("/dev/fsp_EINT",O_RDWR);
    13 
    14     int data;
    15     while(1)
    16     {
    17         read(fd,&data,sizeof(data));
    18         printf("data = %d
    ",data);
    19         sleep(1);
    20     }
    21     close(fd);
    22     return 0;
    23 }

    博客:http://www.itkeyword.com/doc/3093906707123520x327/c-kernel-linux

       https://www.cnblogs.com/hslixiqian/p/9676526.html

  • 相关阅读:
    二叉树非递归遍历
    二叉树之统计二叉树的节点个数
    C语言32个关键字(2)
    C语言32个关键字(1)
    C语言常用字符串操作函数总结
    面向对象的四大特征
    C语言之生产者与消费者模型
    菜鸟随笔(4)---read函数与fread函数的区别
    菜鸟随笔(3)---三种进程学习.孤儿进程.僵尸进程.守护进程
    进程通信——管道、消息队列、共享内存、信号量
  • 原文地址:https://www.cnblogs.com/panda-w/p/11624142.html
Copyright © 2011-2022 走看看