serival(串口驱动)分析

上传人:第*** 文档编号:31314137 上传时间:2018-02-06 格式:DOCX 页数:23 大小:88.30KB
返回 下载 相关 举报
serival(串口驱动)分析_第1页
第1页 / 共23页
serival(串口驱动)分析_第2页
第2页 / 共23页
serival(串口驱动)分析_第3页
第3页 / 共23页
serival(串口驱动)分析_第4页
第4页 / 共23页
serival(串口驱动)分析_第5页
第5页 / 共23页
点击查看更多>>
资源描述

《serival(串口驱动)分析》由会员分享,可在线阅读,更多相关《serival(串口驱动)分析(23页珍藏版)》请在金锄头文库上搜索。

1、分析 ttySn 驱动之前先明确几个概念(1)/dev/ttySn:串口端口终端,是使用串口计算机终端连接的终端设备,对应我们具体的串口设备(2)/dev/tty:如果当前进程有控制终端的话,那么/dev/tty 就是当前进程的控制终端的特殊设备文件可用 ps -ef 来查看,对于你登录的 shell /dev/tty 就是你使用的终端(3)/dev/ttyn /dev/console:控制台终端开始分析之前来看 2 张图:图 1line discipline 表示这条终端“线程”的输入与输出规范设置,主要用来进行输入/输出数据的预定义处理,处理完后,将数据交给 serial _core,最后

2、 serial _core 会调用具体的rk_serial.c 的操作。用户想要访问 linux 的串口设备,在用户空间通过 read/write/ioctl 等,首先通过设备文件(字符设备)和 tty_core 交互, tty_core 根据交互类型选择 tty_driver 或者 line discipline 执行,如果是 ioctl 这交给 tty_driver(这里是 servila_core)去处理,如果是 read/write 这交给line discipline 去处理。图 2再看第二张图,一个 uart_driver 通常会注册一段设备号.即在用户空间会看到 uart_dri

3、ver 对应有多个设备节点。例如:/dev/ttyS0 /dev/ttyS1 每个设备节点是对应一个具体硬件的,这样就可做到对多个硬件设备的统一管理,而每个设备文件应该对应一个 uart_port,也就 是说:uart_device 要和多个uart_port 关系起来。并且每个 uart_port 对应一个 circ_buf(用来接收数据), 所以 uart_port 必须要和这个缓存区关系起来。有了上面的理解,我们开始进入代码去研究具体的实现过程以 RK3288 平台作为媒介去研究tty_core 源码在:kernel/drivers/tty/tty_io.c这个文件主要将 tty 注册成

4、一个 char dev,对应上面的 tty_core 的部分。先放一下,先看看serial _core 的代码。kernel/drivers/tty/serial/serial_core.c 这个文件对应的 serial_core 的操作,里面主要的函数有:EXPORT_SYMBOL(uart_write_wakeup);EXPORT_SYMBOL(uart_register_driver);EXPORT_SYMBOL(uart_unregister_driver);EXPORT_SYMBOL(uart_suspend_port);EXPORT_SYMBOL(uart_resume_port)

5、;EXPORT_SYMBOL(uart_add_one_port);EXPORT_SYMBOL(uart_remove_one_port);这里和 linux 大多数 core 的做法一样,提供一个主要函数给具体的设备驱动注册到对应的core,那么需要从具体的 uart 驱动开始分析。具体驱动代码在:kernel/drivers/tty/serial/rk_serial.c开始分析这个文件module_init(serial_rk_init);linux 设备驱动入口函数static struct uart_driver serial_rk_reg = .owner = THIS_MODULE

6、,.driver_name = rk29_serial,.dev_name = ttyS,.major = TTY_MAJOR,.minor = 64,.cons = SERIAL_CONSOLE,.nr = UART_NR,;static int _init serial_rk_init(void)ret = uart_register_driver(ret = platform_driver_register(这个函数只有 2 个执行函数,从 uart_resister_driver 开始分析,这个函数在 serial_core.c 实现int uart_register_driver(s

7、truct uart_driver *drv) /每个端口对应一个 statedrv-state = kzalloc(sizeof(struct uart_state) * drv-nr, GFP_KERNEL);/分配该串口驱动对应的 tty_drivernormal = alloc_tty_driver(drv-nr);/让 drv-tty_driver 字段指向这个 tty_driverdrv-tty_driver = normal;/设置相关属性normal-owner = drv-owner;normal-driver_name = drv-driver_name;normal-na

8、me = drv-dev_name;normal-major = drv-major;normal-minor_start = drv-minor;normal-type = TTY_DRIVER_TYPE_SERIAL;normal-subtype = SERIAL_TYPE_NORMAL;normal-init_termios = tty_std_termios;normal-init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;normal-init_termios.c_ispeed = normal-init_termi

9、os.c_ospeed = 9600;normal-flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;normal-driver_state = drv;/通过将自己注册到 serial_core 层,后面 serial_core 层会根据对应关系调用到具体的 rk_serial 串口 ops,在 rk_serial 文件 中有自己定义的一个 ops,等待回去看 rk_serial.c 有没有这个操作tty_set_operations(normal, /设置该 tty 对应的 ops 操作集,在这里将/tty_driver 的操作集统一

10、设为了 uart_ops.这样就使得从用户空间下来的操作可以找到正确的 serial_core /的操作函数,uart_ops 是在 serial_core.c 中的如下 ops 操作集所示: /* Initialise the UART state(s).*/for (i = 0; i nr; i+) struct uart_state *state = drv-state + i;struct tty_port *port = tty_port_init(port);port-ops = port-close_delay = 500; /* .5 seconds */port-closin

11、g_wait = 30000; /* 30 seconds */tasklet_init(&state-tlet, uart_tasklet_action,(unsigned long)state);retval = tty_register_driver(normal);/这个函数又做上面的呢?从第一张图中可以看到具体的 tty_driver 是需要跟 tty_core 关联的,同时,tty_core 也需要作为一个字符设备让用户程序能通过 open/read/write 等访问,这个函数就是实现这个操作。进去这个函数看看ops 操作集static const struct tty_oper

12、ations uart_ops = .open = uart_open,.close = uart_close,.write = uart_write,.put_char = uart_put_char,.flush_chars = uart_flush_chars,.write_room = uart_write_room,.chars_in_buffer= uart_chars_in_buffer,.flush_buffer = uart_flush_buffer,.ioctl = uart_ioctl,.throttle = uart_throttle,.unthrottle = uar

13、t_unthrottle,.send_xchar = uart_send_xchar,.set_termios = uart_set_termios,.set_ldisc = uart_set_ldisc,.stop = uart_stop,.start = uart_start,.hangup = uart_hangup,.break_ctl = uart_break_ctl,.wait_until_sent= uart_wait_until_sent,#ifdef CONFIG_PROC_FS.proc_fops = &uart_proc_fops,#endif.tiocmget = ua

14、rt_tiocmget,.tiocmset = uart_tiocmset,.get_icount = uart_get_icount,#ifdef CONFIG_CONSOLE_POLL.poll_init = uart_poll_init,.poll_get_char = uart_poll_get_char,.poll_put_char = uart_poll_put_char,#endif;/这个函数跳到了 drivers/tty/tty_io.c,正好是 tty_core 的实现,和我们猜想的是一致的int tty_register_driver(struct tty_driver

15、*driver)/以下这段代码是注册字符设备的过程,更加验证了作为一个字符设备驱动的猜想if (!driver-major) error = alloc_chrdev_region(&dev, driver-minor_start,driver-num, driver-name);if (!error) driver-major = MAJOR(dev);driver-minor_start = MINOR(dev); else dev = MKDEV(driver-major, driver-minor_start);error = register_chrdev_region(dev, driver-num, driver-name);if (error flags & TTY_DRIVER_DYNAMIC_

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑/环境 > 工程造价

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号