工控网首页
>

应用设计

>

基于Linux的嵌入式生化分析仪信号采集系统驱动程序设计

基于Linux的嵌入式生化分析仪信号采集系统驱动程序设计

2010/3/25 15:34:00
1、引言

        生化分析仪[1]是临床检验医学中经常使用的分析仪器,它通过对血液或者其他体液的分析来测定各种生化指标。重庆大学微系统中心正在研制的嵌入式生化分析仪以CCD作为信息探测的源头、光谱分析为基础,以期达到检测速度快,灵敏度高的特点。同时,为了满足整个仪器小型化、智能化的要求,信号由经嵌入式处理器的控制,通过嵌入式Linux操作系统以用户调用驱动程序的方式进行采集,最终在用户层完成信号的处理、分析工作。可以说,信号的采集对整个仪器的灵敏度、精度等影响重大。因此,本文针对嵌入式生化分析仪信号采集系统的特点,进行Linux下相应的驱动程序的设计与研究。

2、嵌入式生化分析仪信号采集系统硬件结构

        嵌入式生化分析仪信号采集系统由CCD探测器、A/D转换器、FIFO缓存器以及时序发生器组成[1]。时序发生器采用大规模逻辑器件CPLD实现,负责产生包括移位脉冲、积分时间控制信号在内的CCD驱动时序、A/D的转换控制信号和FIFO缓存器的写信号、复位信号等,是整个采集系统的控制中心。CPLD的各种控制信号又由用户对嵌入式处理器S3C2410A[2]的存储空间进行操作从而产生的地址信号输出得到。整个系统的结构如图所示:


       当系统上电后,处理器发送CPLD控制信号进行A/D、FIFO的初始化,进入工作状态,同时,产生的CCD驱动脉冲驱动SONY ILX554B CCD传感器工作,在CCD的第一个有效象元输出时刻CPLD发出采样脉冲,并送给A/D,A/D对CCD产生的2048个有效象元进行转换。由于12位A/D芯片ADS803对信号进行转换时,输出信号要延迟6个时钟周期,因此CPLD要在A/D工作时钟开始延后的6个时钟周期后产生FIFO的写时钟,FIFO对采集的信号进行缓存。系统使用的FIFO芯片是双端口的存储缓冲芯片IDT7284,其具有两个4KX9bit的存储结构。由于输入信号是12位的数据,因此FIFO要采用字长扩展方式,设计为4KX18bit。当采集的信号存到FIFO容量的一半(2KB)时,FIFO的半满标志位有效,半满标志位连接至处理器的GPIO口作为后续驱动程序采集的中断请求信号,通知驱动程序读取数据。

3、Linux设备驱动与硬件通信

        我们的嵌入式处理器采用SAMSUNG S3C2410A,运行Linux-2.6.14内核,系统内核通过设备文件与硬件进行通信。设备文件作为具体设备的抽象为驱动程序提供了硬件的逻辑接口,它包含了由主设备号和次设备号组成的设备号,主设备号标识设备对应的驱动程序,次设备号用于正确确定设备文件所指的设备。可以说,设备文件是驱动程序与物理设备间的桥梁。Linux驱动程序因此可以隐藏设备的具体细节,为不同的设备提供统一的编程接口。一般来说,字符设备驱动程序提供如下的驱动接口:

        •Open:对设备文件执行的第一个操作,打开设备,进行设备的初始化;

        •Release:释放由open分配的内容,在最后一次关闭操作时关闭设备;

        •Read:从设备上读取数据,将数据从内核空间拷贝至用户空间;

        •Write:往设备上写数据,将数据从用户空间拷贝到内核空间;

        •Ioctl:执行读写之外的控制命令;

         站在处理器的角度,每种外设都通过读写寄存器进行控制,不管是在I/O端口区域还是I/O内存区域。而在硬件层看来,它们都通过向地址总线和控制总线发送电平信号进行访问,再通过数据总线读写数据。除了x86上普遍使用I/O端口外,和硬件通信主要通过使用映射到内存的寄存器或设备内存,即I/O内存。因此访问外设,首先必须分配I/O内存区域,然后通过ioremap把物理地址范围重新映射到处理器的虚拟地址空间,以供内核使用。最后通过内核定义的一组相关函数对外设进行访问。

        大部分外设通过I/O得到控制后,还需要实现具体的功能,通常它们都是在与处理器完全不同的时间周期内完成的,并且总是要比处理器慢。为了不让处理器总是等待外部事件,需要通过中断机制让设备在产生某个事件时通知处理器。而在Linux系统中,并不是直接从中断向量表中调用中断处理程序完成中断操作的。Linux内核维护了一个中断信号线的注册表,在驱动中首先设置外设所用的外部中断端口,并请求一个中断信号线[,外设通过中断端口产生中断信号,由经中断信号线发送到内核,并连接相应的中断处理程序处理中断。

4、采集系统驱动程序设计

        本文讨论的嵌入式生化分析仪采集系统驱动程序是以模块方式设计的。添加我们的驱动模块至内核后,由应用层调read函数来请求采集数据,当中断处理采集完数据后,再由read函数拷贝至用户空间,完成用户层对数据的采集。在整个过程中,我们的设备数据抽象为:

struct bio_dev {
wait_queue_head_t readqueue; /* read queue */
u16* buffer; /* begin of buffer */
int buffersize; /* size of buffer */
int status; /* 0: empty 1: half full 2: full full */
u8 integral; /* integral time */
struct semaphore sem; /* mutual exclusion semaphore */
struct cdev cdev; /* Character Device structure */
};

        当调用lsmod命令添加驱动模块至内核时,module_init指定的模块初始化函数将被调用,它负责向内核申请注册驱动所需要的任何设施。初始化函数首先设置与FIFO半满标志位连接的处理器的外部中断端口EINT11为中断模式,然后根据控制CPLD的处理器地址信号确定I/O内存区域,并向内核提出对该I/O内存区域的申请,接下来申请设备号,初始化并注册我们的设备,最后根据中断端口号申请中断线,并注册中断服务程序等。该函数流程图如下:

        在我们的采集驱动程序中,最为关心的是从FIFO中读取采集的数据并提供给用户,这部分由read函数和中断处理程序共同完成。

        read函数每次执行时,需要首先发送清零操作,复位CCD、A/D、FIFO,保证采集的每一帧2048个有效数据的完整,避免FIFO先入先出特性缓存的非同一帧数据。清零后,read函数需要等待FIFO采集完一帧数据,并产生中断信号来进入中断处理程序完成采集数据存储到内核空间的操作。最后,read函数将存储在内核空间的数据拷贝到用户空间中,完成用户对数据的采集工作。考虑到外设与处理器速度上的差别,如果驱动程序无法立刻满足采集数据到内核空间的存储,内核空间的数据将尚不可用,在这种情况下,read函数必须使用阻塞型I/O,将自己置入休眠,等待必要的工作结束后再唤醒返回,继续未完成的操作。read函数流程图如下:


        由于并不是所有FIFO半满标志位产生的硬件中断都意味着有用户的读取请求,所以我们在read函数中分配用于保存采集数据的内核空间,并在中断处理程序开始时判断内核空间的分配情况。当有分配好的内核空间,说明真正有用户的读取操作时,才进行FIFO数据的存储操作,并在完成后唤醒休眠等待的read进程。中断处理程序流程图如下:

图4.3 中断处理程序流程图
 
         由于内核空间由read进程和中断处理进程共享,所以在设计时采用了互斥技术锁定设备,避免竞态,确保采集到的数据的安全有效。

        采集系统的驱动程序除了完成信号的采集工作之外,还需要控制CCD的积分时间。因为针对我们的采集系统,CCD信号输出的最大幅值受CCD器件的光电灵敏度、积分时间和光照度的影响,在选定CCD器件后,该值主要取决于积分时间和光照度,同时,由于CCD对不同波长感测能力不同,在光照度及波长变化的情况下,想保证CCD输出信号在特定波长上的幅值最大、最稳定,就需要通过对积分时间的控制来
投诉建议

提交

查看更多评论
其他资讯

查看更多

助力企业恢复“战斗状态”:MyMRO我的万物集·固安捷升级开工场景方案

车规MOSFET技术确保功率开关管的可靠性和强电流处理能力

未来十年, 化工企业应如何提高资源效率及减少运营中的碳足迹?

2023年制造业“开门红”,抢滩大湾区市场锁定DMP工博会

2023钢铁展洽会4月全新起航 将在日照触发更多商机