本站小编为你精心准备了LXI和GPIB编程仪器通用接口设计参考范文,愿这些范文能点燃您思维的火花,激发您的写作灵感。欢迎深入阅读并收藏。
摘要:如果开发出可编程台式仪器通用接口模块,那么只要更换仪器功能模块便可迅速实现各类可编程台式仪器。目前LXI和GPIB是这类仪器常用接口,且两种接口各有优势,鉴于此,本文应用嵌入式系统开发了具有LXI和GPIB的可编程台式仪器通用接口模块。介绍了其总体设计方案;移植了boa服务器,实现了LXI总线的Web接口;给出了Linux下GPIB驱动开发方法,其中在中断服务中提出了顶半部底半部设计思想,引入了非原子队列实现底半部,提高了驱动运行效率。结合仪器功能模块进行了测试,此接口模块工作正常,具有较高的工程应用价值。
关键词:通用接口;LXI;GPIB;TNT48820
引言
如果在研发可编程台式仪器方面借鉴模块化仪器思路,将总线接口功能独立出来,做成通用接口模块,然后结合仪器功能模块实现产品,这样就能缩短研发周期,降低研发成本,同时也方便对仪器进行升级。LXI是LAN面向仪器的扩展总线,此时仪器可以认为是物联网,此接口模块又具有GPIB接口,所以一般利用嵌入式系统来满足多接口多用户的需求。本文提出了利用S5P4418处理器结合Linux的嵌入式系统来开发通用接口模块的技术方案。由于boa是小巧高效的Web服务器,支持CGI(Com-monGatewayInterface)并且对Linux兼容性很好,因此通过移植boa来实现LXI协议规定的Web接口,为了能够实现Linux下GPIB驱动,给出了开发方法。但有了操作系统就会存在系统中断信号、进程间分配调度等情况,这样就带来了仪器监听命令实时性有时降低的问题,所以在GPIB中断服务中提出了顶半部底半部设计思想,引入了非原子队列实现底半部,增加了驱动运行效率,监听命令实时性有时降低的情况得到了一定改善。
1通用接口模块总体设计
具有LXI和GPIB的可编程台式仪器接口模块硬件系统除了要有LAN接口和GPIB接口外,还要有仪器复位按钮、仪器状态指示灯,为此采用嵌入式系统进行构建,具体硬件原理[1]框图如图1所示。三星公司的S5P4418基于ARMCortex-A9、主频为1.4GHz,内部集成了4GB/8GB/16GB的EMMC、SDRAM控制器,支持RTL8211E千兆以太网控制器,拥有5通道UART、4通道DMA、USB主机接口和设备接口及24路外部中断源。综合考虑功能和性能需求、成本、功耗等因素,选择S5P4418作为嵌入式MCU。对于GPIB接口,需要外加一块GPIB控制器芯片,NI公司提供的TNT4882芯片是一款高速且听讲功能兼备的GPIB接口专用芯片,因此GPIB控制器选择了TNT4882芯片。图2接口模块软件原理框图接口模块软件系统如图2所示。由于boa[2]是一个成熟的嵌入式Web服务器,能够高效依次完成用户的请求,最为关键的是boa支持CGI[3];CGI是一种Web服务器用户接口规范,是运行在Web服务器上的一段程序,它能够实现Web服务器与底层操作系统交互,从而可以实现网络配置[4],因此利用boa实现Web接口。对于GPIB通信,需要开发出Linux下GPIB驱动程序,主要包括初始化函数、中断处理函数、读写操作函数。
2接口的实现
Web服务器利用boa来实现,但由于通用接口模块的平台是基于Linux操作系统和ARM9处理器,所以要对其进行移植。具体方法如下:自带的makefile文件是针对一般环境,需要对其进行修改,找到CC=gcc,将其改成CC=arm-linux-gcc,再找到CPP=gcc–E,将其改成CPP=arm-linux-gcc-E。这样是为了把编译器指定为Linux和ARM处理器平台下的,最后在终端的目录src下输入make命令,并输入arm-linux-stripboa剥去调试信息,生成boa执行文件。在配置文件boa.conf中将bind调用的IP地址绑定到INAD-DR_ANY;Usernobody修改为User0,Groupno-group修改为Group0,需建立/var/log/boa目录,UseLocaltime使用本地时间,ServerName为服务器名字,此参数必须赋值,DocumentRoot需要设置成自己的HT-ML文档的主目录;DirectoryIndex为HTML目录索引的文件名,一般写index.html。如果DirectoryIndex不存在,该目录必须是boa能读写,一般填/var/spool/boa/dircache,KeepAliveTimeout为HTTP持续作用中服务器在两次请求之间等待的时间数,超时将关闭连接,可以根据自身需求设定;需要指明mime.types文件位置;CGI-Path〈string〉提供CGI程序的PATH环境变量值,可写/bin:/usr/bin:/usr/local/bin;ScriptAlias〈/cgi-bin/〉非常重要,指明CGI脚本的虚拟路径对应的实际路径。
3Linux下GPIB驱动开发
3.1初始化函数设计
初始化函数需要完成向内核注册GPIB驱动[5]、GPIB控制器的寄存器硬地址映射[6]到内存、启动TNT4882[7]芯片工作,要对实现读写互斥的信号量和实现阻塞的等待队列进行初始化。由于在中断处理函数中引入了非原子队列,在这里也需进行初始配置。具体开发方法如下:向内核注册GPIB驱动直接调用内核提供的register_chrdev函数;映射是通过调用内核函数ioremap来实现的,此函数第一个参数需要设置为TNT4882芯片的首地址,TNT4882芯片的首地址由硬件设计的片选信号线决定,函数返回内存映射首地址,因为芯片手册给出了每个寄存器的偏移量,这样TNT4882的首地址加上偏移量就可以得到每个寄存器在内存的地址,然后就可以对TNT4882芯片使能。具体流程为:将TNT4882芯片中的Turbo电路复位,并将TNT4882设置成Turbo+7210式,同时设置成单芯片模式,使能Local_PowerOn信号,设置TNT4882的GPIB主地址,将副地址取消以及对GPIB握手参数进行配置开始GPIB操作,读写操作可能会同时访问同一资源,这种情况就变成了临界区,会产生竞态,导致系统内核的崩溃,信号量就是产生互斥的机制,信号量在使用前要对其进行初使化,通过调用内核函数init_MUTEX完成;对于中断响应,如果任务需要耗时比较长,可以把中断处理分割为顶半部和底半部,顶半部只用来响应中断,从而快速完成中断响应,而底半部单独进行任务的处理,非原子队列开辟内核进程还支持休眠,底半部利用非原子队列处理任务,这样使中断处理部分变成内核进程,可以和用户态进程同时执行,从而提高驱动效率,使用前,它通过调用init_WORK函数完成初始化;阻塞可以让进程睡眠,进程在运行时如果需要等待另一个事件来到才能继续运行,这种情况可以用阻塞来使进程睡眠,由于应用层的进程需要等待数据来到才能继续处理,所以在内核的读函数里需要添加阻塞,内核提供了等待队列机制,使用前调用内核函数init_waitqueue_head进行初始化。图3中断函数流程图
3.2中断服务设计
GPIB主设备发来注意命令(ATN),TNT4882产生中断,在GPIB接口处是已远控使能(REN)和听者作用状态(LACS),那么GPIB接口就准备接收数据。如果GPIB接口处是已远控使能和讲者作用状态(TACS),那么GPIB接口就可以发送数据。中断函数流程图如图3所示,具体开发方法如下:request_irq[8]函数是Linux字符设备驱动中断注册接口,利用此函数将中断服务注册到内核里,中断号配置成硬件原理图占用中断向量表的中断号,将参数*device获取的GPIB设备名记录在/proc/inter_rupts文件中,分割中断,利用中断响应属性flags将中断底半部分割运行,把TNT4882中断使能寄存器中有关的ATN、REN、LACS、TACS利用内核函数iowrite8全部使能,在中断服务程序中,读TNT4882中断响应信息寄存器的信息,出现与LACS相同的值后,调用收操作,出现与TACS一致的值,调用发操作。对于收操作和发操作,自定义了两个函数(shortRe-ceive(void)和shortSend(void))来实现,在接收操作方面,因TNT4882的FIFO为16字节深,不仅提供了它的全满标志位,而且还提供了半满标志位,本设计中没有使用传统的全满位作判断位,而是利用了FIFO半满位。好处是,FIFO中数据取到内核缓冲区和FIFO继续接收数据可以同时进行,如果用全满位,则只有满了将数据取走后,有了空间FIFO才能收数据,因此这样可以提高数据接收速率。Receive函数实现具体是:在传输寄存器里配置传输参数,完成设置后,再用ioread8函数读取该寄存器传输准备位,传输就绪后,最后使能传输工作位;设置收到字符计数变量,判断中断使能寄存器的听状态位,出现听状态以及FIFO已经超过了半满,然后循环从FIFO中取数,听状态结束,FIFO中还存在数据,用ioread8函数将数据全部接收,结束收流程。在发送操作方面,它不像收操作直接调用Receive函数,而是间接调用。通过调用非原子队列来调用发函数,这样队列和用户态的进程可同时运行,从而使驱动开销时间减少,提高了运行效率。用creat_workque创建队列,将该创建的队列赋给queue_work函数第一个参数,将Send函数指针赋给queue_work函数第二个参数,从而将Send函数插入队列,并将workque_struct类型的结构体变量中的属性成员配置成非原子操作,中断服务程序运行到queue_work接口处,内核将自动开辟进程执行Send函数。Send函数实现具体是:进行传输初始化,初始化过程与Receive函数一样,设置要传输字符计数变量,读取FIFO状态寄存器,判断是否FIFO为满,不为满时往里面循环传输数据,直到计数变量到达此次发送字符数,退出发送操作,在发送完毕后一定要对开辟线程做结束处理,通过调用内核函数destroy_workqueue完成。
3.3设备文件操作—读写函数设计
read和write是Linux字符设备驱动标准接口,其完成用户态和内核态数据交互,在read和write里分别调用内核的copy_to_user和copy_from_user函数来实现。对于读写操作,需要实现互斥,这里采用Linux内核机制信号量来完成。具体实现方法是:设置一个驱动全局变量为信号量,通过内核宏MUTEX将初始值置为1,在read和write的入口处[9]调用内核函数down,将信号量的值变0,结束处调用up函数再使信号量的值恢复。这样读写操作有一个操作进入了临界区,取走了信号量,类似上了锁,另一个操作将无法访问,只有一个操作完成,还了信号量,另一个操作才能访问临界区,从而实现了互斥。除此之外,为了实现应用程序在数据没有到来的时候能够被挂起,内核的读函数还要实现阻塞。具体实现的思路是:在读函数里的开始处可以通过调用wait_event_in-terruptible函数来使读函数进入睡眠状态,但要注意wait_event_interruptible要放到down函数前面,否则会产生死锁,在GPIB中断函数是已远控使能和听者作用状态结束处通过wake_up_interruptible函数来唤醒睡眠状态,这样就实现了读阻塞。
4测试与验证
接口模块上电开机,把描述仪器信息的HTML文档放置到Web服务器的主目录下,在上位机IE浏览器输入接口模块的IP地址192.168.0.224,便可访问到仪器信息,如图4所示,测试表明Web服务器工作正常。对于GPIB驱动器的测试,接口模块结合上仪器模块,在上位机打开GPIB调试软件GPIB资源管理器和网口调试软件SOCKET通信助手,通过以上两个应用程序向仪器发送命令,从图5中可以看到命令结果正常返回,说明GPIB驱动工作正常。
5结语
为了能够快速实现各类可编程台式仪器,利用S5P4418处理器和Linux开发出了具有LXI和GPIB的可编程台式仪器通用接口模块。通过移植boa实现了Web接口,并对Linux下GPIB驱动和可编程仪器命令通用解析服务器进行了开发,最终实现了该通用接口模块。但发现仪器具有操作系统后,带来了监听命令实时性有时降低的情况,为了改善这种情况,将GPIB中断服务分割成顶半部底半部,底半部引入非原子队列来实现,从而提高驱动运行效率。最后结合仪器功能模块进行了测试,该通用接口模块工作正常,达到了预期的工程目标。
作者:赵昕 郭恩全 朱健 单位:中国船舶集团公司第705研究所 陕西海泰电子有限责任公司