其他分享
首页 > 其他分享> > ADC_驱动

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 !\n");
 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\n",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 !\n");
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 !\n");
175     
176     int ret;
177     fsp_dev = kzalloc(sizeof(struct fsp),GFP_KERNEL);
178     if(IS_ERR(fsp_dev)){
179         printk("kzalloc error!\n");
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!\n");
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!\n");
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!\n");
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!\n");
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!\n");
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 !\n");
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\n",data);
19         sleep(1);
20     }
21     close(fd);
22     return 0;
23 }

 

标签:dev,fsp,ret,cdev,ADC,驱动,include,adc
来源: https://www.cnblogs.com/panda-w/p/11624142.html