嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析

二、串口分析–初始化

/******************************************************************************/
首先贴出来下面要用到的4个操作函数集,
1.

struct tty_ldisc *ld;
struct tty_ldisc_ops *ops;
ld->ops->xx
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第1张图片

2.
struct tty_struct *tty;
const struct tty_operations *ops;
tty->ops->xx
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第2张图片

3.
struct uart_ops s3c24xx_serial_ops
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第3张图片

4.
file_operation
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第4张图片

/******************************************************************************/

参考了这篇文章:
http://blog.csdn.net/mbh_1991/article/details/9317653

串口的分析主要是分析两个文件:samsung.c s3c6400.c

1)串口驱动中的重要数据结构

嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第5张图片

从上面左图可以看出,用户对uart设备操作的调用关系非常简单,
file_operations => [tty_ldisc_ops] => tty_operations => uart ops,这几个调用关系会在后面函数流程分析中详细体现出来,其中tty_ldisc_ops线路规程并不是必要的,依赖于应用层设置是否使用ldisc处理数据

而上面右图,则表示uart驱动常用的数据结构,如下:

UART驱动程序结构: struct uart_driver
UART端口结构: struct uart_port
UART相关操作函数结构: struct uart_ops
UART状态结构: struct uart_ops
UART信息结构: struct uart_info

一个uart_driver就相当于一个串口驱动(1个驱动可以有多个串口)
一个uart_port就相当于一个串口
uart_ops 操作函数集

2)初始化分析

在Samsung.c中,找到其入口函数

module_init(s3c24xx_serial_modinit);
module_exit(s3c24xx_serial_modexit);

为s3c24xx_serial_modinit
完成了一个主要的功能,注册串口驱动
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第6张图片

在s3c6400.c中,其入口函数

module_init(s3c6400_serial_init);
module_exit(s3c6400_serial_exit);

为s3c6400_serial_init,
这里写图片描述
在其入口函数中,调用s3c24xx_serial_init这个函数,
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第7张图片
又调用了注册平台驱动,我们知道,在总线设备驱动模型中,当驱动和设备匹配上时,会调用probe函数进行初始化,因此分析其probe函数
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第8张图片
跳转到s3c6400_serial_probe函数中去,可以看到又调用了s3c24xx_serial_probe这个函数,
这里写图片描述
跳转到s3c24xx_serial_probe这个函数中去,可以看到在这个匹配函数中,做了一系列的初始化,主要分为了4步。
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第9张图片
1,s3c24xx_serial_ports这个函数是对串口的一些信息进行初始化,例如:中断,fifo的大小,操作函数集,如下图所示:
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第10张图片
在s3c24xx_serial_ports中,需要着重注意的是s3c24xx_serial_ops这个操作函数集,在以后会有用处。
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第11张图片
言归正传,在s3c24xx_serial_ports中有一个参数probe_index,,如果是probe_index是0,则取出s3c24xx_serial_ports中串口0的信息

2 调用s3c24xx_serial_init_port函数进行初始化,
2.1 在s3c24xx_serial_init_port函数中,首先做的是获取虚拟基地址,如下
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第12张图片
由此可以知道,采用的是静态映射的方式获取到虚拟地址,即事先指定相应的规则。

2.2接下来是获取中断号,对其进行初始化
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第13张图片

2.3最后对fifo进行复位
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第14张图片
继续回到s3c24xx_serial_probe函数进行分析。
3 建立 &s3c24xx_uart_drv, &ourport->port两者之间的关系,即建立串口与其驱动描述结构之间的关系,s3c24xx_uart_drv如下:
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第15张图片

4 创建属性文件device_create_file,即将属性文件创建到/sys目录,通过属性文件我们可以看到串口的状态信息
5.s3c24xx_serial_cpufreq_register初始化动态频率调节
其流程图如下所示:
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第16张图片

三、串口驱动分析–打开设备

用户程序打开串口,会使用open系统调用,open系统调用会通过一系列的传递,然后传递到串口驱动,然后在串口驱动中会有一个相应open函数的函数,例如xx_open,然后通过这个函数打开串口,如下:

嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第17张图片
上面环节有两个重要点:
1open系统调用的时候,Linux内核是如何把这个调用关系传递到串口驱动???
2驱动程序如何实现打开操作,即xx_open???

1.open系统调用的时候,Linux内核是如何把这个调用关系传递到串口驱动???

我们知道。open函数是打开一个字符设备文件,字符设备文件里面对应操作函数集,即file_operation.
在Samsung.c中
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第18张图片
在uart_register_driver函数中,有一个函数tty_register_driver
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第19张图片

在tty_register_driver函数中,有字符文件设备相关的操作
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第20张图片
tty_fops便是串口设备文件的操作函数集,在这个操作函数集在里面,首先看到的是tty_open函数,
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第21张图片
因此可以知道tty_open是对open系统调用的响应,在tty_open函数中,又调用了函数指针

嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第22张图片
我们可以看到这个ops的类型为tty_operations,因此找到这个ops,
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第23张图片
上图可以看到是调用了uart_open函数,在uart_open函数中,
这里写图片描述
打开uart_startup函数
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第24张图片
因此我们需要知道uport 的ops函数集,
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第25张图片

在s3c24xx_serial_ports里面,有一个操作函数集
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第26张图片

嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第27张图片
这一个操作函数集便是我们的串口操作函数集,s3c24xx_serial_startup这个便是我们最终打开串口的函数。
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第28张图片
根据上图,可以得知,在s3c24xx_serial_startup函数中,主要做的工作有:
1.使能串口接收功能
2.为数据接收注册中断
3.使能串口发送
4.为数据发送注册中断
也就是说,主要做的功能就是使能串口的接收和发送功能,并且对串口的接收和发送中断进行注册,当串口需要发送或者接收数据的时候,立马产生中断,到相应的中断处理函数中进行数据处理,这也是下一章节要说明的,后话,暂且不提。

通过以上流程可以知道,我们的open系统调用,传输到tty子系统中,串口驱动通过XX_OPEN函数对其响应,这个XX_OPEN便是我们的uart_open函数。
上面的分析如下所示:
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第29张图片
下图,为响应open系统调用,经过一一系列的调用,最终的响应。
嵌入式学习-驱动开发-lesson6.2-UART驱动初始化和open流程分析_第30张图片

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

你可能感兴趣的:(OK6410)