当前位置: 首页 > news >正文

UART驱动情景分析-write

一、write过程分析

  • App写:
    • 使用行规程来写
    • 数据最终存入uart_state->xmit的buffer里
  • 硬件发送:
    • 使用硬件驱动中uart_ops->start_tx开始发送
    • 具体的发送方式有两种:通过DMA、通过中断
  • 中断方式:
    • 方法1:直接使能tx empty中断,一开始tx buffer为空,在中断里填入数据
    • 方法2:写不封数据到tx fifo,使能中断,剩下的数据再次中断里继续发送

二、tty_write

文件在driver\tty\tty_io.c

static ssize_t tty_write(struct file *file, const char __user *buf,size_t count, loff_t *ppos)
{struct tty_struct *tty = file_tty(file);struct tty_ldisc *ld;//...if (!ld->ops->write)ret = -EIO;elseret = do_tty_write(ld->ops->write, tty, file, buf, count);	//使用行规程里的惭怍函数,进行写入//tty_ldisc->tty_ldisc_ops->writetty_ldisc_deref(ld);return ret;
}

三、ldisk write

文件drivers\tty\n_tty.c

static struct tty_ldisc_ops n_tty_ops = {		//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,		//上面ld->ops->write,调用的是这个函数//...
};static ssize_t n_tty_write(struct tty_struct *tty, struct file *file,const unsigned char *buf, size_t nr)
{//...while (1) {//...if (O_OPOST(tty)) {//...} else {struct n_tty_data *ldata = tty->disc_data;while (nr > 0) {mutex_lock(&ldata->output_lock);c = tty->ops->write(tty, b, nr);		//tty_struct->tty_operationsmutex_unlock(&ldata->output_lock);//...}}if (!nr)break;if (file->f_flags & O_NONBLOCK) {		//非阻塞方式的话,直接返回,不等数据发送完retval = -EAGAIN;break;}up_read(&tty->termios_rwsem);wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);		//阻塞方式,等待发送完毕down_read(&tty->termios_rwsem);}//...
}

四、uart_write

文件:drivers\tty\serial\serial_core.c

static const struct tty_operations uart_ops = {.open		= uart_open,.close		= uart_close,.write		= uart_write,//....
};static int uart_write(struct tty_struct *tty,const unsigned char *buf, int count)
{struct uart_state *state = tty->driver_data;struct uart_port *port;struct circ_buf *circ;unsigned long flags;int c, ret = 0;//...port = uart_port_lock(state, flags);circ = &state->xmit;		//赋值寄存器地址//...while (port) {//...memcpy(circ->buf + circ->head, buf, c);		//把数据存入xmit buffercirc->head = (circ->head + c) & (UART_XMIT_SIZE - 1);buf += c;count -= c;ret += c;}__uart_start(tty);		//启动串口发送数据uart_port_unlock(port, flags);return ret;
}static void __uart_start(struct tty_struct *tty)
{struct uart_state *state = tty->driver_data;struct uart_port *port = state->uart_port;if (port && !uart_tx_stopped(port))port->ops->start_tx(port);		//uart_port->uart_ops->start_tx
}

五、硬件相关的发送

相关文件:drivers\tty\serial\imx.c

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,//...
};static void imx_uart_start_tx(struct uart_port *port)
{//...if (!sport->dma_is_enabled) {		//不适用DMA时,比较容易理解,以它为例ucr1 = imx_uart_readl(sport, UCR1);//Transimiter Empty Interrupt Enable,发送buffer为空时,就产生中断//在中断函数里发送字符imx_uart_writel(sport, ucr1 | UCR1_TXMPTYEN, UCR1);}if (sport->dma_is_enabled) {//...}
}

一开始时,发送buffer肯定为空,就会立即产生中断:

static irqreturn_t imx_uart_txint(int irq, void *dev_id)
{struct imx_port *sport = dev_id;unsigned long flags;spin_lock_irqsave(&sport->port.lock, flags);imx_uart_transmit_buffer(sport);spin_unlock_irqrestore(&sport->port.lock, flags);return IRQ_HANDLED;
}static inline void imx_uart_transmit_buffer(struct imx_port *sport)
{struct circ_buf *xmit = &sport->port.state->xmit;//...while (!uart_circ_empty(xmit) &&!(imx_uart_readl(sport, imx_uart_uts_reg(sport)) & UTS_TXFULL)) {/* send xmit->buf[xmit->tail]* out the port here *///UART TX FIFO未满时,从xmit buffer取出数据写入FIFO,更新统计信息imx_uart_writel(sport, xmit->buf[xmit->tail], URTX0);xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);sport->port.icount.tx++;}if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)uart_write_wakeup(&sport->port);if (uart_circ_empty(xmit))imx_uart_stop_tx(&sport->port);
}

相关文章:

UART驱动情景分析-write

一、write过程分析 App写&#xff1a; 使用行规程来写数据最终存入uart_state->xmit的buffer里 硬件发送&#xff1a; 使用硬件驱动中uart_ops->start_tx开始发送具体的发送方式有两种&#xff1a;通过DMA、通过中断 中断方式&#xff1a; 方法1&#xff1a;直接使能tx …...

Metasploit入门到高级【第四章】

来自公粽号&#xff1a;Kali与编程预计更新第一章&#xff1a;Metasploit 简介 Metasploit 是什么Metasploit 的历史和发展Metasploit 的组成部分 第二章&#xff1a;Kali Linux 入门 Kali Linux 简介Kali Linux 安装和配置常用命令和工具介绍 第三章&#xff1a;Metasploi…...

java 继承super

在java继承中&#xff0c;如果子类继承父类&#xff0c;在子类中要给用构造器给父类的属性赋值&#xff0c;需要用到 super 举例&#xff0c;Son类继承Father 类&#xff0c;便于理解 在 new Son(String name, int age) 传入name&#xff0c;和age的值 将会调用Son这个构造器…...

Java学习笔记——多态

2.1 概述 引入 多态是继封装、继承之后&#xff0c;面向对象的第三大特征。 生活中&#xff0c;比如跑的动作&#xff0c;小猫&#xff0c;小狗和大象&#xff0c;跑起来都是不一样的。再比如飞的动作&#xff0c;昆虫、鸟类和飞机&#xff0c;飞起来是不一样的。可见&#x…...

Python处理JSON数据

Python和JSON JavaScript Object Notation (JSON) 是一种轻量级的数据交换格式&#xff0c;通常用于Web应用程序之间的数据交换。JSON的设计使得它非常易于人和机器阅读和编写。JSON数据格式与Python数据结构非常相似&#xff0c;因此Python中提供了一个json模块&#xff0c;用…...

JVM信息查询命令

1、查询jar包运行进程 jps #通过jps命令找出jar的进程IDps -ef|grep xxxx #通过包名找出进程ID2、查询JVM的堆信息 jmap -heap pid #通过jmap命令查询堆信息rootd57bff9f-c8nvn:/apps# jmap -heap 6 Picked up JAVA_TOOL_OPTIONS: -Xloggc:/data/tsf_apm/monitor/jvm…...

redis 面试题

&#x1f355; redis 面试题常规问题什么是 Redis&#xff1f;为什么要使用 Redis&#xff1f;Redis 一般有哪些使用场景&#xff1f;Redis 为什么快&#xff1f;数据类型和数据结构Redis有哪些数据类型&#xff1f;常用操作和应用Bitmaps (位图) | 二进制计数与过滤计数器记录…...

SpringCloud微服务技术栈.黑马跟学(十二)

SpringCloud微服务技术栈.黑马跟学 十二今日目标服务异步通信-高级篇1.消息可靠性1.1.生产者消息确认1.1.1.修改配置1.1.2.定义Return回调1.1.3.定义ConfirmCallback1.2.消息持久化1.2.1.交换机持久化1.2.2.队列持久化1.2.3.消息持久化1.3.消费者消息确认1.3.1.演示none模式1.3…...

HashMap集合存储学生对象并遍历

需求&#xff1a;创建一个HashMap集合&#xff0c;键是学生对象&#xff08;Student&#xff09;,值是居住地。存储多个键值对元素&#xff0c;并遍历。 要求保证键的唯一性&#xff1a;如果学生对象的成员变量值相同&#xff0c;我们就认为是同一个对象 思路&#xff1a; 定义…...

“提效”|教你用ChatGPT玩数据

ChatGPT与数据分析&#xff08;二&#xff09; 上文给简单聊了一下为什么ChatGPT不能取代数据分析师&#xff0c;本文我们来深入感受一下如何让GPT帮助数据分析师“提效”。 场景一&#xff1a;SQL取数 背景&#xff1a;多数数据分析师都要用SQL语言从数据库中提取数据&#x…...

https://app.hackthebox.com/machines/Inject

https://app.hackthebox.com/machines/Inject Ref&#xff1a; 1.https://blog.csdn.net/qq_58869808/article/details/129505388 2.https://blog.csdn.net/m0_73998094/article/details/129474782 info collecting ┌──(kwkl㉿kwkl)-[~/HODL/htb/Inject] └─$ nmap -A …...

Java Web 实战 15 - 计算机网络之网络编程套接字

文章目录一 . 网络编程中的基本概念1.1 网络编程1.2 客户端(client) / 服务器(server)1.3 请求(request) / 响应(response)1.4 客户端和服务器之间的交互数据1.4.1 一问一答1.4.2 多问一答1.4.3 一问多答1.4.4 多问多答二 . socket 套接字2.1 UDP 的 Socket API2.1.1 引子2.1.2…...

基于pdf2docx模块Python实现批量将PDF转Word文档(安装+完整代码教程)

PDF文件是一种常见的文档格式&#xff0c;但是在编辑和修改时不太方便&#xff0c;因为PDF本质上是一种静态的文档格式。因此&#xff0c;有时候我们需要将PDF文件转换成Word格式&#xff0c;以便更好地编辑和修改文档。在本篇文章中&#xff0c;我们将介绍如何使用Python实现P…...

3.21~3.22

识编程语言中的&#xff0c;局部变量&#xff0c;全局变量&#xff0c;以及变量生存周期&#xff0c;整形&#xff0c;浮点型数据的内存表示&#xff0c;od的内存窗口的使用 先看一个代码样例 #include<windows.h> #include<stdio.h>#pragma warning(disable:499…...

Chromium 改造实录:增加 MPEG TS 格式支持

在《选择最新 Chromium&#xff0c;支持 H264 / H265》一文中&#xff0c;记录了我通过升级 Chromium 版本解决了 H264 / H265 视频支持难题。然而难题接踵而至&#xff0c;这次的难题是 MPEG TS 流的支持。MPEG2-TS 传输流广泛应用于数字电视广播系统&#xff0c;所以是一个不…...

性能优化之-事件代理

js中的事件委托或是事件代理简单理解 事件委托也叫事件代理&#xff0c;“事件代理”即是把原本需要绑定在子元素的响应事件&#xff08;click、keydown…&#xff09;委托给父元素&#xff0c;让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。 概述&#x…...

MSDS 即化学品安全说明书

MSDS 即化学品安全说明书&#xff0c;亦可译为化学品安全技术说明书或化学品安全数据说明书&#xff0c;是化学品生产商和进口商用来阐明化学品的理化特性&#xff08;如PH值&#xff0c;闪点&#xff0c;易燃度&#xff0c;反应活性等&#xff09;以及对使用者的健康&#xff…...

真人手办没法实现网购?我有一个好办法!

记得以前在网上看到过一个冷笑话式的问答&#xff0c;问的是中国最早的手办是什么&#xff0c;有网友回答是秦始皇兵马俑&#xff0c;这个抖机灵式的回答简直妙得让人会心一笑。 你接触过手办吗&#xff1f; 提到手办&#xff0c;大家第一时间想到的&#xff0c;肯定都会是各…...

2019湖南省大学生程序设计竞赛题解(D)

D-Modulo Nine 很妙的类似区间dp&#xff0c; 我自己是想不到&#xff0c;本题解题思路来自学长的博客&#xff1a; 长沙橘子猫 题意 有一个长度为 nnn 的序列&#xff0c;你可以给每个位置填 0∼90\sim90∼9 的一个数&#xff0c;有 mmm 个限制&#xff0c;每个限制 [li,ri…...

【开发】中间件——RocketMQ

分布式消息系统 RocketMQ概念&#xff0c;用途&#xff0c;特性安装RocketMQ掌握RocketMQ的api使用对producer、consumer进行详解了解RocketMQ的存储特点 简介及相关概念JavaAPISpringBoot整合RocketMQ消息的顺序收发消息系统的事务、存储、重试策略消息系统的集群 RocketMQ R…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...

uni-app学习笔记三十五--扩展组件的安装和使用

由于内置组件不能满足日常开发需要&#xff0c;uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件&#xff0c;需要安装才能使用。 一、安装扩展插件 安装方法&#xff1a; 1.访问uniapp官方文档组件部分&#xff1a;组件使用的入门教程 | uni-app官网 点击左侧…...