Linux2.6.32.2内核在mini2440上的移植(七)添加ADC驱动_第1页
Linux2.6.32.2内核在mini2440上的移植(七)添加ADC驱动_第2页
Linux2.6.32.2内核在mini2440上的移植(七)添加ADC驱动_第3页
Linux2.6.32.2内核在mini2440上的移植(七)添加ADC驱动_第4页
Linux2.6.32.2内核在mini2440上的移植(七)添加ADC驱动_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux-内核在mini2440上的移植(七)-添加ADC驱动【2】在内核中添加ADC 驱动Linux- 内核并没有提供支持S3C2440 的ADC 驱动程序,由于移植开发实战指南中ADC部分代码在实际测试中始终输出-1,而无法通过测试,于是结合博主黄刚 HYPERLINK /u3/101649/showart.php?id=2155714 t _blank 嵌入式Linux之我行S3C2440上ADC驱动实例开发讲解的ADC驱动程序作了下修改,经过修改后有一个好处是方便地通过s3c24xx-adc.h文件中提供的宏修改通道获取采样数据,该头文件的代码也在drivers/char目录下内容为

2、:#ifndef _S3C2410_ADC_H_#define _S3C2410_ADC_H_#define ADC_WRITE(ch, prescale) (ch)16)&0 x7)#define ADC_WRITE_GETPRE(data) (data)&0 xff)#endif /* _S3C2410_ADC_H_ */驱动程序的文件名为:mini2440_adc.c位于drivers/char 目录下。由上述内容可知,ADC 驱动和触摸屏驱动若想共存,就必须解决共享“A/D 转换器”资源这个问题,因此在ADC 驱动程序中声明了一个全局的“ADC_LOCK”信号量,ADC 驱动程序的内容

3、和注解如下:#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /;自己定义的头文件,因原生内核并没有包含#include s3c24xx-adc.h#undef DEBUG/#define DEBUG#ifdef DEBUG#define DPRINTK(x.) printk(_FUNCT

4、ION_(%d): ,_LINE_);printk(#x);#else#define DPRINTK(x.) (void)(0)#endif/;定义ADC 转换设备名称,将出现在/dev/adc#define DEVICE_NAME adcstatic void _iomem *adc_base;/*定义了一个用来保存经过虚拟映射后的内存地址*/;定义ADC 设备结构typedef struct wait_queue_head_t wait;int channel;int prescale;ADC_DEV;static ADC_DEV adcdev;/;声明全局信号量,以便和触摸屏驱动程序共享

5、A/D 转换器DECLARE_MUTEX(ADC_LOCK);/;ADC驱动是否拥有A/D 转换器资源的状态变量/static volatile int OwnADC = 0;/*用于标识AD转换后的数据是否可以读取,0表示不可读取*/static volatile int ev_adc = 0;/*用于保存读取的AD转换后的值,该值在ADC中断中读取*/static int adc_data;/*保存从平台时钟队列中获取ADC的时钟*/static struct clk *adc_clk;/;定义ADC 相关的寄存器#define ADCCON (*(volatile unsigned lo

6、ng *)(adc_base + S3C2410_ADCCON) /ADC control#define ADCTSC (*(volatile unsigned long *)(adc_base + S3C2410_ADCTSC) /ADC touch screen control#define ADCDLY (*(volatile unsigned long *)(adc_base + S3C2410_ADCDLY) /ADC start or IntervalDelay#define ADCDAT0 (*(volatile unsigned long *)(adc_base + S3C24

7、10_ADCDAT0) /ADC conversion data 0#define ADCDAT1 (*(volatile unsigned long *)(adc_base + S3C2410_ADCDAT1) /ADC conversion data 1#define ADCUPDN (*(volatile unsigned long *)(adc_base + 0 x14) /Stylus Up/Down interrupt status#define PRESCALE_DIS (0 14)#define PRESCALE_EN (1 14)#define PRSCVL(x) (x) 6

8、)#define ADC_INPUT(x) (x) 3)#define ADC_START (1 0)#define ADC_ENDCVT (1 15)/;定义“开启AD 输入”宏,因为比较简单,故没有做成函数/#define START_ADC_AIN(ch, prescale)#define start_adc(ch, prescale) do ADCCON = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT(ch) ; ADCCON |= ADC_START; while(0)/*设置ADC控制寄存器,开启AD转换*/*static void sta

9、rt_adc(int ch,int prescale) unsigned int tmp; tmp = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT(ch);/(1 14)|(255 6)|(0 3);/ 0 1 00000011 000 0 0 0/此处writl()的原型是void writel(u32 b, volatile void _iomem *addr),addr是经过地址重映射后的地址 writel(tmp, ADCCON); /AD预分频器使能、模拟输入通道设为AIN0 tmp = readl(ADCCON); tmp = tmp |

10、ADC_START; /(1 f_flags & O_NONBLOCK) /*应用程序若采用非阻塞方式读取则返回错误*/ return -EAGAIN; else /*以阻塞方式进行读取*/ /*设置ADC控制寄存器,开启AD转换*/ start_adc(adcdev.channel, adcdev.prescale); /*使等待队列进入睡眠*/ wait_event_interruptible(adcdev.wait, ev_adc); /*能到这里就表示已有AD转换后的数据,则标识清0,给下一次读做判断用*/ ev_adc = 0; /*将读取到的AD转换后的值发往到上层应用程序*/ c

11、opy_to_user(buffer, (char *)&adc_data, sizeof(adc_data); /*释放获取的信号量(即:解锁)*/ up(&ADC_LOCK); return sizeof(adc_data);/;打开ADC设备的函数,一般对应于用户态程序的openstatic int adc_open(struct inode *inode, struct file *filp)int ret;/* normal ADC */ADCTSC = 0;/;初始化中断队列init_waitqueue_head(&(adcdev.wait);adcdev.channel=0;/;

12、缺省通道为“0”adcdev.prescale=0 xff;/* 申请ADC中断服务,这里使用的是共享中断:IRQF_SHARED,为什么要使用共享中断,因为在触摸屏驱动中 也使用了这个中断号。中断服务程序为:adc_irq在下面实现,IRQ_ADC是ADC的中断号,这里注意: 申请中断函数的最后一个参数一定不能为NULL,否则中断申请会失败,这里传入的是ADC_DEV类型的变量*/ret = request_irq(IRQ_ADC, adc_irq, IRQF_SHARED, DEVICE_NAME, &adcdev);if (ret) /*错误处理*/ printk(KERN_ERR IR

13、Q%d error %dn, IRQ_ADC, ret); return -EINVAL; DPRINTK( adc openedn); return 0;static int adc_release(struct inode *inode, struct file *filp)DPRINTK( adc closedn);return 0;static struct file_operations dev_fops = owner: THIS_MODULE,open: adc_open,read:adc_read,release: adc_release,;static struct misc

14、device adc_miscdev = .minor = MISC_DYNAMIC_MINOR,.name = DEVICE_NAME,.fops = &dev_fops,;static int _init dev_init(void)int ret;/* 1,从平台时钟队列中获取ADC的时钟,这里为什么要取得这个时钟,因为ADC的转换频率跟时钟有关。 系统的一些时钟定义在arch/arm/plat-s3c24xx/s3c2410-clock.c中*/adc_clk = clk_get(NULL, adc);if (!adc_clk) printk(KERN_ERR failed to ge

15、t adc clock sourcen);return -ENOENT;/*时钟获取后要使能后才可以使用,clk_enable定义在arch/arm/plat-s3c/clock.c中*/clk_enable(adc_clk);/* 2,将ADC的IO端口占用的这段IO空间映射到内存的虚拟地址,ioremap定义在io.h中。 注意:IO空间要映射后才能使用,以后对虚拟地址的操作就是对IO空间的操作, S3C2410_PA_ADC是ADC控制器的基地址,定义在mach-s3c2410/include/mach/map.h中,0 x20是虚拟地址长度大小*/adc_base=ioremap(S3

16、C2410_PA_ADC,0 x20);if (adc_base = NULL) printk(KERN_ERR Failed to remap register blockn);ret = -EINVAL; goto err_noclk;/* 3,把看ADC注册成为misc设备,misc_register定义在miscdevice.h中 adc_miscdev结构体定义及内部接口函数在第2步中讲,MISC_DYNAMIC_MINOR是次设备号,定义在miscdevice.h中*/ ret = misc_register(&adc_miscdev); if (ret) /*错误处理*/ pri

17、ntk(KERN_ERR Cannot register miscdev on minor=%d (%d)n, MISC_DYNAMIC_MINOR, ret); goto err_nomap; printk(DEVICE_NAME tinitialized!n);return 0;/以下是上面错误处理的跳转点err_noclk: clk_disable(adc_clk); clk_put(adc_clk);err_nomap: iounmap(adc_base); return ret;static void _exit dev_exit(void)free_irq(IRQ_ADC, &ad

18、cdev); /;释放中断iounmap(adc_base);/*释放虚拟地址映射空间*/if (adc_clk) /*屏蔽和销毁时钟*/clk_disable(adc_clk);clk_put(adc_clk);adc_clk = NULL;misc_deregister(&adc_miscdev);/;导出信号量“ADC_LOCK”,以便触摸屏驱动使用EXPORT_SYMBOL(ADC_LOCK);module_init(dev_init);module_exit(dev_exit);MODULE_LICENSE(GPL);MODULE_AUTHOR(singleboy);MODULE_D

19、ESCRIPTION(Mini2440 ADC Driver);说明:杂项设备(misc device)杂项设备也是在嵌入式系统中用得比较多的一种设备驱动。在 Linux 内核的include/linux 目录下有Miscdevice.h 文件,要把自己定义的misc device 从设备定义在这里。其实是因为这些字符设备不符合预先确定的字符设备范畴,所有这些设备采用主编号10,一起归于misc device,其实misc_register 就是用主标号10 调用register_chrdev()的。也就是说,misc设备其实也就是特殊的字符设备。然后打开drivers/char/Makefi

20、le 文件,在大概24 行加入ADC 驱动程序目标模块obj-$(CONFIG_EP93XX_PWM)+= ep93xx_pwm.oobj-$(CONFIG_C2PORT)+= c2port/obj-$(CONFIG_MINI2440_ADC) += mini2440_adc.oobj-y+= eeprom/obj-y+= cb710/再打开drivers/char/Kconfig 文件,定位到16行附近,加入ADC 驱动配置选项:menuconfig MISC_DEVICESbool Misc devicesdefault y-help- Say Y here to get to see o

21、ptions for device drivers from various different categories. This option alone does not add any kernel code. If you say N, all options in this submenu will be skipped and disabled.if MISC_DEVICESconfig MINI2440_ADCbool ADC driver for FriendlyARM Mini2440 development boardsdepends on MACH_MINI2440def

22、ault y if MACH_MINI2440helpthis is ADC driver for FriendlyARM Mini2440 development boardsNotes: the touch-screen-driver required this optionconfig ATMEL_PWMtristate Atmel AT32/AT91 PWM supportdepends on AVR32 | ARCH_AT91SAM9263 | ARCH_AT91SAM9RL | ARCH_AT91CAP9help This option enables device driver

23、support for the PWM channels on certain Atmel processors. Pulse Width Modulation is used for purposes including software controlled power-efficient backlights on LCD displays, motor control, and waveform generation.这样,我们就在内核中添加了ADC 驱动。【3】确认配置选项现在内核源代码目录的命令行执行:make menuconfig,依次选择如下子菜单项,找到刚刚添加的ADC 驱动

24、配置选项:Device Drivers - * Misc devices - 如图所示,按空格键选中 ADC 配置选项然后退出保存所选配置, 在命令行执行: make zImage , 将会生成arch/arm/boot/zImage,brd: module loadedadc initialized!S3C24XX NAND Driver, (c) 2004 Simtec Electronics. .说明ADC设备加载成功。“adc-test” 测试程序已经集成到我们的文件系统中, 因此在开发板的命令行终端输入:adc-test,旋转开发板上的 W1可调电阻,可以看到 ADC 转换的结果也在

25、变动,按下触摸屏时,会输出“-1” ,这和我们在驱动程序中设置的结果是一样的,如图:接下来,将进行触摸屏驱动移植附录资料:不需要的可以自行删除CentOS网络设置这里介绍一下Linux下的网络设置文件,这是网络计算机服务器的前提条件。1网络的基本设置我们在设置网络环境的时候,提前要弄清楚以下的相关信息。IP IP地址 Netmak 子网掩码Gateway 默认网关HostName 主机名称DomainName 域名DNS DNS的IP2网络设置文件无论是通过网络配置命令(下文将提到)来配置网络,还是通过图形化的配置界面,最终的配置信息都将写入到某某的文件中,也就是说一旦我们知道了这些信息都写到

26、了什么文件中或哪儿个文件中,我们就可以通过直接的修改某某文件来直接进行配置,下面就说明一下网络设置将要涉及到的几个主要的文件。不光是 CentOS,其他的UNIX系的OS都可以通过这个方法来配置网络,不过系统的不同定义也不同,比如说有些系统会说到通过直接修改文件的方法配置网络信息会导致网络环境的不稳定,提倡使用图形界面或配置命令的形式来配置网络,这里要特别的注意。(1)文件 /etc/sysconfig/network这个/etc/sysconfig/network文件是定义hostname和是否利用网络的不接触网络设备的对系统全体定义的文件。设定形式:设定值=值/etc/sysconfig/

27、network的设定项目如下:NETWORKING 是否利用网络 GATEWAY 默认网关IPGATEWAYDEV 默认网关的接口名HOSTNAME 主机名DOMAIN 域名(2)文件 /etc/sysconfig/network-scripts/ifcfg-eth0/etc/sysconfig/network-scripts在这个目录下面,存放的是网络接口(网卡)的制御脚本文件(控制文件),ifcfg- eth0是默认的第一个网络接口,如果机器中有多个网络接口,那么名字就将依此类推ifcfg-eth1,ifcfg-eth2,ifcfg- eth3.(这里面的文件是相当重要的,涉及到网络能否正

28、常工作)设定形式:设定值=值设定项目项目如下:DEVICE 接口名(设备,网卡)BOOTPROTO IP的配置方法(static:固定IP, dhcpHCP, none:手动) HWADDR MAC地址ONBOOT 系统启动的时候网络接口是否有效(yes/no)TYPE 网络类型(通常是Ethemet)NETMASK 网络掩码IPADDR IP地址IPV6INIT IPV6是否有效(yes/no)GATEWAY 默认网关IP地址这里有一个例子:CODE:rootlinux # cat -n /etc/sysconfig/network-scripts/ifcfg-eth0 1 DEVICE=e

29、th0 2 BOOTPROTO=static 3 BROADCAST=55 4 HWADDR=00:0C:2x:6x:0 x:xx 5 IPADDR=3 6 NETMASK= 7 NETWORK= 8 ONBOOT=yes 9 TYPE=Ethernet(3)文件 /etc/resolv.conf这个文件是用来配置主机将用的DNS服务器信息。在这个文件中如果不设置DNS服务器的IP地址,那么在通信的时候,将无法指定像 HYPERLINK /./ t _blank url=/url/url这样的域名。(DNS是Domain NameSystem的简称,中文名称域名解析服务器,主要是IP和域名转换

30、功能)/etc/resolv.conf的设定项目:domain 定义本地域名search 定义域名和搜索列表nameserver定义被参照的DNS服务器的IP地址(最多可指定3个)一般来说最重要的是第三个nameserver项目,没有这项定义,用域名将无法访问网站,并且yum等服务将无法利用(4)文件 /etc/hosts/etc/hosts这个文件是记载LAN内接续的各主机的对应HostName和IP用的。在LAN内,我们各个主机间访问通信的时候,用的是内网的IP地址进行访问(例:2,3),从而确立连接进行通信。除了通过访问IP来确立通信访问之外,我们还可以通过HostName进行访问,我们

31、在安装机器的时候都会给机器起一个名字,这个名字就是这台机器的HostName,通过上图可以看到,HostA的 hostname是centos1,HostB的hostname是centos2那我们怎么能不但通过IP确立连接,通过这个IP对应的 HostName进行连接访问呢?解决的办法就是这个/etc/hosts这个文件,通过把LAN内的各主机的IP地址和HostName的一一对应写入这个文件的时候,就可以解决问题。要在HostA上用ssh访问HostB的时候,在命令行下做这样的操作: - CODE:rootcentos1 # ssh 3email=root3sroot3s/email pass

32、word:Last login: Mon Dec 25 15:04:58 2006 from centos1rootcentos2 #访问成功后,我们看到hostname的地方变化了。那么我们用hostname试试看: - CODE:rootcentos1 # ssh centos2ssh:centos2: Name or service not known 提示错误,不知道主机rootcentos1 #那么我们编辑/etc/hosts文件,将HostB的IP和hostname的对应关系写入这个文件,如果主机有域名,可以将域名写在IP地址之后hostname之前,并且用空格隔开,形式如第三行的

33、设置。 - CODE:rootcentos1 # cat -n /etc/hosts 1 # Do not remove the following line, or various programs 2 # that require network functionality will fail. 3 localhost.localdomain localhost 4 3 centos2rootcentos2 #然后我们再从复#ssh centos2的操作 - CODE:rootcentos1 # ssh centos2email=rootcentos2srootcentos2s/email

34、 password:Last login: Mon Dec 25 15:05:07 2006 from centos1rootcentos2 #可以看到访问成功了,这个文件就是这样的,倘若你要用windowsXP访问局域网中的linux你也可以用上面的方法,只不过在 windowsXP下面你也要修改hosts这个文件,文件路径:C:WINDOWSsystem32driversetchosts,在这个文件中添加你要访问的局域网中的主机的IP和hostname,就能通过主机名访问主机了。3网络基本命令(1)network service的制御网络接口配置信息改动后,网络服务必须从新启动,来激活网络

35、新配置的使得配置生效,这部分操作和从新启动系统时时一样的作用。制御(控制)是/etc/init.d/network这个文件,可以用这个文件后面加上下面的参数来操作网络服务。例如:rootlinux #/etc/init.d/networkrestart同样也可以用service这个命令来操作网络服务例如:rootlinux #service network restartstart 启动stop 停止restart 再启动reload 和再启动一样(.)status 状态表示如果服务器软件采用rpm的方式安装,以上的内容大多数都对应。(2)network管理命令网络管理还有一些常用的命令,下面

36、介绍几个常用的命令。ifconfignetstathostnamepingtracerouteifconfig这个命令可以用于,网络接口的启动/停止,更改设置和表示网络状态,在不添加任何参数的情况下,这个ifconfig可以表示网络接口的状态。例如:rootlinux # ifconfigeth0 Link encap:Ethernet HWaddr00:xx:xx:xx:04:45 inet addr:1 Bcast:55 Mask: inet6 addr: fe80:20c:29ff:fe61:445/64 Scopeink UPBROADCAST RUNNING MULTICAST MT

37、U:1500 Metric:1 RXpackets:472 errors:0 dropped:0 overruns:0 frame:0 TXpackets:445 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RXbytes:35804 (34.9 KiB) TX bytes:53012(51.7 KiB) Interrupt:185 Base address:0 x1080lo Link encapocal Loopback inet addr: Mask: inet6 addr: :1/128 Sc

38、ope:Host UPLOOPBACK RUNNING MTU:16436 Metric:1 RXpackets:8 errors:0 dropped:0 overruns:0 frame:0 TXpackets:8 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RXbytes:560 (560.0 b) TX bytes:560 (560.0b)rootlinux #看看ifconfig的输出内容1. Link encap 2. HWaddr MAC地址 3.inet addr IP地址(IPV4) 4.

39、Bcast 广播地址 5. Mask 衍码 6. inet6 addr IP地址(IPV6) 7. UP 启动中 8. BROADCAST 广播地址有效 9. RUNNING 动作10. MTU 网络接口的MTU(MaximumTransfer Unit:Ethernet最大传送frame值)11. Metric 12. RX packets 受信包数13. TX packets 送信包数14. collisions 15. interrupt IRQ号码16. Baseaddress I/O地址通过这个命令还可以up(开启)和down(关闭)某个网络接口(网卡),例如我们关闭eth0可以用下

40、面的命令:rootlinux #ifconfigeth0 down相反的开启如下:rootlinux #ifconfigeth0 up通过这个命令还可以设置网络接口(网卡),例如我们将eth0的IP设置成1,子网衍码设置成如下:rootlinux #ifconfigetho inet 1 netmask 假如有多个网络接口的情况下,ethX的X部分用网络接口码(数字,例如eth0,eth1,eth2代替)。netstat这条命令是显示网络各种情况的命令,在不跟随任何参数被执行的情形下,将表示Active Internet connections和ActiveUNIX domain socket

41、s的情报。看看下面的输出信息:这里是6正在通过ssh连接1的情形rootlinux #netstatActive Internetconnections (w/o servers)Proto Recv-Q Send-QLocal Address ForeignAddress State tcp 0 0 :ffff:1:ssh :ffff:6:4757 ESTABLISHEDActive UNIX domainsockets (w/o servers)Proto RefCntFlags Type State I-Node Pathunix 11 DGRAM 5202 /dev/logunix 2

42、 DGRAM 5997 /var/run/hal/hotplug_socketunix 2 DGRAM 2536 udevdunix 2 DGRAM 7474unix 3 STREAM CONNECTED 5995 /var/run/dbus/system_bus_socketunix 3 STREAM CONNECTED 5994unix 3 STREAM CONNECTED 5974unix 3 STREAM CONNECTED 5973unix 2 DGRAM 5933unix 2 DGRAM 5923unix 2 DGRAM 5876unix 2 DGRAM 5819unix 2 DG

43、RAM 5805unix 2 DGRAM 5786unix 2 DGRAM 5723unix 3 STREAM CONNECTED 5388unix 3 STREAM CONNECTED 5387unix 2 DGRAM 5280unix 2 DGRAM 5210rootlinux #主要的选项:-a 显示所有socket,包括正在监听的。-c 每隔1秒就重新显示一遍,直到用户中断它。-i 显示所有网络接口的信息,格式同“ipconfig -e”。-n 以网络IP地址代替名称,显示出网络连接情形。-r 显示核心路由表,格式同“route -e”。-t 显示TCP协议的连接情况。-u 显示UDP协议的连接情况。-v 显示正在进行的工作。以上的选项可以结合使用,例如我们想知道正在开放的TCP端口,可以用下面的形势执行察看:rootlinux #netstat -atActive Internetco

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论