linux串口子系统设备及端口注册及注销接口说明

 

     上一章我们介绍了串口的数据结构,本章我们介绍串口相关的操作接口,并介绍串口的注册与注销接口,本章主要包括如下几个方面的内容:

 

串口控制器、串口的注册与注销

       既然串口子系统是对tty子系统的封装,因此其注册与注销也同样包括tty_driver、tty_port两部分。在之前阅读tty子系统时,我们可以发现真正实现读写tty端口的操作全部是由tty_driver数据结构中的操作接口实现的,而tty_port中仅仅是实现具体tty端口的使能与去使能等操作。而在串口子系统中,为了减少开发量,同时又要对接tty子系统,串口子系统内部为tty_driver注册了通用的操作接口,而把不同串口控制器操作接口的操作又移至uart_port->ops接口中,从而使串口驱动的开发只需要关注uart_potr->ops即可,无需再同时关注tty_driver->ops、tty_port->ops。

串口控制器驱动注册与注销

      针对串口控制器驱动,其注册接口为uart_register_driver,而针对uart_driver的注册,开发人员主要需要设置uart_driver的driver_name、dev_name、nr、cons,其中dev_name、nr表示串口的名称前缀、串口个数,而cons则表示该串口控制器是否支持控制台功能,若支持控制台则设置该变量。

        如下就是uart_driver的注册接口,其实现的功能较简单,主要功能如下:我们知道tty_port中包含接收数据的缓存,但却没有发送数据的缓存,而uart_state中则包含了发送数据的缓存(即环形缓存区),因此借助uart_state、tty_port则实现了串口收发数据的缓存(在我们之前实现的虚拟串口中也定义了数据发送的buff,只不过是使用kfifo实现的)。

 

linux串口子系统设备及端口注册及注销接口说明

      从上面的代码我们可以看到,针对所有的uart_driver,其tty_driver成员的ops都设置为uart_ops接口,而uart_ops的定义如下,下面简要说明下其实现的功能:

 

linux串口子系统设备及端口注册及注销接口说明

    在主要的接口中,也设置了tty_port->ops成员,我们看下uart定义的tty_port操作接口函数,这几个接口也捎带说明下:针对uart子系统而言,在其uart_tty_driver->open接口中,并没有调用tty_port_open接口,取而代之的是uart_startup、uart_ops->start,因此只需要实现uart_ops->start接口即可,此处定义的uart_port_activate并不会被调用,没有意义。。。接口中,也没有调用uart_port_ops->shutdown接口(即uart_port_shutdown)

因此此处设置的activate、shutdown,没有任何意义,没有必要设置这两个变量

 

 

但是uart_port_shutdown也会被uart_shutdown接口调用。

 

linux串口子系统设备及端口注册及注销接口说明

 

串口的注册接口

串口的注册接口为uart_add_one_port,该接口的定义如下,主要功能说明如下:

 

linux串口子系统设备及端口注册及注销接口说明

 

     在uart port的注册时,为其对应的device创建了属性文件(即tty_dev_attr_groups),我们看下tty_dev_attr_groups的定义。包含的属性如下所示,包括串口类型、index、端口的iobase、中断、flag、发送fifo大小、uart clk、iomem_base等,当我们需要获取一个串口详细信息时,可进入串口对应的sysfs文件下对应文件中查看(我之前实现的虚拟串口也创一个文件属性,用于模拟向虚拟串口发送,当时是调用sysfs_create_group实现的,其实tty_port_register_device_attr接口即可实现tty port注册+创建属性文件,哎,我没看这个接口啊…)。

linux串口子系统设备及端口注册及注销接口说明

串口子系统操作接口的介绍说明

     串口子系统提供的操作接口包含uart_open、uart_close、uart_write、uart_put_char、uart_flush_chars、uart_write_room、uart_chars_in_buffer、uart_flush_buffer、uart_ioctl、uart_throttle、uart_unthrottle等接口,在上面也做了简要说明,此处则对应uart_open、uart_write这两个接口进行一个说明

uart_open接口

      一般针对tty_driver->open接口而言,基本上就是调用tty_port_open接口,增加tty_port的引用计数、完成tty_port与tty_struct的关联,并调用tty_port->ops->active接口,使能该tty端口;而在串口的open函数中,虽然没有调用tty_port_open接口,但也实现了其中的tty_port的引用计数、完成tty_port与tty_struct的关联,也调用tty_port_block_til_ready等待该串口可用。因没有调用tty_port->ops->active接口,uart_open则通过调用uart_startup使能一个串口。

 

下面看下该接口的实现,该接口实现如下流程图(省略了异常判断),主要功能如下:

 

linux串口子系统设备及端口注册及注销接口说明

 

而tty_port_block_til_ready的作用如下:

 

uart_write接口

该接口的实现比较简单,代码如下:

linux串口子系统设备及端口注册及注销接口说明

 

 

串口驱动开发流程说明

      基本上完成以上几步,即完成了一个串口驱动,其实最主要的就是实现struct uart_ops中各成员函数指针。下一章我们来完成一个虚拟的串口设备及其驱动。

 

串口子系统架构总结

     串口子系统针对所有串口,完成了统一的tty_driver的变量的实现,而将每一个串口需要实现的内容全部移至uart_port、uart_pos中,而无需实现tty_driver的操作接口、tty_port的操作接口(均由串口子系统内部实现)。相对于tty子系统而言,确实方便了一些。