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 }