在上一章我们已经说明了uart驱动的开发流程,本章我们就不再介绍uart相关的接口实现,仅通过实现一个虚拟的串口控制器程序,用以说明虚拟串口的开发流程。
本次开发的虚拟串口提供的功能如下:
本次开发的代码涉及的模块包括:
在虚拟串口驱动中,定义了数据结构virtual_uart_port,该数据结构中包含了uart_port。并定义了tx_enable_flag、rx_enable_flag,分别用于控制串口收发,因是虚拟串口所以使用这两个变量进行表示,若是真是的串口控制器,则不需要这两个变量,而只需要在uart_ops->startup、uart_ops->stop_rx、uart_ops->stop_tx中关闭中断即可,这两个变量由自旋锁write_lock进行保护。
定义virtual_uart_driver,本串口控制器驱动支持的串口个数为MAX_VIRTUAL_UART(6个)、而dev_name则为该虚拟串口对应字符设备文件名称的前缀,本次定义前缀为“vttyU”,本串口不支持控制台。调用uart_register_driver即完成本串口控制器驱动的注册与注销
本次我们主要完成了串口的注册,因此我们定义并注册了两个platform device,而传递的参数为串口的index的。接口定义如下所示,platform device的name为“virtual_uart_port_dev”,根据该名称可完成与platform driver的匹配及探测功能(因我们在ubuntu16.04下完成的验证,没有设备树概念,因此就定义了这两个platform device,若支持设备树,则无须我们手动定义这两个platform device,只需要修改设备树文件即可)。
我们的platform driver的定义如下,支持probe、remove接口,probe接口主要完成uart port的注册、remove接口主要完成uart port注销,该platform driver的name为“virtual_uart_port_dev”,通过该名称可进行platform device与platform driver的匹配检测,同时我们也定义了of_device_id,若内核支持设备树,则在设备树中的compatible中也设置“jerry_chg,virtual-uart”,即可完成platform device与platform driver的匹配检测。
virtual_uart_port_platform_probe接口的定义如下,主要实现的功能如下:
我们为虚拟串口定义的操作接口如下
而set_mctrl接口则一定要定义,即使是一个空函数也要定义。
因为我们是虚拟串口,但是又要模拟串口接收功能,因此我们在tty port对应的device中,定义了模拟串口接收数据的属性文件,定义如下:
当用户向该属性文件(uart_receive_buff)中写数据时,则在该属性文件的store接口中,将写入的数据发送到tty_port的接收缓存中,并通过调用tty_flip_buffer_push接口,将tty_port接收缓存中的数据通过线路规程的receive_buff接口将数据刷新到tty_struct的接收缓存中,并wakeup读等待队列中sleep的读线程(这一系统的操作流程可参考我之前写的几篇文档),即将数据发送的该串口上的读线程中。
我们可以通过如下脚本向uart_receive_buff写数据,从而模拟串口接收数据
至此我们完成了虚拟串口驱动代码的实现以及验证工作,我们也完成了tty子系统、uart子系统架构内部实现流程的分析,也完成了对应虚拟控制器驱动的实现及验证,下一次我们开始进行input子系统的分析(关于本驱动的源码,后续我们会把链接发出来)。