嵌入式学习-驱动开发-lesson6.3-UART驱动send和receive流程分析

来源:互联网 发布:理性 知乎 编辑:程序博客网 时间:2024/05/17 21:55

四、串口驱动分析–数据发送

本课需要解决的知识点是:
1.当使用write系统调用时,是如何一步一步传递到串口驱动来的,
2.当串口驱动接收到来自用户空间的发送数据请求后,如何实现发送

1)TTY数据发送调用关系

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述
tty_write又调用线路规程中的n_tty_write
这里写图片描述

这里写图片描述
在n_tty_write中,
这里写图片描述

这里写图片描述
在uart_write函数中,又会调用uart_start
这里写图片描述
uart_start调用__uart_start函数,
这里写图片描述

这里写图片描述

这里写图片描述
上面的函数调用关系,总结如下:
这里写图片描述

s3c24xx_serial_start_tx这个函数将是我们的发送函数,接下来我们需要了解这个函数是怎么实现的。

这里写图片描述
如果tx_enabled没有被打开,则使能中断,打开tx_enabled,但是这里面并没有数据的发送??,原因是在前面串口的打开即open 一章中介绍过,有发送中断和接收中断,当中断打开之后,如果有fifo数据,则在中断处理函数中,进行数据的接收和发送。

start_tx起到激活中断,使能中断的作用,在中断处理程序中完成数据的发送

找到中断处理程序:
这里写图片描述
发送中断处理程序s3c24xx_serial_tx_chars
这里写图片描述
发现发送数据寄存器S3C2410_UTXH,说明中断处理程序完成数据的发送。

也就是说,write函数经过一系列调用,找到了start_tx函数,start_tx激活中断,然后驱动程序里面的中断处理程序,完成数据的发送。

问题来了,数据从哪里来的?

在串口中有一个重要的部分—循环缓冲,tty会把数据放到循环缓冲里面,当触发发送中断时,中断处理程序会从循环缓冲里面把数据取走。

这里写图片描述
如果循环缓冲不为空,则从中取出数据,并发送。

那么,数据是如何送进循环缓冲的?
在uart_write函数,可以看到buf是在这个函数里面写进去的,
这里写图片描述
上图中的buf是从应用程序中传递过来的,

然后uart_write会通过memcpy把buf写到循环缓冲里面去,如下
这里写图片描述

循环缓冲的结构如下:
这里写图片描述

言归正传,开始分析串口中断处理处理程序之发送函数s3c24xx_serial_tx_chars函数:

这里写图片描述
发送xon标志,代表可以开始接受数据。即:

这里写图片描述
循环缓冲为空,或者串口停止发送,则调用s3c24xx_serial_stop_tx来关闭中断

这里写图片描述
发送缓冲不为空,发送数据,
这里写图片描述
最多一次性发送256个字符
循环发送数据 条件:循环缓冲有数据 最多发送256个数据
在这个循环函数中,主要是做了三项工作
这里写图片描述
1.当发送fifo满的时候,退出发送
2.从循环缓冲中取出数据,写入UTXH寄存器
3.调整循环缓冲位置

这里写图片描述
数据量< 256时,唤醒在发送之前阻塞的进程

这里写图片描述
如果循环缓冲为空,则关闭中断

这里写图片描述
综合以上流程,可以得知,uart_write会把用户空间的数据写到循环buf里面去, 驱动里面的start_tx会激活发送中断,从而调用发送中断处理函数,发送中断处理函数会从循环buf取出数据,通过一系列检验过程,最终把数据传送到串口,这便是串口的数据发送过程。

五、 串口驱动分析–数据接收

1)数据接收过程

数据的接收和上面数据的发送过程基本一致,下面开始分析:
29
这里写图片描述

tty_read响应read系统调用,
这里写图片描述
调用线路规程里面的read,即n_tty_read
这里写图片描述
在n_tty_read函数中,做了下面几项工作:
这里写图片描述
将当前的状态设置为TASK_INTERRUPTIBLE状态,可中断阻塞态
这里写图片描述
如果没有数据可读,通过调度让阻塞失效。

这里写图片描述
如果有数据,从read_buf中读走数据

上面便是接收数据函数之间的调用关系,流程图如下:

这里写图片描述
问题来了,read_buf中的数据从哪里来的?下面分析中断处理接收函数,便可以得到答案,

2)串口接收数据分析

在串口接收终端处理函数s3c24xx_serial_rx_chars中,做了一下几个工作
36这里写图片描述

这里写图片描述
读取UFCON寄存器
读取UFSTAT寄存器

这里写图片描述
如果接收fifo里面的数据量为0,退出

这里写图片描述
读取UERSTAT寄存器,
从URXH取出接收到字符

这里写图片描述
进行流控处理

这里写图片描述
根据UERSTAT的值,记录具体的错误类型

这里写图片描述
如果接收到的是sysrq字符,进行特殊处理uart_handle_sysrq_char

这里写图片描述
把接收到的字符放到串口驱动的bufuart_insert_char

这里写图片描述
把串口驱动接收到的数据送进线路规程的read_buf -tty_flip_buffer_push

综合以上可以得知,在中断处理接收函数中,进行数据的接收,并将接收到的数据放到read_buf中去,而线路规程中的n_tty_read函数,则从read_buf中读走数据。over

下面是具体流程图

这里写图片描述

菜鸟一枚,如有错误,多多指教。。。

0 0