在uClinux下CAN总线控制器驱动程序的设计过程
- 格式:doc
- 大小:85.50 KB
- 文档页数:6
CAN-USB适配器设计*****指导老师:***学院名称:*****专业班级:****设计提交日期:**年**月摘要随着现场总线技术和计算机外设接口技术的发展,现场总线与计算机快速有效的连接又有了更多的方案。
USB作为一种新型的接口技术,以其简单易用、速度快等特点而备受青睐。
本文介绍了一种基于新型USB接口芯片CH372的CAN总线网络适配器系统的设计,提出了一种使用USB接口实现CAN总线网络与计算机连接的方案。
利用芯片CH372可在不了解任何USB协议或固件程序甚至驱动程序的情况下,轻松地将并口或串口产品升级到USB接口。
该系统在工业现场较之以往的系统,可以更加灵活,高速,高效地完成大量数据交换,并可应用于多种控制系统之中,具有很大的应用价值。
关键词:USB;CH372;CAN;SJA100;适配器目录1.设计思想 (3)2.CAN总线与USB的转换概述 (4)3. 适配器硬件接口设计 (5)3.1 USB接口电路 (5)3.2 CAN总线接口电路 (7)4.USB通用设备接口芯片CH372 (8)4.1 概述 (8)4.2 引脚功能说明 (9)4.3 内部结构 (9)4.4 命令 (10)5.软件设计 (10)5.1 概述 (10)5.2主监控程序设计 (12)5.3 CAN和USB接口芯片的初始化 (13)5.4 CAN报文的发送 (15)5.5 CAN报文的接收 (17)5.6.自检过程 (19)5.7 USB下传子程序设计 (20)5.8 USB上传子程序设计 (22)5.9.USB—CAN转换器计算机端软件设计 (23)6. 抗干扰措施 (25)7. 估算成本 (26)8. 应用实例介绍 (27)9 总结及设计心得 (28)10 参考文献 (28)1 设计思想现场总线网络技术的实现需要与计算机相结合。
目前,在微机上扩展CAN总线接口设备一般采用PCI总线或者RS-232总线。
PCI虽然仍是高速外设与计算机接口的主要渠道,但其主要缺点是占用有限的系统资源、扩展槽地址;中断资源有限;并且插拔不方便;价格较贵;而且设计复杂、需有高质量的驱动程序保证系统的稳定;且无法用于便携式计算机的扩展;RS-232虽然插拔方便,但是传输速率太慢。
本文由我司收集整编,推荐下载,如有疑问,请与我司联系基于MCP2515的Linux CAN总线驱动程序设计(一)2017/06/06 0 时间:2016-12-12作者:华清远见1.前言 CAN(Controller Area Network)总线,即控制器局域网总线,是一种有效支持分布式控制或实时控制的串行通信网络。
由于其高性能、高可靠性、及独特的设计和适宜的价而广泛应用于工业现场控制、智能楼宇、医疗器械、交通工具以及传感器等领域,并已被公认为几种最有前途的现场总线之一。
CAN总线规范已经被国际标准化组织制订为国际标准ISO11898,并得到了众多半导体器件厂商的支持。
本文使用华清远见FS2416平台。
FS2416使用Socket网络设备驱动和字符设备驱动两种方式向Linux内核提供MCP2515的驱动,本文详细介绍了使用Socket方式设计的基于MCP2515的Linux CAN总线驱动程序。
2.FS2416简介 图1 FS2416开发板 FS2416采用的是三星公司的ARM926EJ内核CPU S3C2416,无论从性能上,还是成本上, S3C2416都强于2440,是2440的最完美替代者。
作为32/16 bit RISC指令集、低成本、低功耗、高性能的微处理器。
S3C2416使用了65nm的制作工艺从而降低成本、功耗及提高性能,其使用的ARM926EJ的核心,集成了2D图形加速,添加了低功耗模式,支持内部ROM/RAM引导,支持moviNand启动和低功耗音频编解码。
此外相对于其他ARM9芯片,它的外设也得到了升级,有更多的资源。
图2 FS2416板级资源介绍 3.MCP2515简介 MCP2515是一种独立的CAN总线通信控制器,是Microchip公司首批独立CAN 解决方案的升级器件,其传输能力较Microchip公司原有CAN控制器(MCP2510)高两倍,最高通信速率可达到1Mbps。
CAN总线在嵌入式Linux下驱动程序的实现时间:2009-11-05 09:41:22 来源:微计算机信息作者:黄捷峰蔡启仲郭毅锋田小刚1 引言基于嵌入式系统设计的工业控制装置,在工业控制现场受到各种干扰,如电磁、粉尘、天气等对系统的正常运行造成很大的影响。
在工业控制现场各个设备之间要经常交换、传输数据,需要一种抗干扰性强、稳定、传输速率快的现场总线进行通信。
文章采用CAN总线,基于嵌入式系统32位的S3C44B0X微处理器,通过其SPI接口,MCP2510 CAN控制器扩展CAN总线;将嵌入式操作系统嵌入到S3C44B0X微处理器中,能实现多任务、友好图形用户界面;针对S3C44B0X微处理器没有内存管理单元MMU,采用uClinux嵌入式操作系统。
这样在嵌入式系统中扩展CAN设备关键技术就是CAN设备在嵌入式操作系统下驱动程序的实现。
文章重点解决了CAN总线在嵌入式操作系统下驱动程序实现的问题。
对于用户来说,CAN设备在嵌入式操作系统驱动的实现为用户屏蔽了硬件的细节,用户不用关心硬件就可以编出自己的用户程序。
实验结果表明驱动程序的正确性,能提高整个系统的抗干扰能力,稳定性好,最大传输速率达到1Mb/s;硬件的错误检定特性也增强了CAN的抗电磁干扰能力。
2 系统硬件设计系统采用S3C44B0X微处理器,需要扩展CAN控制器。
常用的CAN控制器有SJA1000和MCP2510,这两种芯片都支持CAN2.0B标准。
SJA1000采用的总线是地址线和数据线复用的方式,但是嵌入式处理器外部总线大多是地址线和数据线分开的结构,这样每次对SJA1000操作时需要先后写入地址和数据2次数据,而且SJA1000使用5V逻辑电平。
所以应用MCP2510控制器进行扩展,收发器采用82C250。
MCP2510控制器特点:1.支持标准格式和扩展格式的CAN数据帧结构(CAN2.0B);2.0~8字节的有效数据长度,支持远程帧;3.最大1Mb/s的可编程波特率;4.2个支持过滤器的接受缓冲区,3个发送缓冲区;5.SPI高速串行总线,最大5MHz;6.3~5.5V宽电压范围供电。
CAN总线软件编程流程1.初始化CAN总线接口:先选择一个适合的硬件接口,根据硬件接口的数据手册与相应的寄存器进行初始化设置,包括波特率、工作模式等通信参数的配置。
2.配置CAN总线参数:设置CAN总线的参数,如通信速率、帧格式、收发过滤器等。
这些参数的设置要根据实际应用需求进行。
3.监听CAN总线:使能CAN总线接收中断,通过中断响应的方式获取CAN总线上的数据帧。
这样可以实时监听总线上的数据。
4.发送CAN数据帧:将需要发送的数据组成CAN数据帧,设置好帧的标识符、数据长度、数据内容等信息,并通过CAN总线接口发送出去。
在发送过程中,可以根据需要设置发送缓冲区,以便处理发送失败的情况。
5.接收CAN数据帧:通过CAN总线接收中断获取到新的数据帧,解析出数据帧的标识符、数据长度、数据内容等信息,并进行处理。
可以根据数据帧的标识符对接收到的数据进行分类和分析。
6.处理CAN错误:监测CAN总线上的错误,如位错误、格式错误等,及时进行处理并进行相应的错误处理流程。
可以通过错误中断、错误计数器等方式实现错误检测和处理。
7.进行其他相关操作:在CAN总线通信过程中还可能涉及到其他的相关操作,如同步、节点管理、故障检测等。
根据实际应用需求进行相应的处理。
8.关闭CAN总线接口:在软件结束运行之前,应该关闭CAN总线接口,释放资源,并进行相关清理操作,确保资源的正常释放。
9.错误处理和异常流程:在CAN总线通信过程中,可能会遇到一些错误和异常情况,比如通信超时、数据出错等。
在软件编程时需要考虑这些异常情况,设置相应的错误处理和异常流程,避免系统崩溃或数据丢失。
总的来说,CAN总线软件编程流程包括初始化CAN总线接口、配置CAN总线参数、监听CAN总线、发送CAN数据帧、接收CAN数据帧、处理CAN错误、进行其他相关操作、关闭CAN总线接口以及错误处理和异常流程等步骤。
通过这些步骤,可以实现CAN总线的稳定通信和数据交换。
嵌入式系统课程设计题目1.ARM系统在LED显示屏中的应用(利用ARM系统控制彩色LED显示屏)2.ARM-Linux 嵌入式系统在农业大棚中的应用(温度、湿度和二氧化碳浓度是影响棚栽农作物生长的3 大要素。
为了实现农业大棚中这3 种要素数据的远程实时采集,引入了当前嵌入式应用中较为成熟的ARM9 微处理器和Linux 嵌入式操作系统技术, 采用温度传感器PH100TMPA、湿度传感器HM1500 和二氧化碳浓度传感器NAP221A ,设计一种基于TCP/ IP 协议的嵌入式远程实时数据采集系统方案。
从硬件设计和软件实现2方面对该系统进行具体设计。
)3.ARM 嵌入式处理器在智能仪器中的应用(设计一种基于ARM 嵌入式处理器系统的智能仪器的硬件和软件设计方案, 并结合uc/o s2II或者Linux嵌入式实时操作系统, 给出一套完整的任务调度和管理的方法, 最后用实例说明)4.ARM系统在汽车制动性能测试系统中的应用(采用ARM系统构建一个路试法的汽车制动性能测试系统)5.ARM 嵌入式控制器在印染设备监控中的应用(针对拉幅热定型机,设计一种基于485 总线的分布式监控系统。
用ARM 嵌入式控制器实现主、从电机的同步运行和烘房温度的控制;在PC 机上用VB6. 0 设计转速和温度的监控画面;实现ARM、变频器和PC 机之间的数据通信。
)6.基于ARM系统的公交车多功能终端的设计(完成电子收费、报站、GPS定位等功能)7.基于ARM9的双CAN总线通信系统的设计(设计一种基于ARM9内核微处理器的双路CAN总线通信系统。
完成系统的总体结构、部分硬件的设计,系统嵌入式软件的设计,包括启动引导代码U - boot、嵌入式L inux - 操作系统内核、文件系统以及用户应用管理软件四个部分。
)8.基于ARM9 和Linux 的嵌入式打印终端系统(嵌入式平台上的打印终端的外围电路连接设计、嵌入式Linux 的打印机驱动程序开发和应用程序的开发)9.基于ARM 的车载GPS 终端软硬件的研究(重点研究基于ARM 的导航系统的软硬件设计)10.ARM系统在B超系统中的应用(完成系统软件硬件设计,包括外围电路)11.基于ARM 的嵌入式系统在机器人控制系统中应用(提出一种基于ARM、DSP 和arm-linux 的嵌入式机器人控制系统的设计方法, 完成控制系统的功能设计、结构设计、硬件设计、软件设计)12.基于ARM的视频采集系统设计(完成系统软件硬件设计,包括外围电路,采用USB接口的摄像头)13.基于ARM的高空爬壁机器人控制系统(构建一种经济型的爬壁机器人控制平台, 与上位机视觉定位和控制系统结合,使其适用于导航与定位、运动控制策略、多机器人系统体系结构与协作机制等领域。
CAN总线CAN是控制器局域网络(Controller Area Network,CAN)的简称,由德国BOSCH公司开发,并最终成为国际标准(ISO 11898-1)。
CAN总线主要应用于工业控制和汽车电子领域,是国际上应用最广泛的现场总线之一。
1 CAN总线简介CAN总线是一种串行通信协议,能有效地支持具有很高安全等级的分布实时控制。
CAN 总线的应用范围很广,从高速的网络到低价位的多路接线都可以使用CAN。
在汽车电子行业里,使用CAN 连接发动机的控制单元、传感器、防刹车系统等,传输速度可达1 Mbps。
与前面介绍的一般通信总线相比,CAN总线的数据通信具有突出的可靠性、实时性和灵活性,在汽车领域的应用最为广泛,世界上一些著名的汽车制造厂商 都采用CAN总线来实现汽车内部控制系统与各检测和执行机构之间的数据通信。
目前,CAN总线的应用范围已不仅仅局限于汽车行业,而且已经在自动控制、航 空航天、航海、过程工业、机械工业、纺织机械、农用机械、机器人、数控机床、医疗器械及传感器等领域中得到了广泛应用。
CAN总线规范从最初的CAN 1.2 规范(标准格式)发展为兼容CAN 1.2 规范的CAN 2.0规范(CAN 2.0A为标准格式,CAN 2.0B为扩展格式),目前应用的CAN器件大多符合CAN 2.0规范。
2 CAN总线的工作原理当CAN 总线上的节点发送数据时,以报文形式广播给网络中的所有节点,总线上的所有节点都不使用节点地址等系统配置信息,只根据每组报文开头的11位标识符(CAN 2.0A规范)解释数据的含义来决定是否接收。
这种数据收发方式称为面向内容的编址方案。
当某个节点要向其他节点发送数据时,这个节点的处理器将要发送的数据和自己的标识符传送给该节点的CAN总线接口控制器,并处于准备状态;当收到总 线分配时,转为发送报文状态。
数据根据协议组织成一定的报文格式后发出,此时网络上的其他节点处于接收状态。
opLINUXCNC源程序学习源程序的树结构如下:Overview of the emc2 directory (generated by tree -I .git -d):。
|—— app—defaults|—— bin (user mode binaries)|-- configs||—- 5axis||-- boss||—— common||-— dallur—thc| |—- demo_mazak (sample mazak config files)||—- demo_sim_cl (sample sim with ladder IO)||-— demo_step_cl (sample stepper with ladder IO)| |—- etch-servo||-— halui_halvcp||-— hexapod—sim| |—- lathe—pluto||-— m5i20 (sample servo using Mesa PCI)| |—- max| |-- motenc (sample servo using Vital PCI)| |—- nist—lathe| |—— plasma—thc||-— plasma-thc—sim| |-- ppmc||—— puma||—- scara| |-- sim (simulated motion and IO)| |—— stepper (parport stepper driver)||-- stepper-gantry||—— stepper-xyza| |-- stg (sample servo using STG ISA)| |-- univpwm (sample PICO servo generator)| |-- univstep (sample PICO stepper generator)|`—— vti|—— debian (files needed to build deb packages)| |—— extras—Ubuntu-5.10 (extra files for Ubuntu 5.10)| ||—— etc||||-- modprobe.d||||—- udev|| | | |-— rules。
linux设备驱动程序的设计与实现
Linux设备驱动程序的设计与实现是一个涉及底层系统编程和硬件交互的复杂过程。
下面是一个简单的步骤指南,以帮助你开始设计和实现Linux设备驱动程序:
1. 了解硬件:首先,你需要熟悉你要驱动的硬件设备的规格和特性。
这包括硬件的内存空间、I/O端口、中断请求等。
2. 选择驱动程序模型:Linux支持多种设备驱动程序模型,包括字符设备、块设备、网络设备等。
根据你的硬件设备和需求,选择合适的驱动程序模型。
3. 编写Makefile:Makefile是一个文本文件,用于描述如何编译和链接你的设备驱动程序。
它告诉Linux内核构建系统如何找到并编译你的代码。
4. 编写设备驱动程序:在Linux内核源代码树中创建一个新的驱动程序模块,并编写相应的C代码。
这包括设备注册、初始化和卸载函数,以及支持读写和配置硬件的函数。
5. 测试和调试:编译你的设备驱动程序,并将其加载到运行中的Linux内核中。
使用各种测试工具和方法来验证驱动程序的正确性和稳定性。
6. 文档和发布:编写清晰的文档,描述你的设备驱动程序的用途、用法和已知问题。
发布你的代码以供其他人使
用和改进。
linux 开发新驱动步骤Linux作为一款开源的操作系统,其内核源码也是开放的,因此,许多开发人员在Linux上进行驱动开发。
本文将介绍在Linux上进行新驱动开发的步骤。
第一步:确定驱动类型和接口在进行驱动开发前,需要确定驱动类型和接口。
驱动类型包括字符设备驱动、块设备驱动、网络设备驱动等。
接口包括设备文件、系统调用、ioctl等。
根据驱动类型和接口的不同,驱动开发的流程也有所不同。
第二步:了解Linux内核结构和API驱动开发需要熟悉Linux内核的结构和API。
Linux内核由许多模块组成,每个模块都有自己的功能。
API是应用程序接口,提供了许多函数和数据结构,开发人员可以使用这些函数和数据结构完成驱动开发。
第三步:编写驱动代码在了解了Linux内核结构和API后,就可以编写驱动代码了。
驱动代码需要按照Linux内核的编码规范编写,确保代码风格统一、可读性好、可维护性强等。
在编写代码时,需要使用API提供的函数和数据结构完成相应的功能。
第四步:编译驱动代码和内核模块驱动代码编写完成后,需要编译成内核模块。
编译内核模块需要使用内核源码中的Makefile文件。
编译完成后,会生成一个.ko文件,这个文件就是内核模块。
第五步:加载和卸载内核模块内核模块编译完成后,需要加载到Linux系统中。
可以使用insmod命令加载内核模块,使用rmmod命令卸载内核模块。
在加载和卸载内核模块时,需要注意依赖关系,确保依赖的模块已经加载或卸载。
第六步:调试和测试驱动开发完成后,需要进行调试和测试。
可以使用printk函数输出调试信息,在/var/log/messages文件中查看。
测试时需要模拟各种可能的情况,确保驱动程序的稳定性和可靠性。
Linux驱动开发需要掌握Linux内核结构和API,熟悉驱动类型和接口,按照编码规范编写驱动代码,并进行编译、加载、调试和测试。
只有掌握了这些技能,才能进行高效、稳定和可靠的驱动开发。
在uClinux下CAN总线控制器驱动程序的设计过程在uClinux下CAN总线控制器驱动程序的设计过程CAN总线技术是现今流行的一种先进的现场总线技术,可以有效的支持分布式控制和实时控制的串行通信网络。
由于CAN总线具有通信速率高,可靠性高,连接方便和性能价格比高等诸多优点,因此在嵌入式系统开发中有普遍的应用。
目前,CAN总线通信控制芯片众多,要在uClinux平台下开发基于 CAN总线的应用系统,就需要自己开发uClinux下的驱动程序。
本文将基于一个CAN 总线在汽车电子中的应用详细介绍在uClinux下CAN总线控制器驱动程序的设计过程。
1 系统硬件结构本嵌入式系统主要的硬件组成为:处理器采用三星公司的S3C44B0X,CAN总线控制器和收发器分别采用MicroChip公司的MCP2510和 MCP2551。
开发一个uClinux的驱动,在熟悉uClinux内核结构之外,大量的工作在于阅读相应的控制芯片手册。
硬件信息决定驱动的主要结构。
S3C44B0X 采用的是ARM公司的16/32位ARM7TDMI内核,它是三星公司为一般应用提供的高性价比和高性能的微控制器解决方案,特别适合对成本和功耗敏感的应用场合。
MCP2510是一款带有符合工业标准的SPI接口的CAN总线控制芯片,它支持CAN技术规范V2.0A/B,并能够发送和接收标准的和扩展的信息帧,同时具有接收滤波和信息管理的功能。
MCP2510在目前市场上是体积最小、最易于使用也是最节约成本的独立CAN控制器。
MCP2551是与 MCP2510相配的高速CAN总线收发器,它担负着节点和总线之间接收和发送电平转换的任务。
MCP2510通过SPI接口与S3C44B0X 进行数据传输,最高数据传输数率可达5 Mb/s。
MCP2510再通过CAN收发器连接到CAN总线上,CAN总线上可以挂接多个节点,S3C44B0X通过MCP2510与CAN 总线上的其它微处理器进行通信。
MCP2510内含3个发送缓冲区和两个接收缓冲区,同时具有灵活的中断管理能力,帧屏蔽和过滤、帧优先级设定等特性,这使得微处理器对CAN 总线的操作变得非常简便。
系统原理如图1所示。
图1 嵌入式应用系统结构2 CAN总线应用系统的软件设计2.1 嵌入式操作系统选择uClinuxuClinux是Linux2.0版本得一个分支,被设计用在微型控制应用领域。
uClinux具备标准Linux系统的稳定性,并且支持Linux内核约定的全部特性。
uClinux同标准Linux的最大的区别就是在于内存管理。
标准Linux是针对有内存管理单元(memory management unit,MMU)的处理器设计的。
在这种处理器上,虚拟地址被送到MMU,MMU把虚拟地址映射为物理地址。
嵌入式应用对成本和实时性敏感,其使用的 CPU中有很多都没有MMU,例如本系统采用的S3C44B0X就是一款不带MMU 的微处理器。
标准Linux无法适用于这部分嵌入式应用。
uClinux 通过对标准Linux中内存管理的改写,去掉了对MMU的依赖,保存了Linux 内核的大多数优点,因此它在嵌入式应用中有很好的前景。
uClinux的应用主要体现在驱动程序的编写和上层应用软件的编写。
所以,针对CAN总线控制器MCP2510的驱动程序需要我们自己编写。
2.2 CAN总线控制器驱动程序编写驱动程序是应用程序与硬件之间的一个中间软件层。
它使某个特定的硬件响应一个定义良好的内部编程接口,同时完全隐蔽了设备的工作细节。
用户通过一组标准化的调用来完成相关操作,这些标准化的调用是和具体设备驱动无关的,而驱动程序的任务就是把这些调用映射到具体设备对于实际硬件的特定操作上。
驱动程序应该为应用程序展现硬件的所有功能,不应该强加其它的约束,对于硬件使用的权限和限制应该由应用程序层控制。
驱动程序设计主要需要考虑下面3个方面:提供尽量多的选项给用户;提高驱动程序的速度和效率;尽量使驱动程序简单,使之易于维护。
uClinux支持的设备驱动可分为3种:字符设备,块设备,网络接口设备。
MCP2510就属于字符设备。
字符设备是uClinux中最简单的设备,所谓字符设备就是以字节为单位逐个进行I/O操作的设备。
在uClinux中它们被映射为文件系统的一个节点,这个设备就像是一个普通文件,应用程序使用标准系统调用对它进行打开(open)、读取(read)、写入(write)和关闭(release)等操作。
2.2.1 驱动程序中定义的主要数据结构驱动程序中读写函数需要传输多个CAN消息,我们根据CAN通信协议和系统应用的需要,设计一个称为CanData的结构体来定义所传输的数据struct{unsigned int id;unsigned char data[8];unsigned char dlc;int IsExt;int rxRTR;)CanData;其中id为CAN消息ID号;data是要传输的消息数据,最大是8个字节;dlc表示实际传输的数据长度,取值范围为0到8;IsExt是判断CAN消息是否使用扩展ID;rxRTR是判断该消息是数据帧还是远程帧。
MCP2510中有3个发送缓冲区,可以循环使用,也可以只使用一个发送缓冲区,但是必须保证在发送的时候,前一次的数据已经发送结束。
两个接收缓冲区也是一样。
处理器通过SPI接口对缓存区进行读取和写入。
MCP2510对CAN总线的数据发送没有限制,只要用处理器通过SPI接口将待发送的数据写入MCP2510的发送缓存区,然后再调用RTS(发送请求)命令即可将数据发送到CAN 总线上。
而对CAN总线上的数据接收是通过两个接收缓冲区,两个接收屏蔽器,6个接收过滤器的组合来实现的。
CAN总线上的帧只有同时满足至少任意一个接收屏蔽器和一个接收过滤器的条件才可以进入接收缓冲区。
这里定义了一个MCP2510 REV的数据结构,用于记录接收缓冲区运行的各种状态struct{CanDate MCP2510_Candata[128];int nCanRevpos;int nCanReadpos;int loopbackmode;wait_queue_head_t wq;spinlock_t lock;)MCP2510_REV;该结构中首先定义了一个接收缓冲区,nCanRevpos和nCanReadpos分别表示接收缓冲区和用户读取缓冲区数据的状态;loopbackmode表示支持回环模式,该模式可使器件内部发送缓冲器和接受缓冲器之间进行报文自发自收;wq 定义的是一个等待队列,包含一个锁变量和一个正在睡眠进程链表,作用是当有好几个进程都在等待某件事时,uClinux会把这些进程记录到这个等待队列;lock定义的是自旋锁,自旋锁是基于共享变量来工作的,函数可以通过给某个变量设置一个特殊值来获得锁。
而其它需要锁的函数则会循环查询锁是否可用,作用是实现互斥访问。
2.2.2 驱动程序的接口驱动程序的接口主要分为3部分:①与设备的接口,完成对设备的读写等操作;②与内核通信的接口,由file_operations数据结构完成;③与系统启动代码的接口,完成对设备的初始化。
uClinux继承了LimLx操作系统下用户对设备的访问方式。
设备驱动与内核通信时使用的是设备类型,主次设备号等参数,但是对于应用程序的用户来说比较难于理解和记忆,所以uClinux使用了设备文件的概念。
它抽象了对硬件文件的管理,为用户程序提供了一个统一的、抽象的虚拟文件系统 (virtual file system,VFS)界面。
如图2所示,VFS主要由一组标准的,抽象的文件操作构成,以系统调用的形式提供给用户,如open()、 release()、read()、write()、ioctl()等。
图2 文件层次结构内核是通过主设备号这个变量将设备驱动程序和设备文件相连的,而构成驱动程序的一个重要数据结构就是file_operations,内核就是通过这个结构来访问驱动程序的。
file_operations结构定义于linux/fs.h文件中,它包含指向驱动程序内部大多数函数指针,它的每一个成员名称对应着一个系统调用。
系统引导时,内核调用每一个驱动程序的初始化函数,将驱动程序的主设备号以及程序内部的函数地址结构的指针传输给内核。
这样,内核就能通过设备驱动程序的主设备号索引访问驱动程序内部的子程序,完成打开,读写等操作。
下面给出了file_operations结构体中的一些主要成员struct file_operations{struct module *owner;//module的拥有者loff_t(*llseek)(struct file *,loff_t,int);//移动文件指针的位置,只能用于可以随机存取的设备ssize_t(*write)(struct file *,const char *,size_t,loff_t *);//向字符设备中写入数据ssize_t(*read)(struct file *,char *,size_t,loft_t *);//从设备中读取数据,与write类似unsigned int(*poll)(struct file *,struct poll_table_struct *);//用于查询设备是否可读写或处于某种状态int(*ioctl)(struct inode *,struct file *,unsigned int,unsigned long);//控制设备,除读写操作外的其它控制命令int(*mmap)(struct file *,struct vm_area_struct *);//用于把设备的内容映射到地址空间int(*lock)(struct file *,int,struct file lock*);//文件锁定,用于文件共享时的互斥访问int(*open)(struct inode *,struct file *);//打开设备进行I/O操作int(*release)(struct inode *,struct file *);//关闭设备并释放资源……};//file_operations结构中的成员全部是函数指针,所以实质上就是函数跳转表由于在file_operations结构中,每个字段都必须指向驱动程序中实现特定操作的函数,可以想象,随着内核新功能不断的增加,file_operations结构也就会变得越开越庞大。
所以,现在通常采用“标记化”的方法来为该结构初始化,即对驱动中用到的函数记录到相应字段中,没用到的就不管,这样代码就精简了许多。
代码片断如下static struct file_operations s3c44b0x_fops={owner: THIS_MODULE,write: mcp2510_write,read: mcp2510_read,ioctl: mcp2510_ioctl,open: mcp2510_open,release: mcp2510_release,};要注意的是这种表示方法不是标准C语法,而是uClinux下GNU 编译器的一种特殊扩展。