在上一章我们已经说明了uart驱动的开发流程,本章我们就不再介绍uart相关的接口实现,仅通过实现一个虚拟的串口控制器程序,用以说明虚拟串口的开发流程。

本次开发的虚拟串口提供的功能如下:

  1. 提供两个串口实例
  2. 串口名称的前缀为vttyU
  3. 为了验证串口收发,提供了loopback机制,即应用程序向虚拟串口写入数据后,数据再回环至应用程序;
  4. 在/sys目录下提供数据写入属性文件,可向虚拟串口中写入数据,用以模拟串口接收数据的功能

本次开发的代码涉及的模块包括:

  1. 创建两个platform device,分别对应两个虚拟串口的platform device;
  2. 创建一个platform driver,在platform driver的probe接口中,完成虚拟串口的注册,主要是完成uart_add_one_port接口完成虚拟串口的注册;在platform driver的remove接口中,完成虚拟串口的注销;
  3. 在串口驱动的初始化函数中,调用uart_register_driver,uart driver的注册。

数据结构说明

在虚拟串口驱动中,定义了数据结构virtual_uart_port,该数据结构中包含了uart_port。并定义了tx_enable_flag、rx_enable_flag,分别用于控制串口收发,因是虚拟串口所以使用这两个变量进行表示,若是真是的串口控制器,则不需要这两个变量,而只需要在uart_ops->startup、uart_ops->stop_rx、uart_ops->stop_tx中关闭中断即可,这两个变量由自旋锁write_lock进行保护。

uart_driver定义及注册

定义virtual_uart_driver,本串口控制器驱动支持的串口个数为MAX_VIRTUAL_UART(6个)、而dev_name则为该虚拟串口对应字符设备文件名称的前缀,本次定义前缀为“vttyU”,本串口不支持控制台。调用uart_register_driver即完成本串口控制器驱动的注册与注销

Platform device定义及注册

本次我们主要完成了串口的注册,因此我们定义并注册了两个platform device,而传递的参数为串口的index的。接口定义如下所示,platform device的name为“virtual_uart_port_dev”,根据该名称可完成与platform driver的匹配及探测功能(因我们在ubuntu16.04下完成的验证,没有设备树概念,因此就定义了这两个platform device,若支持设备树,则无须我们手动定义这两个platform device,只需要修改设备树文件即可)。

Platform driver的定义及注册

我们的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接口的定义如下,主要实现的功能如下:

  1. 为uart_port申请内存,并设置uart_port的ops、fifosize、type、line等值,另外还可为该uart_port创建uart_port相关的私有属性文件(sysfs下),而在linux3.10的内核中uart_port中并没有定义attr_group变量,导致uart_add_one_port接口只能在tty_port对应device中创建uart核心定义的属性文件,而不能创建uart port私有的属性文件,而在后面的内核中特意增加了attr_group,用于创建uart port私有的属性文件,这个成员变量增加的挺好,本次虚拟串口就借助该变量创建了属性文件uart_receive_buff,用于模拟串口接收数据。
  2. 初始化一个工作队列及其回调函数virtual_uart_flush_to_port,该接口主要是模拟串口发送中断的功能,在真实的串口控制器中,则是申请串口中断,在串口中断的处理函数中进行数据的发送,而我们这个工作队列则是模拟串口中断函数的功能;
  3. 调用uart_add_one_port,完成串口的添加。

Uart port操作接口定义

我们为虚拟串口定义的操作接口如下

  1. 其中tx_empty接口用于测试发送缓存是否为空(uart_port的环形缓冲区);
  2. stop_tx用于停止发送操作(在真实串口控制器驱动中,则关闭发送中断即可);
  3. start_tx用于启动发送操作(在真实串口控制器驱动中,则开启发送中断,然后则触发发送中断,继而在发送中断处理接口中执行数据的发送操作,而在我们的虚拟串口中,则调用schedule_work,启动工作队列,调用工作队列的回调函数进行数据发送);
  4. throttle、unthrottle则是流控操作,在真实串口中则设置相应定时器即可(本驱动未实现该功能);
  5. stop_rx用于停止接收操作(在真实串口控制器驱动中,则关闭接收中断即可)
  6. startup接口主要是启动串口功能(在真实串口控制器驱动中,则申请中断,并使能接收中断;而发送中断的使能在start_tx中实现,而在我们虚拟串口驱动中,则是使能收发数据的flag);
  7. set_termios则主要是设置termios相关参数(包括字节宽度、波特率等参数的设置);

而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写数据,从而模拟串口接收数据

测试验证

  1. 在应用程序中打开/dev/vttyU1,进行数据接收;
  2. 向/sys/class/tty/vttyU1/uart_receive_buff写数据,则上述1中的进程即会接收到数据,测试截图如下

至此我们完成了虚拟串口驱动代码的实现以及验证工作,我们也完成了tty子系统、uart子系统架构内部实现流程的分析,也完成了对应虚拟控制器驱动的实现及验证,下一次我们开始进行input子系统的分析(关于本驱动的源码,后续我们会把链接发出来)。

抱歉,忘记把代码链接放出来,链接地址如下:https://gitee.com/jerry_chg/virt_uart

linux虚拟串口控制器驱动开发及代码实现(uart driver)相关推荐

  1. linux 控制虚拟串口,linux虚拟串口控制器实现-适用于无开发板学习tty driver-好向圈...

    在前面几章,我们介绍了tty子系统的框架.数据结构.tty驱动的注册与注销等内容,本章我们借助 之前学习的内容开发一个虚拟的串口控制器驱动,以便我们理解开发串口驱动的步骤及驱动开发实践. 本次实现的虚 ...

  2. c++创建虚拟串口_linux虚拟串口控制器驱动实现——适用于无开发板学习串口驱动...

    在上一章我们已经说明了uart驱动的开发流程,本章我们就不再介绍uart相关的接口实现,仅通过实现一个虚拟的串口控制器程序,用以说明虚拟串口的开发流程. 本次开发的虚拟串口提供的功能如下: 提供两个串 ...

  3. linux pl320 mbox控制器驱动分析-(3) pl320驱动代码分析

    linux pl320 mbox控制器驱动分析-(3)pl320驱动代码分析 1 pl320 mbox控制器宏定义 2 初始化接口 3 ipc_handler mbox中断处理函数 4 数据的收发 4 ...

  4. 32驱动_轻松掌握pinctrl子系统驱动开发——一个虚拟pinctrl dev驱动开发

    这周主要对pinctrl子系统进行分析,该分析的基本上已经分析完成,唯一没有细说的估计就是gpio与pinctrl之间的关联了.本章即是pinctrl子系统分析的最后一章,本章我们主要实现一个虚拟的p ...

  5. 嵌入式linux之SPI控制器驱动

    这篇文章粗略的浏览一下linux的SPI控制器驱动,我们知道SPI的device和driver是通过虚拟总线联系在一起的,但在spi_driver中有个spi控制器,这个控制器是怎么回事呢?spi控制 ...

  6. 嵌入式linux ASoC架构声卡驱动开发

    嵌入式linux ASoC架构声卡驱动开发 文章目录 嵌入式linux ASoC架构声卡驱动开发 需求分析 ASoC架构下声卡驱动代码结构 codec驱动 snd_soc_register_codec ...

  7. Linux下LED设备驱动开发(LED灯实现闪烁)

    文章目录 一.配置连接说明 二.更新设备树 (1)将led灯引脚添加到pinctrl子系统 (2)设备树中添加LDE灯的设备树节点 (3)编译更新设备树 三.驱动开发与测试 (1)编写设备驱动代码 ( ...

  8. linux pl320 mbox控制器驱动分析 - (1) pl320手册分析

    linux pl320 mbox控制器驱动分析 1 pl320简介 1.1 pl320用途 1.2 pl320 IPCM 由以下部分组成: 1.3 pl320 IPCM可配置的参数 1.4 功能操作 ...

  9. linux can总线接收数据串口打包上传_使用Zedboard开发板学习Linux的移植及驱动开发...

    本文是昨天发的文章<龙芯杯CPU设计竞赛与ZYNQ设计流程介绍>接续部分.重点介绍传统方式的Linux移植和Xilinx的Petalinux的快速移植开发两种. 部分硬件设计中需要CPU完 ...

  10. Linux下按键设备驱动开发以及对中断的上半部分和下半部分详细介绍

    文章目录 一.编写并且加载设备树插件 (1)检测管脚是否占用 (2)添加设备树插件 (3)加载设备树插件 二.中断相关函数 (1)request_irq中断注册函数 (2)free_irq中断注销函数 ...

最新文章

  1. html当作附件发送,MIME以HTML文件作为附件发送电子邮件?
  2. RCP开发小技巧(二)
  3. Android开发--图形图像与动画(二)--Animation实现图像的 渐变、缩放、位移、旋转
  4. PyTorch 0.4新版本 升级指南 no_grad
  5. 基于c语言的linux嵌入式开发入门
  6. nginx配置文件语法高亮的Sublime Text扩展
  7. 使用 CefSharp 在 C# App 中嵌入 Chrome 浏览器
  8. yum 来安装 nodejs
  9. ebpf_exporter - Prometheus exporter for custom eBPF metrics
  10. Physical Plausible Shading
  11. matlab泛函分析,Matlab数字图像处理的学习建议 – MATLAB中文论坛
  12. 安装 samba 记录
  13. express 4.x 获取post提交的数据
  14. 简单工具之 ---- IP地址快速修改脚本
  15. Java - JSP和Servlet是什么关系?
  16. 计算机声卡的步骤,声卡调试教程
  17. ue4风格化材质_风格化材质 - 游戏蛮牛 - Unreal中文翻译用户手册
  18. 微信小程序转发功能的实现
  19. xp系统打不开vba服务器,xp系统打不开360安全卫士的解决方法
  20. Quoted-Printable编码原理及代码实现

热门文章

  1. 几何分布的期望和方差公式推导_二项分布与负二项分布的均值与方差推导
  2. vue项目PC端移动端适配方案
  3. 了解新型计算机ppt,第1章计算机系统基础ppt课件.ppt
  4. nmds与mds的区别_PCA、PCoA、NMDS、CCA、RDA傻傻分不清楚
  5. 【转载】华为荣耀V9的手机录屏功能如何开启
  6. VMware虚拟机中Windows内存扩展
  7. NX/UG二次开发—CAM—获取、修改程式的切削参数
  8. gvim【一】【安装和基本使用】
  9. 【Unity】出现NullReferenceException:Object reference not set to an instance of an object.的原因总结
  10. R语言| 缺失值判断