微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > CAN通信卡的Linux设备驱动程序设计实现

CAN通信卡的Linux设备驱动程序设计实现

时间:04-25 来源:电子技术应用 点击:

理的,设备驱动程序在初始化时,需要申请资源。在资源不用的时候,应该释放它们,以利于资源的共享。在Linux系统里,对中断的处理是属于系统核心的部分,设备驱动程序通过调用request_irq()函数来申请中断,通过free_irq()函数来释放中断。作为系统核心的一部分,设备驱动程序在申请和释放内存时不是调用malloc()函数和free()函数,而代之以调用kmalloc函数和kfree()函数。

在init_module模块中,先检查是否存在CAN通信卡,如果不存在则退出设备驱动程序的加载;如果存在,使用request_irq()函数为CAN通信卡申请系统中空闲的中断,使用kmalloc()为设备驱动程序申请输入输出缓存队列,如果这些资源申请不成功,则释放已经申请到的系统资源,然后退出设备驱动程序的加载,如果申请成功,使用register_chrdev()函数将CAN通信卡驱动程序注册到Linux系统中,加载完成。

在cleanup_module模块中先使用free_irq()函数释放init_module模块中申请到的中断,然后使用kfree()函数释放init_module模块中申请到的内存空间,最后使用unregister_chrdev()函数释放init_module模块中注册的设备驱动程序,卸载完成。

2.2 CAN通信卡设备驱动程序的中断处理部分

Linux中断处理程序可以分为上半部和下半部。上半部即一般的中断服务程序,由硬件中断触发,它一般运行在关中断的方式下,应当尽可能短小,处理尽可能快;而下半部是单独的一段处理程序,一般将其挂入立即队列中以便快速执行。立即队列中的任务在退出系统调用或调度器获得运行时,将最优先地被执行。下半部运行在一个安全的环境,即开中断和任务串行化,可以处理一些较花时间的任务。

这样,驱动程序上半部在处理完实时性很强的任务后,用queue_task()函数将下半部处理函数挂入立即队列,并用mark_bh()函数来激活立即队列,则下半部可以最优先地被执行。

当有接收中断时,CAN通信卡设备驱动程序的中断处理程序上半部首先获取驱动程序接收缓存中的空闲块,将CAN通信卡上的接收缓冲器中数据复制到驱动程序的接收缓存中,释放CAN通信卡接收缓冲器,然后将下半部处理函数挂入立即队列,最后激活立即队列。

当有发送中断时,CAN通信卡设备驱动程序的中断处理程序上半部首先获取发送缓冲队列中的数据,将需要发送的数据写入CAN控制器的发送缓冲器,最后请求发送。

CAN通信卡设备驱动程序的中断处理程序下半部使用Hilon A协议对要传送到CAN网络上的数据打包,并对从CAN网络上接收到的数据进行解包和组帧。这样中断处理程序的上半部只需要从CAN通信卡的缓冲器中将数据复制到驱动程序的缓冲区,系统开销很小,但很费CPU时间;系统开销较大的打包、解包和组帧处理则放在中断处理程序的下半部,使用系统非中断时间调度,可以使系统响应中断更快,通信更稳定。

2.3 缓冲区管理

在CAN通信卡设备驱动程序中,为了增强CAN通信卡的通信能力、提高通信效率,根据CAN的特点,使用两级缓冲区结构,即直接面向CAN通信卡的收发缓冲区和直接面向系统调用的接收帧缓冲区。

通讯中的收发缓冲区一般采用环形队列(或称为FIFO队列),使用环形的缓冲区可以使得读写并发执行,读进程和写进程可以采用"生产者和消费者"的模型来访问缓冲区,从而方便了缓存的使用和管理。然而,环形缓冲区的执行效率并不高,每读一个字节之前,需要判断缓冲区是否为空,并且移动尾指针时需要进行"折行处理"(即当指针指到缓冲区内存的末尾时,需重新将其定向到缓冲区的首地址);每写一个字节之前,需要判断缓冲区是否为满,并且移动尾指针时同样需要进行"折行处理"。程序大部分的执行过程都是在处理个别极端的情况,只有小部分在进行实际有效的操作。这就是软件工程中所谓的"8比2"关系。结合CAN通讯的实际情况,在本设计中对环形队列进行了改进,可以较大地提高数据的收发效率。

由于CAN通信卡上接收和发送缓冲器每次只接收一帧CAN数据,而且根据CAN的通讯协议,CAN控制器的发送缓冲器由1个字节的标识符、一个字节的RTR和DLC位及8个字节的数据区组成,共10个字节;接收缓冲器与之类似,也有10个字节的寄存器。所以CAN控制器收发的数据是短小的定长帧(数据可以不满8字节)。

于是,采用长度为10字节的数据块来分配内存比较方便,即每次需要内存缓冲区时,直接分配10个字节,由于这10个字节的地址是线性的,故不需要进行 "折行" 处理。更重要的是,在向缓冲区中写数据时,只需要判断一次是否有空闲块并获取其块首指针就可以了,从而减少了重复性的条件判断,大大提高了程序的执行效率;同样在从缓冲队列中读取数据时,也是一次读取10字节的数据块,同样减少了重复性的条件判断。

在CAN卡驱动程序

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

网站地图

Top