2 Linux下的统一驱动
这些总线有一些共性,也就是驱动要实现的内容,主要包括单字节数据收发、数据流收发以及工作模式控制等。在这些共性的基础上,一般都需要向上层提供一个统一的接口,以使得对使用这些API的应用程序而言(下层总线无论是RS-232、SPI、I2C,还是1-Wire)都不需要做任何改变。同时,还要对下层也提供一个通用接口,使得不同的总线都能与上层统一接口协调通信。该驱动的结构框架如图1所示。
本文主要讨论的是总线驱动部分,而应用层和物理层在测试的时候,也可用两个简单的例子来验证设计结果。
2.1 注册一个新设备号
首先可为统一接口的总线定义一个新的设备号240,而且以后注册的总线子设备都以此为主设备号。假如现在注册了一个1-Wire和一个I2C总线接口,那么,它们两者的主设备号都为240,而次设备号不同。如果1-Wire的次设备号为0,而I2C的次设备号为1,那么就可将两条总线区分开来了。此时的程序如程序片段一所示。
程序片段一:
2.2 设备接口层
为了实现统一的接口,有必要定义一个统一的字符设备接口buses_ops,应用程序访问总线都通过这个接口,这样,所讨论的统一接口问题也就实现了。该接口的主要函数成员如程序片段二所示。
程序片段二:
应用程序打开设备的时候,利用子设备号可以找到总线对应的底层适配器,也就是说,子设备号兼具了适配器索引的功能,其具体实现如程序片段三所示。
程序片段三:
事实上,buses_dev是设备层和适配器层的桥梁,在open操作里被赋值给文件指针的私有数据域。那么,在读与写函数中,就可以反其道而行,通过文件指针的私有数据域就可获得buses_dev数据结构体。
2.3 适配器接口层
适配器负责对底层数据的操作,由于不同的总线之间存在共性,所以,一般来说,它们都包含了单字节读、单字节写、多字节读、多字节写以及一些特殊控制。综上所述,该数据结构如程序片段四所示。
程序片段四:
完成设备驱动加载之后,就会在/dev目录下生成如图2所示的文件节点。通过打开节点,就可以打开总线的统一接口,从而实现对总线的读、写和控制操作。
同时,还会在/sys目录下生成关于注册的总线属性目录和文件,主要包含有设备号的属性文件、电源管理属性目录、到类目录的链接、特殊事件属性文件等,具体如图3所示。
这里分别对I2C接口的E2PROM芯片AT24C02、1-Wire接口的EEPROM芯片DS2433和SPI接口的EEPROM芯片25AA010进行测试。其测试结果如图4所示。