微波EDA网,见证研发工程师的成长!
首页 > 射频和无线通信 > 射频无线通信文库 > 频谱仪多种内核间通信机制的方案设计

频谱仪多种内核间通信机制的方案设计

时间:11-15 来源:互联网 点击:


    • Linux操作系统将所有的设备(而不仅是存储器里的文件)都看成文件,以操作文件的方式访问设备。应用程序不能直接操作硬件,而是使用统一的接口函数调用硬件驱动程序。在设计的驱动程序中,首先要根据驱动程序的功能完成file_operations结构中的函数实现,不需要的函数接口可以直接在file_operations结构中初始化为NULL。而file_operations结构变量会在驱动程序初始化时注册到系统内部。当操作系统对设备操作时,就会调用驱动程序注册的file_operations结构中相应的函数指针。
      对于Linux驱动的注册有两种方式:一种是直接编译到内核中,在系统启动时即对设备进行注册;另一种是以模块的方式注册设备,需要在系统启动后用命令对设备进行注册。后一种方式在系统开发期使用比较方便,不用在每次修改驱动程序后和内核一起进行编译,只需要将模块编译成后缀为,ko的模块文件,就可下载到开发板中直接使用。在本课题中,使用的是模块注册的方式,在项目开发期间可大大缩短开发时间。

      4 Linux设备驱动的实现
      对于编写一个Linux设备的驱动程序,大致的流程如下:
      ①查看原理图、数据手册,了解设备的操作方法。
      ②实现驱动程序的初始化,比如向内核注册这个驱动程序,这样应用程序传入文件名时,内核才能找到相应的驱动程序。
      ③设计所要实现的操作,比如open、close、read、write等函数。
      ④实现中断服务(不是必须的)。
      ⑤编译该驱动程序到内核中,或者用insmod命令加载。
      ⑥测试驱动程序。
      4.1 HPI设备驱动程序实现
      4.1.1 物理地址到虚拟地址的映射
      写Linux设备驱动的第一步,是完善头文件中的宏定义,除了各种参数的定义外,主要是实现硬件寄存器的物理地址到虚拟地址的映射。对于硬件寄存器的操作,其实就是对其物理地址进行读写操作。而Linux系统提供了一种内存管理机制,在这种机制下,程序可以使用比真实物理地址大得多的地址空间,称为虚拟地址。Linux系统中程序的操作部是使用虚拟地址,所以要完成物理地址到虚拟地址的映射。本课题采用ioremap函数的方法,如下:
      #define AT91C_SMC_CSR2*(volatile unsigned long*)ioremap(0xFFFFFF78.4)
      对于ioremap函数,就是将物理地址0xFFFFFF78开始的4字节的地址映射到虚拟地址空间中,返回值即4字节虚拟地址的首地址,赋给宏定义的变量名AT91C_SMC_CSR2。对宏定义的操作即对物理地址的操作。
      4.1.2 HPI驱动的初始化
      首先是对HPI硬件的初始化以及中断初始化。对于HPI,主要是重置DSP,已完成时序的同步。设置SMC(静态存储控制器),因为ARM跟DSP的HPI通信是使用PIO线复用。最后向DSP发送握手信号,表示初始化完成。对于中断的初始化,使用:
      request_irq(AT91C_ID_IRQ0,handler,SA_INTERRUPT,”irqO”,NULL);
      此函数向内核注册中断,包括中断号和中断处理函数handler。
      对于HPI设备的注册,为HPI设备分配系统未使用的254作为主设备号,0为次设备号。通过register_chrdev_region函数向内核注册。函数cdev_init是初始化设备,其实就是建立设备与file_operations结构的对应关系。最后将设备加入内核。代码如下:

      上述的代码都是在驱动模块的hpi_init函数中实现。在HPI驱动被加载到内核时就完成了一系列初始化。
      4.1.3 file_operations结构中函数的实现
      设计驱动的大部分工作就是实现file_operations结构中的函数。代码如下:

      其中,“.owner=THIS_MODULE”表示结构属于本模块,然后是open、read等各函数的对应关系。由于初始化在hpi_init函数中实现,所以open函数并没有特别的操作,主要是在终端输出信息。函数release主要是申请中断资源的释放,使用free_irq函数。下面主要讲解read函数,write函数与之类似,不再详述。
      ssize_t hpi_read(struct file*file,char*buf,size_t count,loff_t*offp)
      其中,参数file是打开文件的标识符;参数buf和count就是要向buf指向的地址存放count字节的数据;参数offp是文件读取的位置,默认为文件头,不用设置。
      在read函数的最开始有如下代码:
      wait_event interruptible(hpi_wait,ev_start);
      down(&sem);
      ……
      up(&sem);
      其中wait_event_interruptible函数会阻塞进程,使其进入等待队列。直到DSP的数据准备好后,发来中断。HPI设备注册的中断处理函数handler会将变量ev_start置1,同时唤醒hpi_wait等待队列。read函数继续执行之后的代码,即开始从DSP的HPID寄存器读取数据到参数buf指向的地址。读取完成后向DSP指定地址写入0xffffffff,表示读取完成。函数down与up是操作二进制信号量,使渎取数据的过程为“原子”操作,避免执行过程中被打断,从而影响读取结果。read函数的流程如图5所示。

上一篇:网桥的功能
下一篇:双绞线

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top