2
(1.西南科技大学 信息工程学院,四川 绵阳 621010; 2.四川理工学院 人工智能重点实验室,四川 自贡 643000;3.成都理工大学 地质灾害防治与地质环境保护国家重点实验,四川 成都 610059)
随着地震勘探技术向高密度空间采样和多波多分量数据采集方向发展[1],多路并行地震数据采集成为地震勘探的关键技术环节。传统的地震数据采集站一般是野外工作的嵌入式系统,无关具体平台,其采集驱动实现方式一般分为裸机驱动[2-3]、带操作系统的应用层驱动[4-5]和操作系统之下的内核驱动[6-7]。但是裸机驱动需要操作大量底层寄存器,不适用于大量地震数据采集的采集与传输,而应用层驱动又需依靠频繁的API系统调用接口实现硬件控制,且控制实时性差。若单道数据采集的系统调用量过大,实时性低,占用大量CPU、内存等资源,就会严重限制地震采集单元向多通道、大数据量的方向发展。
针对上述问题,在Linux 3.0.35内核下,以总线设备驱动模型为指导[8],提出一种单路SPI驱动多路ADC并行采集的驱动,并在驱动实现过程中简化系统调用,减小内核和用户空间的切换频率,然后通过归类并分离实现实时操作与非实时操作的改进方式,增加数据采集单元的工作效率,提高其数据可靠性。
地震采集站主要是用于地震资料的采集、存储与传输[9]。本地震数据采集单元主要由前级MEMS检波器组、滤波电路、多路独立ADC并行采集单元、多路复用接口和Cortex-A9处理器及其外围存储单元构成。图1为地震数据采集单元的总体结构。针对目前存在的实时性不高以及系统调用频繁问题,本文的ADC数据采集驱动主要由Cortex-A9处子框中的用户空间实现转到内核空间实现。
图1 地震数据采集单元的系统总体结构
在Linux内核中,利用Linux内核的SPI子系统总线挂接外设ADS1282单元[10]后,还需:① 在板级支持文件中填写SPI口参数信息(如时钟、电平模式等)和ADS1282与Cortex-A9的GPIO连接信息等,配置相关的网络服务、编译内核映像uImage和BootLoader,制作文件系统烧写系统并重启;② 设备注册,将ADS1282外设单元抽象成字符设备挂载到SPI总线上,填充设备描述结构,申请设备号、内存等资源,使用cdev_init实现设备名和描述结构的互联;③ 驱动注册,注册与设备同名的驱动名,填充驱动描述结构,申请中断、异步通知、乒乓缓存等资源。
ADS1282地震数据采集驱动的内核实现流程如图2所示。首先,初始化ADS1282外设,按照SPI协议发送命令配置RESET、PWDN、SYNC、DIN引脚,读SampleRate(采样率S)和SecondPerFile(每ns写1个地震文件)参数,准备进入连续采集状态;然后,Linux中断顶半部等待DRDY信号中断,底半部利用SPI单字节读写函数依次将数据写入乒乓缓存;最后,数据采集完成,创建内核线程,直接调用具体的VFS文件系统读写函数实现乒乓缓存到地震数据文件中的拷贝,并采用异步信号(软中断)通知应用程序数据写文件完成。
图2 ADS1282内核驱动实现流程框图
在用户空间测试驱动和设备能否正常工作。首先打开ADS1282设备;其次读取配置文件中SampleRate和SecondPerFile参数,并通过ioctl函数实现应用程序对内核参数的控制;最后阻塞等待异步通知,添加文件头地震数据文件(包括采集站IP、采集时间戳等信息)。此外,应用程序还提供了“停止采集”命令控制接口,用于用户终止ADC连续采集。驱动测试应用程序流程图如图3所示。
系统调用把应用程序的请求传给内核,调用相应的内核函数完成所需的处理,再将处理结果返回[11]。本文主要在GPIO中断控制和写地震数据文件部分实现了系统调用的简化。
图3 驱动测试应用程序流程图
针对常规的嵌入式应用层驱动不能如裸机般直接对GPIO进行方向操作或是电平置高置低的问题,采用内核中断顶半部与底半部相结合[12]的方式减少了大量的系统调用。应用程序只能通过文件I/O方式将待用的GPIO引脚从内核导出,产生/sys/class/gpio/gpioN目录,对其中value文件进行读写实现gpio中断控制、电平控制等。而本驱动的DRDY引脚与Cortex-A9直连,中断顶半部通过直接读取DRDY硬件脉冲来简化文件I/O的系统调用,且避免了由于select函数轮询value文件值延迟而造成的数据采集不实时问题。
针对写地震数据文件部分存在大量系统调用的问题,为了实现内核空间到用户空间的数据拷贝,常用的方式是内核使用copy_to_user函数结合应用层write系统调用,优化方式主要由内核和用户空间采用mmap内存映射方式实现数据传输,但要频繁进行内存映射与解映射。因此,本驱动直接在数据采集完成后,在内核中调用具体的VFS(虚拟文件系统)读写函数ext3_file_operations结构的do_sync_write函数直接将缓存数据写入文件,实现写文件的同时省略了从write到VFS读写函数的调用过程。
根据实时性对地震数据采集驱动实现的必要操作归类,硬实时部分主要是对DRDY控制与多路数据的快速缓存,软实时操作包括将数据从缓存存入文件,加入系统时间戳,并用异步通知信号告知应用程序数据写文件完成,非实时操作主要是给数据文件添加IP地址等文件头。
本驱动在中断顶半部函数中实现了对DRDY的实时硬件监控,在底半部实现多路数据的乒乓缓存。由于地震数据的高精度时间同步要求,在单个文件采集开始或者完成时均须加上当前的系统时间,涉及到引起阻塞或睡眠的函数,因此不能直接在顶半部中缓存数据。而添加文件头等非实时操作便由应用程序在监测到异步信号后再对数据文件进行完善。由于异步通知的引入避免了应用程序一直轮询设备状态,更提高了本驱动的实时性。
以i.mx6q[13]Cortex-A9处理器为例,搭载3路32位A/D芯片ADS1282,在Linux 3.0.35内核下进行了采集驱动的实现。采集单元硬件连线如图4所示。测试设置SPI主时钟为2 MHz,采样率SampleRate为4000 Hz,SecondPerFile为5 s,每个地震数据文件由3×20000个采样点组成。
图4 地震数据采集单元硬件连接图
测试单道ADS1282的数据采集功能,并采用Matlab读取采集的地震数据文件,绘图显示波形曲线如图5所示。
① 将ADS1282差分输入端直接短接,测试采集板等效输入噪声水平及其幅频曲线,如图5(a)和图5(b)所示;
② 输入100 Hz 1 mV的标准正弦波信号,测试ADS1282采集效果及其幅频曲线,如图5(c)和图5(d)所示;
③ 输入人工敲击地震波信号,测试ADS1282采集信号及其幅频曲线,如图5(e)和图5(f)所示。
对比文件IO方式实现的应用层驱动与本内核驱动对单次写地震数据文件的耗时情况,可绘制图6所示两种驱动完成单次采集的耗时对比图。
图5 ADS1282内核驱动功能测试
图6 两种驱动单次采集操作的耗时对比
实验采用内核驱动和应用层驱动分别采集100个数据文件。由图6分析可知,相对于传统的应用层驱动,内核驱动确实减少了系统调用,同时提高了数据传输速度,完成同样的采集、数据转换、存储操作,内核驱动相较于应用程序用时少了约90 ms,效率更高。根据4000 Hz的采样率计算,DRDY信号间隔约250 μs,多耗时90 ms意味着写文件的操作会影响ADC采集,甚至会丢失有效地震信号。
采用统计分析的方式,对系统调用的减少量进行分析。实验采用应用层驱动和内核驱动各采集20000个采样点时各类系统调用次数的总量,如表1所示。
根据统计结果分析,内核驱动程序和测试程序部分的系统调用主要集中在测试程序中打开设备,ioctl设备参数以及系统时钟获取部分,因此明显比ADS1282应用层驱动减少了各类系统调用的次数。而应用层驱动的系统调用量主要集中在查询与GPIO相连的DRDY_value文件和写地震数据文件部分,因此,通过内核驱动直接调用具体的VFS写函数而非在用户空间调用write系统调用的方式便可实现系统调用量的大大降低,从而提高采集的实时性。
根据ADS1282手册可知,其支持的SPI时钟为2~16 MHz,读写1 bit数据耗时t为62.5 ns~0.5 μs,而采样率为S,即DRDY信号间隔为1/S。查阅ADG804手册可知,其开关快速切换时间小于25 ns,若忽略采集时通道间切换时间,则其通道可扩展的理论最大道数N=1/(S·32·t)。以SPI时钟2 MHz,采样率4 kHz为例,其通道可扩展数N=1/(4000×32×0.5×10-6),约15道。实测一个DRDY间隔(250 μs)内,采集3路数据加上3路通道切换耗时60~65 μs,则该地震数据采集单元可扩展成12路ADC同时采集。
表1 两种驱动系统调用量统计
本文设计了一种基于Linux的ADC地震数据采集内核驱动,支持外部3路ADS1282并行地震数据采集。通过在内核驱动实现过程中简化系统调用过程,归类实时性与非实时性操作,解决了地震数据采集过程中应用层驱动存在系统调用频繁、硬件控制实时性不高以及数据采集效率低下等问题。测试部分,在i.mx6q平台上、Linux 3.0.35内核下,首先完成了ADS1282内核驱动的功能测试,并给出了采集驱动的功能测试;其次给出了驱动写数据文件的耗时测试,根据耗时减少说明内核驱动的实时性有所提高;最后统计了应用层驱动和内核驱动的系统调用量,随后给出了多路扩展性分析。总之,本驱动相较于应用层驱动所采集的数据效果好,引入的噪声少,工作效率高,实时性更好,具备多路可扩展的特点。本设计已经应用到复杂山地多波宽频带地震数据采集仪器中并取得良好的实际应用效果。