NXP i.MX8系列平台开发讲解 - 3.19 Linux TTY子系统(二)

62348318f81043abb7388ce3bd435859.png

专栏文章目录传送门:返回专栏目录5ceabff517714259aba8c604e56841b4.png

Hi, 我是你们的老朋友,主要专注于嵌入式软件开发,有兴趣不要忘记点击关注【码思途远】


目录

 

1. Linux 串口驱动

1.1 Uart 驱动注册流程

1.2 uart 操作函数

1.3 line discipline

2. Linux tty应用层使用

2.1 UART 操作步骤

2.2 UART 使用注意要点

3. 总结


本章节主要对Linux 下tty 相关设备,以serial进行一些分析;

  • cpu: i.mx8mq

  • OS:Android 11

  • Kernel version:kernel 5.10

根据上一章节对TTY的整个框架有一些简单了解,常说的串口驱动也一并进行简单说明,对tty调用至串口相关的整个流程进行讲解。

1. Linux 串口驱动

Linux 串口整个驱动在嵌入式中使用率是非常非常高的一个部分,常用用于打印调试。先查看串口驱动的整个层次结构情况,主要是串口驱动与tty驱动的关系紧密。

a8f7def04d4548ac8ef6b7e2f84d53f0.png

对于TTY Core 层中,已经在Linux tty子系统介绍(一)已经有大致提到,主要是为用户层提供相关接口,为下层各种不一样的tty 进行管理;

Serial Core 层:Serial Core 层提供了一个抽象层,用于表示和处理串口设备。它定义了一组通用的接口和数据结构,使得不同类型的串口设备能够在同一接口上进行交互。

Uart driver 层:UART Driver Layer 提供了一个硬件抽象层,允许不同型号和厂商的 UART 控制器以统一的方式与 Linux 内核交互。这种抽象层使得 Linux 内核能够适应各种不同的硬件实现。

1.1 Uart 驱动注册流程

串口驱动的注册主要包含:UART驱动注册,platform 平台注册

UART驱动注册:

uart_register_driver(&imx_uart_uart_driver);

ee448c22c88b4bd78c1c1fd2d0fa41f7.png

注册流程图

从注册流程来看,最终会注册到一个TTY设备,将会在文件系统产生一个tty 设备,这样可以提供给应用程进行调用控制UART.

主要代码接口uart_register_driver

关于代码调用相关:

这里引用TTY 驱动设备创建过程:

313f84b30a33457c88d1dbb0f277eee0.png

platform 平台注册:

platform_driver_register(&imx_uart_platform_driver);

这一步注册了一个平台驱动。imx_uart_platform_driver 是一个 platform_driver 结构体的实例,它定义了平台驱动的属性和操作函数,包括匹配、探测、移除等操作。平台驱动负责与具体的硬件平台进行交互。

主要用于总线匹配:

d604533abf9c433f9a0384140806d032.png

通过 platform_driver_registerplatform_driver 结构体注册到内核,内核因此知道有一个新的平台驱动可以处理特定的平台设备。

1.2 uart 操作函数

串口驱动的 uart_ops 结构体包含了uart 的操作函数。在不同平台SoC需要实现该操作函数。

static const struct uart_ops imx_uart_pops = {.tx_empty       = imx_uart_tx_empty,      // 检查发送缓冲区是否为空.set_mctrl      = imx_uart_set_mctrl,     // 设置调制解调器控制信号.get_mctrl      = imx_uart_get_mctrl,     // 获取调制解调器控制信号.stop_tx        = imx_uart_stop_tx,       // 停止发送数据.start_tx       = imx_uart_start_tx,      // 开始发送数据.stop_rx        = imx_uart_stop_rx,       // 停止接收数据.enable_ms      = imx_uart_enable_ms,     // 启用调制解调器状态中断.break_ctl      = imx_uart_break_ctl,     // 控制串口的断点信号.startup        = imx_uart_startup,       // 启动串口.shutdown       = imx_uart_shutdown,      // 关闭串口.flush_buffer   = imx_uart_flush_buffer,  // 刷新发送和接收缓冲区.set_termios    = imx_uart_set_termios,   // 设置串口的参数(波特率、数据位、停止位等).type           = imx_uart_type,          // 获取串口类型.config_port    = imx_uart_config_port,   // 配置串口端口.verify_port    = imx_uart_verify_port,   // 验证串口端口
#if defined(CONFIG_CONSOLE_POLL).poll_init      = imx_uart_poll_init,     // 初始化轮询模式.poll_get_char  = imx_uart_poll_get_char, // 在轮询模式下获取字符.poll_put_char  = imx_uart_poll_put_char, // 在轮询模式下发送字符
#endif
};

假如在RK3588平台,同样需要实现uart_ops的操作函数。

1.3 line discipline

在架构图中可以发现有一个line discipline,这个作用是什么?

line discipline是线路规划意思,是TTY子系统中的一个比较重要概念,它在字符设备和用户空间之间扮演了一个中间层的角色,处理从用户空间传入的数据和从硬件传出的数据。它的主要作用是提供一个可插拔的处理机制,使得不同的协议和数据处理方式可以方便地集成到串口驱动中。

line discipline代码中结构体 tty_ldisc_ops 代表不同的线路规程(line discipline),每种线路规程实现了一种特定的数据处理方式或协议。

734f4a7288464f0c9f24f5672913be6c.png

比如:

N_TTY:默认线路规划,用于标准的字符终端输入输出处理。它处理基本的控制字符(如回车、删除等),并提供行缓冲和行编辑功能。

N_PPP:用于点对点协议(PPP)处理,适用于通过串口进行的网络连接。它负责处理 PPP 的帧封装和解封装。

N_SLIP:用于串行线路互联网协议(SLIP)处理。SLIP 是一种简单的封装协议,用于在串行接口上传输 IP 数据报。

N_R3964:用于西门子的 R3964 协议,通常用于工业控制系统。它实现了西门子硬件设备的通信协议。

最常用的就是n_tty,源码路径:drivers/tty/n_tty.c

static struct tty_ldisc_ops n_tty_ops = {.magic           = TTY_LDISC_MAGIC,.name            = "n_tty",.open            = n_tty_open,.close           = n_tty_close,.flush_buffer    = n_tty_flush_buffer,.read            = n_tty_read,.write           = n_tty_write,.ioctl           = n_tty_ioctl,.set_termios     = n_tty_set_termios,.poll            = n_tty_poll,.receive_buf     = n_tty_receive_buf,.write_wakeup    = n_tty_write_wakeup,.receive_buf2    = n_tty_receive_buf2,
};

2. Linux tty应用层使用

对于TTY 应用层中的UART 来说,可以发现并没有像其他通信串口IIC,SPI具体设备驱动,关于具体设备一般都在应用层实现。对于 应用层中只有简单的一些操作。

2.1 UART 操作步骤

打开串口设备

配置串口参数

读写数据

关闭串口设备

这几个步骤 需要注意在配置串口举例子:

#include <termios.h>
​
struct termios options;
tcgetattr(fd, &options);  // 获取当前串口配置
​
// 设置波特率
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
​
// 设置控制模式
options.c_cflag |= (CLOCAL | CREAD);  // 允许接收数据
options.c_cflag &= ~PARENB;           // 无校验
options.c_cflag &= ~CSTOPB;           // 一位停止位
options.c_cflag &= ~CSIZE;            // 清除数据位掩码
options.c_cflag |= CS8;               // 数据位 8
​
// 设置输入模式
options.c_iflag &= ~(IXON | IXOFF | IXANY);  // 关闭软件流控制
​
// 设置输出模式
options.c_oflag &= ~OPOST;  // 原始输出模式
​
// 设置本地模式
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);  // 原始输入模式
​
// 设置新的串口配置
tcsetattr(fd, TCSANOW, &options);

关于读写操作普通的write read等。

2.2 UART 使用注意要点

使用串口通信需要注意的是:

波特率的问题: 需要与通信接口的波特率一直既可。

阻塞和非阻塞模式:在阻塞模式下,读写操作会一直等待直到完成;在非阻塞模式下,读写操作会立即返回,应用程序需要使用轮询或其他方法来检查是否有数据可用或是否已经完成写入。

串口设备文件权限:确保应用程序对串口设备文件有足够的访问权限,否则可能无法打开串口。

3. 总结

本文主要以串口驱动去介绍TTY 相关的知识,主要对串口驱动注册流程,一些重要操作函数进行简单分析,对于应用层来说是一个非常通用的用法,不过在遇到一些通信不上的时候,通过一些排查手法进行查看问题。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/47281.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FPGA 实现DDR4的读写

1 硬件设计 FPGA 端&#xff1a; DDR4: 2 验证方案 3 仿真验证 4 DDR4 下板验证

《昇思25天学习打卡营第25天|第10天》

今天是打卡的第十天&#xff0c;今天开始学应用实践中的LLM原理和实践&#xff0c;今天学的是基于MindSpore实现BERT对话情绪识别。最先了解的是BERT模型的简介&#xff08;来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&…

NodeJS技巧:在循环中管理异步函数的执行次数

背景介绍 在现代Web开发中&#xff0c;NodeJS因其高效的异步处理能力而备受青睐。尤其在数据抓取、网络爬虫等应用场景中&#xff0c;NodeJS的非阻塞I/O特性使其成为不二之选。然而&#xff0c;在实际编程过程中&#xff0c;我们经常会遇到一个棘手的问题——如何在循环中控制…

各地跨境电子商务示范区工具变量DID数据(2010-2022年)

数据来源&#xff1a;参考李震等&#xff08;2023&#xff09;的做法&#xff0c;从官方网站上搜集整理了我国跨境电子商务示范区名单与上市公司进行匹配制作。时间跨度&#xff1a;2010-2022年数据范围&#xff1a;上市企业包含指标&#xff1a; stock year 证券简称 In…

个性化画册制作方法,快来看看

画册&#xff0c;不仅仅是一本书&#xff0c;它是记忆的宝库&#xff0c;是时光的缩影。随着技术的进步&#xff0c;个性化画册的制作已经不再是一件困难的事情。今天&#xff0c;就让我来为大家揭开个性化画册制作的神秘面纱&#xff0c;带你一起创造独一无二的回忆。 第一步&…

数据库内核研发学习之路(三)创建postgres内置函数

本章之前已经讲明白了我们的postgres如何进行编译安装&#xff0c;这是很重要的一步&#xff0c;接下来就是学会对postgres进行小的改动&#xff0c;然后保证依然能够顺利编译安装运行&#xff01; 本章续讲内容如何创建一个内置函数。 1、内置函数和用户自定义函数的区别 熟…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【查询密钥别名集(ArkTS)】

查询密钥别名集(ArkTS) HUKS提供了接口供应用查询密钥别名集。 开发步骤 初始化密钥属性集。用于查询指定密钥别名集TAG&#xff0c;TAG仅支持HUKS_TAG_AUTH_STORAGE_LEVEL。调用接口[listAliases]&#xff0c;查密钥别名集。 HarmonyOS与OpenHarmony鸿蒙文档籽料&#xff1…

入门小结:JavaScript小白语法

一、变量 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…

Boost中线程的使用

目录 boost的线程基本用法 boost:condition thread_group 线程组 thread_pool boost的线程基本用法 boost::thread Thread_GenerateUuid;boost::thread Thread_ShowUuid;boost::mutex mutex;std::queue<std::string>UuidQueue;void procGenerateUuid();void showUuid…

vmware_虚拟机安装zabbix_超快超简单

TIPS: 一开始用docker 和 安装包&#xff0c;安装zabbix总是有问题&#xff0c;后发现zabbix官方提供了装好的虚拟机 1、下载VMware pro 个人免费版 官网地址如下 https://support.broadcom.com/group/ecx/productdownloads?subfamilyVMwareWorkstationPro 如果提示注册&am…

服务器数据恢复—开盘修复raid5阵列硬盘故障的数据恢复案例

服务器存储数据恢复环境&#xff1a; 某品牌P2000存储&#xff0c;存储中有一组由8块硬盘&#xff08;包含一块热备盘&#xff09;组建的raid5阵列。上层部署VMWARE ESX虚拟化平台。 服务器存储故障&#xff1a; 存储在运行过程中有两块硬盘指示灯亮黄色。经过运维人员的初步检…

Go语言中GC(垃圾回收回收机制)三色标记与混合写屏障

5、Golang三色标记混合写屏障GC模式全分析 (yuque.com) 第1讲-课程目标_哔哩哔哩_bilibili Golang三色标记GC混合写屏障 Go V1.3之前的标记清除&#xff08;mark and sweep) 垃圾回收、内存管理、自动适放、三色标记法、STW (stop the world) 图的遍历&#xff1f;可达性分…

【Git】(基础篇二)—— Git操作

Git操作 在了解git理论知识之后&#xff0c;本文将结合实践操作为你讲解git的底层逻辑 Git的安装和配置 git官网下载&#xff1a;https://git-scm.com/ 下载后安装时除了选择安装地址外&#xff0c;其余都保持默认下一步即可。 安装好后鼠标右键会出现两个新的选项【Open …

基于 JAVA 的旅游网站设计与实现

点击下载源码 塞北村镇旅游网站设计 摘要 城市旅游产业的日新月异影响着村镇旅游产业的发展变化。网络、电子科技的迅猛前进同样牵动着旅游产业的快速成长。随着人们消费理念的不断发展变化&#xff0c;越来越多的人开始注意精神文明的追求&#xff0c;而不仅仅只是在意物质消…

项目JetCache的常见配置与使用

Hello, 大家好&#xff0c;今天本汪给大家带来的是JetCache在项目中的常见配置与用法讲解&#xff0c;接下来&#xff0c;随本汪一起来看看吧 一、介绍 官网地址&#xff1a;https://github.com/alibaba/jetcache JetCache 是一种 Java 缓存抽象&#xff0c;它为不同的缓存…

秘密,一般人我不告诉他.偷偷告诉你信创产品采购的正确打开方式:python爬虫实现

创作不易 只因热爱!! 热衷分享&#xff0c;一起成长! “你的鼓励就是我努力付出的动力” 采购XX有没有找你诉说 , 某某ZFCG网上的信创产品, 品种太多太杂,无法细分查找,某某详情页面要一个个看, 真费时费力,于是乎… !!!以下内容仅供学习使用,便于快速筛选找到需求产品!!!请勿…

【算法/序列】等差数列子序列算术序列最长对称子串

概念&#xff1a; 等差数列&#xff1a;任意两项的差总等于同一个常数 子数组 &#xff1a;是数组中的一个连续序列。 子序列&#xff1a;是通过从原序列删除零个或多个元素并在不改变顺序的情况下排列其余元素而获得的序列 算术序列&#xff1a;是一个数字列表&#xff0c;其中…

【时时三省】(C语言基础)变量

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ——csdn时时三省 变量 可以改变的量 比如 int age&#xff1d;20 &#xff08;类型 变量的名字&#xff1d;0&#xff09; 如果后面要改可以直接代入 age&#xff1d;age1 age可以是任何字母 变量的分类…

【C++】类和对象的基本概念与使用

本文通过面向对象的概念以及通俗易懂的例子介绍面向对象引出类和对象。最后通过与之有相似之处的C语言中的struct一步步引出C中的类的定义方式&#xff0c;并提出了一些注意事项&#xff0c;最后描述了类的大小的计算方法。 一、什么是面向对象&#xff1f; 1.面向对象的概念 …

【C++编程】标准模板库 STL 的基本概念

STL 从广义上分为&#xff1a;容器、算法、迭代器 容器、算法之间通过迭代器进行无缝连接 STL 六大组件&#xff1a; 容器&#xff1a;各种数据结构&#xff0c;如 vector、list、deque、set、map 等&#xff0c;用来存放数据 序列式容器&#xff1a;物理存放上有序关联式容器&…