一种基于阻塞接收机制的嵌入式Linux串口驱动开发方法与流程

文档序号:11250628阅读:1701来源:国知局
一种基于阻塞接收机制的嵌入式Linux串口驱动开发方法与流程

本发明涉及linux串口驱动开发技术领域,更具体而言,涉及一种基于阻塞接收机制的嵌入式linux串口驱动开发方法。



背景技术:

近年来,随着嵌入式系统的快速发展,嵌入式linux系统以其源码开放、系统本身独特的特点在嵌入式开发领域中占据着重要的地位。虽然linux系统本身拥有很多的通用设备驱动程序支持,但是针对具体的开发应用要求用户需要添加自己的程序(如机制的联合、添加协议解析等),通用的设备驱动并不适用。现在多数嵌入式设备中针对串口数据的实时采集和处理通用的技术方法是采用在驱动层中完成数据包的采集、应用层对数据包进行处理的开发方法,具体开发模式和存在的问题如下:

(1)通用的驱动层中完成串口数据包采集方法是:在驱动层为了降低cpu占有率,采用串口中断、休眠和唤醒等机制实现数据的接收,一般流程是:驱动层read串口读取函数首先进入休眠,然后在中断来临的情况下接收数据并进行中断唤醒read进程,并将单字节数据/数据包上传给应用层。这种机制会导致以下冲突:由于驱动层read读取之前接收的数据或数据包上传给应用层之前都是出于休眠状态,只有在中断接收数据情况下才将read进程唤醒,当read函数被唤醒后正准备从缓存区读取数据时,中断又接收到新的数据,将新的数据存储于read函数读取的缓存区中,这样写入和读取缓存区的时序冲突而被新的数据覆盖,导致read读取出现丢帧。在串口通信速率较高的情况下,由于冲突引起通信丢帧问题更严重;

(2)应用层对串口数据的读取通过调用驱动层的read函数,一般情况下采用无阻塞读取方法(如定时查询、实时查询)或者阻塞读取方法(接收队列被挂起直至数据或数据包接收完成),非阻塞定时查询能够解决(1)所述的机制冲突问题,会降低接收数据的实时性;非阻塞实时查询和阻塞读取方法需要驱动层相应机制配合,同样会导致(1)所述的问题;

(3)对串口数据包进行处理(如检测数据帧头和帧尾、检查数据长度和校验位等)的开发方法一般是在应用层进行开发,而串口数据都需要经过linux内核层传送,降低了数据的实时性能,尤其是当应用层数据处理之后错误的情况下仍需重新对串口进行收发,应用层再一次调用linux内核层驱动,必然会再次降低数据的实时性能。

基于此,有必要发明一种稳定性高、实时性强的嵌入式linux串口驱动开发方法,以解决linux串口驱动中通信丢帧问题,提高串口数据采集和处理的实时性能。



技术实现要素:

为了克服现有技术中所存在的不足,本发明提供一种基于阻塞接收机制的嵌入式linux串口驱动开发方法,该方法稳定性高、实时性强,解决了linux串口驱动中通信丢帧的问题,并且提高了串口数据采集和处理的实时性能。

为了解决上述技术问题,本发明所采用的技术方案为:

一种基于阻塞接收机制的嵌入式linux串口驱动开发方法,按照以下步骤进行:步骤一、采用字符型设备框架,设计linux串口驱动程序;步骤二、设计接收数据缓存区;步骤三、设计read函数阻塞读取机制;步骤四、设计数据包实时处理机制。

所述步骤一具体为:

1)定义一个结构体file_operationsmyuart_fops,并向结构体中添加open、read、write、close、ioctl函数;

2)定义设备名称,并向内核注册该设备;

3)定义串口寄存器并进行虚拟地址映射,配置寄存器和引脚;

4)声明串口休眠等待队列,在open函数中初始化,并在open函数中申请串口接收中断号,初始化串口配置,初始化休眠等待队列,使其能接收中断;

5)编写write函数:判断当前发送缓存区是否为空,然后将要发送的数据写入发送缓存区,发送数据;循环上述步骤,直至发送完指定的发送数据长度tx_count。

所述步骤二具体为:

1)定义缓存区结构体rx_fifo,成员为:缓存区长度fifo_size、缓存区起始偏移地址fifo_in、缓存区结束偏移地址fifo_out;fifo_out-fifo_in=rx_count,rx_count为串口驱动当前接收的数据长度;

2)设计接收缓存区环形存储模式:

当(fifo_size-fifo_out)≥app_rx_count,说明剩余缓存区空间可以缓存app_rx_count长度数据,初始化fifo_out=fifo_in,串口中断一直处于接收状态,一旦有数据就放入缓存区,进行下一步判断;

当(fifo_size-fifo_out)<app_rx_count或者fifo_size等于fifo_out,说明接收缓存区不足以缓存app_rx_count长度的数据或者接收缓存区已满,令fifo_in=0和fifo_out=fifo_in,缓存区回到起始状态,这样形成了缓存区回环存储机制。

所述步骤三具体为:

1)linux串口驱动接收采用中断+休眠/唤醒机制进行数据的实时接收,驱动层read函数采用阻塞读取机制以配合应用层非阻塞实时查询read读取的实时调用;

2)设置好环形缓存区后,驱动层中断函数每接收一个字节数据放入rx_fifo缓存区;驱动层read函数中采用如下阻塞机制和数据包实时处理机制:

①先判断当rx_count≥app_rx_count,即串口当前接收的数据长度大于或等于应用层需要读取的数据长度,直接读取缓存区的数据,有效避免驱动层read函数只有休眠后被中断唤醒才能读取上传数据、中断接收数据的时序冲突;

②当rx_count<app_rx_count,即串口当前接收的数据长度小于应用层需要读取的数据长度,才会让read进程休眠,这时,read函数没有数据的读取和上传,只有等到rx_count≥app_rx_count才去执行①步骤。

所述步骤四具体为:驱动层read读取缓存区接收的数据后,进行数据包解析,如果数据正确,则通过copy_to_user函数将解析后的数据传递到应用层read函数,如果数据不正确,调用驱动层write函数再一次发送之前的命令信息,通过read函数再一次解析接收数据,如果数据仍不正确,read函数向应用层会发送接收错误信息。

与现有技术相比,本发明所具有的有益效果为:

其一,与现有的阻塞串口驱动开发技术相比,本发明通过采用环形缓存机制和read阻塞读取判断机制,解决了驱动层read函数被调用过程中和中断之间的时序冲突而引起的数据丢帧问题;其二,与现有的非阻塞串口驱动开发技术相比,本发明通过应用程序实时调用read读取函数,驱动层采用read阻塞读取判断机制和中断休眠机制实时接收串口数据,解决了非阻塞串口驱动开发技术中所采用的应用层定时读取函数造成的实时性差问题,或者应用层实时接收数据导致的cpu占用率高等问题;其三,与传统的应用层解析数据包机制相比,本发明在驱动层read函数采用两次解析数据,提高了数据通信准确率和实时处理数据性能。

综上所述,本发明所述的一种基于阻塞接收机制的嵌入式linux串口驱动开发方法基于原有的中断+休眠/唤醒方法进行的优化和改进,有效解决了阻塞串口驱动开发技术中的丢帧问题和非阻塞串口驱动开发技术中的实时性差等问题,提高了串口通信的稳定性和实时性。

附图说明

图1为linux串口驱动阻塞机制流程图;

图2为linux串口驱动中断接收流程图。

图中:

app_rx_count为应用层read函数读取串口接收的数据长度;

rx_count为串口驱动当前接收的数据长度;

fifo_in为环形缓冲区接收数据之前的起始偏移地址;

fif0_out为环形缓冲区接收一定数据长度的结束偏移地址;

fifo_size为环形缓冲区大小;

ev_press为中断标志位;

rx_queue为接收等待队列。

具体实施方式

下面将结合附图对本发明作进一步详细的描述,使本发明所记载的方案更加容易理解。

如图1-图2所示,本发明公开了一种基于阻塞接收机制的嵌入式linux串口驱动开发方法,该方法是采用如下步骤实现的。

步骤一、linux串口驱动程序采用字符型设备框架设计,即:

1)定义一个结构体file_operationsmyuart_fops,并向结构体中添加open、read、write、close、ioctl函数;

2)定义设备名称,并向内核注册该设备;

3)定义串口寄存器并进行虚拟地址映射,配置寄存器和引脚;

4)声明串口休眠等待队列,在open函数中初始化,并在open函数中申请串口接收中断号,初始化串口配置,初始化休眠等待队列,使能接收中断;

5)编写write函数:判断当前发送缓存区是否为空,然后将要发送的数据写入发送缓存区,发送数据;循环上述步骤,直至发送完指定的发送数据长度tx_count。

步骤二、设计接收数据缓存区,如图1所示,即:

1)定义缓存区结构体rx_fifo,成员为:缓存区长度fifo_size、缓存区起始偏移地址fifo_in、缓存区结束偏移地址fifo_out。

2)设计接收缓存区环形存储模式:

当(fifo_size-fifo_out)≥app_rx_count,说明剩余缓存区空间可以缓存app_rx_count长度数据,初始化fifo_out=fifo_in,串口中断一直处于接收状态,一旦有数据就放入缓存区,进行下一步判断;

当(fifo_size-fifo_out)<app_rx_count或者fifo_size等于fifo_out,说明接收缓存区不足以缓存app_rx_count长度的数据或者接收缓存区已满,令fifo_in=0和fifo_out=fifo_in,缓存区回到起始状态,这样形成了缓存区回环存储机制。

通过设计环形存储区,方便了驱动层read函数缓存读取和中断函数的接收数据,环形存储机制保证存储空间的重复利用和存储数据的不丢失。

步骤三、设计read函数阻塞读取机制,如图1所示,即:

1)linux串口驱动接收采用中断+休眠/唤醒机制进行数据的实时接收,如图2所示,以降低cpu的占用率。驱动层read函数采用阻塞读取机制以配合应用层非阻塞实时查询read读取的实时调用,以提高串口接收的实时性。

2)设置好环形缓存区后,驱动层中断函数每接收一个字节数据放入rx_fifo缓存区。由于应用层read函数一直在实时调用驱动层read函数,因此驱动层read函数中采用如下阻塞机制和数据包实时处理机制:

①先判断当rx_count≥app_rx_count,即串口当前接收的数据长度大于或等于应用层需要读取的数据长度,直接读取缓存区的数据,这样有效地避免了驱动层read函数只有休眠后被中断唤醒才能读取上传数据、中断接收数据的时序冲突。

②当rx_count<app_rx_count,即串口当前接收的数据长度小于应用层需要读取的数据长度,才会让read进程休眠,大大降低了cpu的使用率。在这种情况下,read函数没有数据的读取和上传,只有等到rx_count≥app_rx_count才去执行①步骤。

步骤四、设计数据包实时处理机制,如图1所示,即:

本发明将数据包解析放置在驱动层而不放在应用层,主要是为了提高应用层向内核调用数据的实时性。驱动层read读取缓存区接收的数据后,进行数据包解析(如判断帧头和帧尾、校验等),如果数据正确,则通过copy_to_user函数将解析后的数据传递到应用层read函数,如果数据不正确,调用驱动层write函数再一次发送之前的命令信息,通过read函数再一次解析接收数据,如果数据仍不正确,read函数向应用层会发送接收错误信息。通过驱动层两次解析数据,提高了数据的通信正确率,也避免了应用层read函数多次调用内核层read函数,提高了数据通信的实时性。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1