FL2440—独立ADC驱动模块
来源:互联网 发布:橘子vr软件下载 编辑:程序博客网 时间:2024/05/22 02:27
fl2440 ADC驱动编写
前面的学习中多次了解到linux内核对于各种常见驱动的支持相当的好,ADC也不例外。但是为了驱动的学习,参考datasheet的内容以及网友的博客文章,依然自己编写单独的ADC驱动模块。下面对ADC驱动的学习做一个简单的总结。
在s3c2440中集成了一个8通道的10位ADC,其从有4个通道即XP, XM, YP, YM连接到触摸屏的接口,用来检测转换触摸屏的模拟信号。剩下的4个通道A0,A1,A2,A3可以外接设备采集外设的模拟信号。其最高转换速率可达到5KHz.
在FL2440的开发板上,ADC的通道0外接一个电位器CN3,当调节电位器CN3的阻值,通道0采集到的电压值会随之在0~3.3V 的范围变化。
驱动程序&&测试程序
参考datasheet和网上的博客文章,下面是本人编写的驱动和测试程序。
- 驱动程序
/******************************************************************************** * Copyright: (C) 2017 Li Wanneng<liwjng@gmail.com> * All rights reserved. * * Filename: s3c_adc.h * Description: This head file is a driver for adc * * Version: 1.0.0(04/21/2017) * Author: Li Wanneng <liwjng@gmail.com> * ChangeLog: 1, Release initial version on "04/21/2017 02:43:21 PM" * ********************************************************************************/#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <plat/regs-adc.h>#include <linux/errno.h>#include <asm/uaccess.h> /* copy_to_user copy_from_user */#include <linux/input.h>#include <linux/serio.h>#include <linux/clk.h>#include <linux/sched.h>#include <linux/cdev.h>#include <linux/wait.h>#include <asm/io.h>#include <linux/ioport.h>#define DRV_AUTHOR "Liwanneng <liwjng@gmail.com>"#define DRV_DESC "S3C2440 ADC DRIVER"#define DEV_NAME "S3C_ADC"/* Set ADC dev major number*/#ifndef ADC_MAJOR#define ADC_MAJOR 0#endif#define DRV_MAJOR_VER 1#define DRV_MINOR_VER 0#define DRV_REVER_VER 0#define DISABLE 0#define ENABLE 1#define S3C_ADC_CON 0x58000000#define S3C_CON_LEN 4#define S3C_ADC_DATA 0x5800000C#define S3C_DATA_LEN 4#define PRSC_EN 1#define PRSC_VAL 49#define SEL_MUX 0static void __iomem *adc_con; static void __iomem *adc_data;#define s3c_adc_write(val, reg) __raw_writel((val),(reg))#define s3c_adc_read(reg) __raw_readl((reg))static struct clk *adc_clk;DEFINE_MUTEX(ADC_CLK); int debug = DISABLE;int dev_cnt = 1;int dev_major = ADC_MAJOR;int dev_minor = 0;static struct cdev *adc_cdev;static ssize_t adc_read(struct file *file, char *buff, size_t count,loff_t *ppos){ unsigned temp; volatile unsigned long adc_value; adc_con = ioremap(S3C_ADC_CON, S3C_CON_LEN); adc_data = ioremap(S3C_ADC_DATA,S3C_DATA_LEN); temp = s3c_adc_read(adc_con); temp = (PRSC_EN << 14) | (PRSC_VAL << 6) | (SEL_MUX << 3);/* 0 1 00000011 000 0 0 0 */ s3c_adc_write(temp, adc_con);/* Enable prescaler */ temp = s3c_adc_read(adc_con); temp = temp | (1 << 0); s3c_adc_write(temp, adc_con); /* Enable ADC Conversion start */ printk(KERN_INFO "write in kernel.\n"); while(s3c_adc_read(adc_con) &0x1); printk(KERN_INFO "write in kernel.\n"); while(!(s3c_adc_read(adc_con) &0x8000)); printk(KERN_INFO "will lock in kernel.\n"); mutex_lock(&ADC_CLK); /* Lock */ printk(KERN_INFO "locked in kernel.\n"); adc_value = s3c_adc_read(adc_data) &0x3ff;/* Acquire adc_value */ printk(KERN_INFO "adc_value getted.\n"); copy_to_user(buff, (char *)&adc_value, sizeof(adc_value)); mutex_unlock(&ADC_CLK);/* Unlock */ return sizeof(adc_value);}static int adc_open(struct inode *inode, struct file *file){ int minor = iminor(inode); file->private_data = (void *)minor; printk(KERN_INFO "/dev/S3C_ADC%d opened.\n", minor); return 0;}static int adc_release(struct inode *inode, struct file *file ){ return 0;}static struct file_operations adc_fops = { .owner = THIS_MODULE, .open = adc_open, .read = adc_read, .release = adc_release,};static int __init s3c_adc_init(void){ int result; dev_t devno; if(0!=dev_major) { devno = MKDEV(dev_major, 0); result = register_chrdev_region(devno, dev_cnt, DEV_NAME); } else { result = alloc_chrdev_region(&devno, dev_minor, dev_cnt, DEV_NAME); dev_major = MAJOR(devno); } if(result<0) { printk(KERN_ERR "%s driver can't use major %d\n", DEV_NAME, dev_major); return -ENODEV; } printk(KERN_DEBUG "%s driver use major %d\n", DEV_NAME, dev_major); adc_clk = clk_get(NULL,"s3c_adc"); if(!adc_clk) { printk(KERN_ERR "failed to find adc clock source\n"); return -ENOENT; } clk_enable(adc_clk); if(NULL == (adc_cdev=cdev_alloc()) ) { printk(KERN_ERR "S3C %s driver can't alloc for the cdev.\n", DEV_NAME); unregister_chrdev_region(devno, dev_cnt); return -ENOMEM; } adc_cdev->owner = THIS_MODULE; cdev_init(adc_cdev, &adc_fops); result = cdev_add(adc_cdev, devno, dev_cnt); if(0!=result) { printk(KERN_INFO "S3C %s driver can't reigster cdev: result=%d\n", DEV_NAME, result); goto ERROR; } printk(KERN_INFO "%s driver[major=%d] version %d.%d.%d installed successfully!\n",DEV_NAME, dev_major, DRV_MAJOR_VER, DRV_MINOR_VER,DRV_REVER_VER); return 0;ERROR: printk(KERN_ERR "S3C %s driver installed failure.\n", DEV_NAME); cdev_del(adc_cdev); unregister_chrdev_region(devno, dev_cnt); return result;}static void __exit s3c_adc_exit(void){ dev_t devno = MKDEV(dev_major, dev_minor); cdev_del(adc_cdev); unregister_chrdev_region(devno, dev_cnt); iounmap(adc_con); iounmap(adc_data); if(adc_clk) { clk_disable(adc_clk); clk_put(adc_clk); /* ERROR */ printk("exit4\n"); adc_clk = NULL; printk("exit5\n"); } printk(KERN_ERR "S3C %s driver version %d.%d.%d removed!\n",DEV_NAME, DRV_MAJOR_VER, DRV_MINOR_VER,DRV_REVER_VER); return ;}/* This two function defined in <linux/init.h> */module_init(s3c_adc_init);module_exit(s3c_adc_exit);module_param(debug, int, S_IRUGO);module_param(dev_major, int, S_IRUGO);MODULE_AUTHOR(DRV_AUTHOR);MODULE_DESCRIPTION(DRV_DESC);MODULE_LICENSE("GPL");
- Makefile
[lwn@localhost adc]$ vim Makefile LINUX_SRC?=~/fl2440/kernel/linux-lwn-3.0.1CROSS_COMPILE=/opt/dl/buildroot-2012.08/ARM920t/usr/bin/arm-linux-obj-m := adc.omodules: @make -C $(LINUX_SRC) M=`pwd` modules @make cleanclean: rm -f *.ko.* *.o *mod.c *.order *.symvers
- 测试程序
/********************************************************************************* * Copyright: (C) 2017 Li Wanneng<liwjng@gmail.com> * All rights reserved. * * Filename: adc_test.c * Description: This file test s3c_adc driver * * Version: 1.0.0(04/21/2017) * Author: Li Wanneng <liwjng@gmail.com> * ChangeLog: 1, Release initial version on "04/21/2017 07:36:33 PM" * ********************************************************************************/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>/******************************************************************************** * Description: * Input Args: * Output Args: * Return Value: ********************************************************************************/int main (int argc, char **argv){ int fd; fd = open("/dev/S3C_ADC",O_RDONLY); if(fd<0) { printf("open S3C_ADC device failed.\n"); exit(1); } printf("fd>0\n"); while(1) { int ret; int data; printf("while read in user\n"); ret = read(fd, &data, sizeof(data)); printf("readed in user\n"); if(sizeof(data) != ret) { if(errno != EAGAIN) { printf("Read ADC Device Faild!\n"); } continue; } else { printf("Read ADC value is: %d\n", data); } sleep(1); } close(fd); return 0;} /* ----- End of main() ----- */
编译测试
编写好以上程序之后,接下来下载到开发板测试运行。
1.在虚拟机中用make命令和gcc交叉编译器编译驱动程序s3c_adc.c和测试程序test_adc.c:
2.接下来将编译生成的驱动文件和测试文件下载到开发板测试ADC(因为我开发板的AD模块坏了,所以在同学的板子上运行,就是界面丑了点蛤)
0 0
- FL2440—独立ADC驱动模块
- fl2440——驱动学习-ADC驱动
- ADC驱动在FL2440的开发
- 触摸屏和ADC驱动的移植 (fl2440)
- fl2440触摸屏与ADC驱动移植
- 基于fl2440内核linux-3.0移植----添加adc驱动
- FL2440 adc 实验
- FL2440 ADC 数据采样
- FL2440驱动添加(1):hello world 驱动模块添加
- FL2440无操作系统应用程序编写测试006——ADC
- fl2440开发板hello world模块驱动编写
- fl2440模块学习——3G拨号上网
- FL2440驱动入门——helloworld
- fl2440——驱动入门,hello world!
- fl2440——DS18B20 驱动编写
- ADC 模块
- S3C2440驱动篇—ADC驱动分析
- ADC驱动
- 在Win10 Anaconda中安装Tensorflow
- SPOJ COT2 Count on a tree II
- 关于两个特殊信号,SIGSTOP与SIGCONT
- 首次开通博客【人工置顶】
- 第二行代码读书笔记--git的使用(四)
- FL2440—独立ADC驱动模块
- MySQL优化
- Linux Java程序debug总结
- iOS之UICololor的使用
- 从DllMain下断点到LdrpCallInitRoutine
- Codeforces 793A Oleg and shares 题解
- Android深入四大组件(三)Service的绑定过程
- Matlab图像处理(02)-图像基础
- 网络互联基础知识