您的位置:首页 > 运维架构

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

2016-08-04 21:57 585 查看

二、串口分析–初始化

/[b]******************************************************************************[/b]/

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

1.

struct tty_ldisc *ld;

struct tty_ldisc_ops *ops;

ld->ops->xx



2.

struct tty_struct *tty;

const struct tty_operations *ops;

tty->ops->xx



3.

struct uart_ops s3c24xx_serial_ops



4.

file_operation



/[b]******************************************************************************[/b]/

参考了这篇文章:

http://blog.csdn.net/mbh_1991/article/details/9317653

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

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



从上面左图可以看出,用户对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

完成了一个主要的功能,注册串口驱动



在s3c6400.c中,其入口函数

module_init(s3c6400_serial_init);

module_exit(s3c6400_serial_exit);

为s3c6400_serial_init,



在其入口函数中,调用s3c24xx_serial_init这个函数,



又调用了注册平台驱动,我们知道,在总线设备驱动模型中,当驱动和设备匹配上时,会调用probe函数进行初始化,因此分析其probe函数



跳转到s3c6400_serial_probe函数中去,可以看到又调用了s3c24xx_serial_probe这个函数,



跳转到s3c24xx_serial_probe这个函数中去,可以看到在这个匹配函数中,做了一系列的初始化,主要分为了4步。



1,s3c24xx_serial_ports这个函数是对串口的一些信息进行初始化,例如:中断,fifo的大小,操作函数集,如下图所示:



在s3c24xx_serial_ports中,需要着重注意的是s3c24xx_serial_ops这个操作函数集,在以后会有用处。



言归正传,在s3c24xx_serial_ports中有一个参数probe_index,,如果是probe_index是0,则取出s3c24xx_serial_ports中串口0的信息

2 调用s3c24xx_serial_init_port函数进行初始化,

2.1 在s3c24xx_serial_init_port函数中,首先做的是获取虚拟基地址,如下



由此可以知道,采用的是静态映射的方式获取到虚拟地址,即事先指定相应的规则。

2.2接下来是获取中断号,对其进行初始化



2.3最后对fifo进行复位



继续回到s3c24xx_serial_probe函数进行分析。

3 建立 &s3c24xx_uart_drv, &ourport->port两者之间的关系,即建立串口与其驱动描述结构之间的关系,s3c24xx_uart_drv如下:



4 创建属性文件device_create_file,即将属性文件创建到/sys目录,通过属性文件我们可以看到串口的状态信息

5.s3c24xx_serial_cpufreq_register初始化动态频率调节

其流程图如下所示:



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

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



上面环节有两个重要点:

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

2驱动程序如何实现打开操作,即xx_open???

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

我们知道。open函数是打开一个字符设备文件,字符设备文件里面对应操作函数集,即file_operation.

在Samsung.c中



在uart_register_driver函数中,有一个函数tty_register_driver



在tty_register_driver函数中,有字符文件设备相关的操作



tty_fops便是串口设备文件的操作函数集,在这个操作函数集在里面,首先看到的是tty_open函数,



因此可以知道tty_open是对open系统调用的响应,在tty_open函数中,又调用了函数指针



我们可以看到这个ops的类型为tty_operations,因此找到这个ops,



上图可以看到是调用了uart_open函数,在uart_open函数中,



打开uart_startup函数



因此我们需要知道uport 的ops函数集,



在s3c24xx_serial_ports里面,有一个操作函数集





这一个操作函数集便是我们的串口操作函数集,s3c24xx_serial_startup这个便是我们最终打开串口的函数。



根据上图,可以得知,在s3c24xx_serial_startup函数中,主要做的工作有:

1.使能串口接收功能

2.为数据接收注册中断

3.使能串口发送

4.为数据发送注册中断

也就是说,主要做的功能就是使能串口的接收和发送功能,并且对串口的接收和发送中断进行注册,当串口需要发送或者接收数据的时候,立马产生中断,到相应的中断处理函数中进行数据处理,这也是下一章节要说明的,后话,暂且不提。

通过以上流程可以知道,我们的open系统调用,传输到tty子系统中,串口驱动通过XX_OPEN函数对其响应,这个XX_OPEN便是我们的uart_open函数。

上面的分析如下所示:



下图,为响应open系统调用,经过一一系列的调用,最终的响应。



菜鸟一枚,如有错误,多多指教。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: