首页 Linux uart驱动及应用

Linux uart驱动及应用

举报
开通vip

Linux uart驱动及应用#define TTY_MAJOR        4 #define TTYAUX_MAJOR        5 Tty : 终端设备的统称。一般分为:控制台、串口和pty. /dev/ttySn: 串行端口终端(串口),串行端口被看做字符设备。 4:66 (设备号)-> ../../devices/platform/serial8250/tty/ttyS2 4:67 -> ../../devices/platform/serial8250/tty/ttyS3 4:68 -> ../../devices/plat...

Linux uart驱动及应用
#define TTY_MAJOR        4 #define TTYAUX_MAJOR        5 Tty : 终端设备的统称。一般分为:控制台、串口和pty. /dev/ttySn: 串行端口终端(串口),串行端口被看做字符设备。 4:66 (设备号)-> ../../devices/platform/serial8250/tty/ttyS2 4:67 -> ../../devices/platform/serial8250/tty/ttyS3 4:68 -> ../../devices/platform/serial8250/tty/ttyS4 echo test > /dev/ttyS2可接串口来测试ttyS2。 Pty: pseudo tty虚拟(伪)终端 pts(pseudo-terminal slave) 与ptmx(pseudo-terminal  master)  配合使用实现pty。 打开一个伪terminal,那么将会在devpts文件系统/dev/pts下创建一个对应的pts字符文件。 通过tty命令(或者who am i)查看当前终端,可以看出此伪terminal对应着pts3。 再打开一个伪terminal: 此伪terminal对应着pts4. 两个终端间传输信息: /dev/tty: 就是当前使用的终端。设备号:5:0 tty可以是pts3,也可以是tty1。 控制台终端: tty0:代表当前使用的控制台终端。设备号4:0. Ubuntu下:图像界面下通过Ctrl + Alt + F1—F6 可以切换到tty1到tty6。Ctrl + Alt + F7切会图像界面。 Pts3 发送到tty1。 /dev/console是指向当前console。设备号5:1 ---------------------------------------------------------------------------------------------------------- Tty核心: structtty_driver *alloc_tty_driver(int lines) { structtty_driver *driver; driver = kzalloc(sizeof(structtty_driver), GFP_KERNEL); if (driver) { kref_init(&driver->kref); driver->magic = TTY_DRIVER_MAGIC; driver->num = lines;(次设备个数) /* later we'll move allocation of tables here */ } return driver; } //分配一个结构体tty_driver,初始化其magic、num。 inttty_register_driver(structtty_driver *driver) { if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL); } if (!driver->major) { error = alloc_chrdev_region(&dev, driver->minor_start, driver->num, driver->name); } else { dev = MKDEV(driver->major, driver->minor_start); error = register_chrdev_region(dev, driver->num, driver->name); } //如果没有指定主设备号,则分配并注册,否则直接注册设备号。 if (p) { driver->ttys = (structtty_struct **)p; driver->termios = (structktermios **)(p + driver->num); } else { driver->ttys = NULL; driver->termios = NULL; } cdev_init(&driver->cdev, &tty_fops); //初始化设备操作函数集。 driver->cdev.owner = driver->owner; error = cdev_add(&driver->cdev, dev, driver->num); //注册字符设备。 mutex_lock(&tty_mutex); list_add(&driver->tty_drivers, &tty_drivers); //此driver->tty_drivers加到链表tty_drivers上 mutex_unlock(&tty_mutex); if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) { for (i = 0; i< driver->num; i++) { d = tty_register_device(driver, i, NULL); //如果没有指定TTY_DRIVER_DYNAMIC_DEV,则注册tty设备(在sysfs上建立相应的文件) } } proc_tty_register_driver(driver); driver->flags |= TTY_DRIVER_INSTALLED; //标记为已安装 return 0; } structtty_struct { structtty_driver *driver; structtty_ldisc *ldisc; } 下面 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 一下tty_fops: staticconststructfile_operationstty_fops = { .llseek        = no_llseek, .read        = tty_read, .write        = tty_write, .poll        = tty_poll, .unlocked_ioctl    = tty_ioctl, .compat_ioctl    = tty_compat_ioctl, .open        = tty_open, .release    = tty_release, .fasync        = tty_fasync, }; tty_write -->do_tty_write -->tty->ldisc->ops->write tty_read -->tty->ldisc ->ops->read tty ->ldisc在哪里赋值?在tty_open里。 tty_open -->tty_init_dev -->initialize_tty_struct -->tty_ldisc_init 在initialize_tty_struct里还有:tty->ops = driver->ops; ---------------------------------------------------------------------------------------------------------- Tty线路规程: voidtty_ldisc_init(structtty_struct *tty) { structtty_ldisc *ld = tty_ldisc_get(N_TTY); //ldops = tty_ldiscs[disc];ld->ops = ldops; tty_ldisc_assign(tty, ld); //tty->ldisc = ld; } 全局变量tty_ldiscs在哪里赋值? start_kernel -->console_init -->tty_ldisc_begin -->tty_register_ldisc --> tty_ldiscs[disc] =tty_ldisc_N_TTY structtty_ldisc_opstty_ldisc_N_TTY = { .magic          = TTY_LDISC_MAGIC, .name            = "n_tty", .open            = n_tty_open, .close          = n_tty_close, .flush_buffer    = n_tty_flush_buffer, .chars_in_buffer = n_tty_chars_in_buffer, .read            = n_tty_read, .write          = n_tty_write, .ioctl          = n_tty_ioctl, .set_termios    = n_tty_set_termios, .poll            = n_tty_poll, .receive_buf    = n_tty_receive_buf, .write_wakeup    = n_tty_write_wakeup }; n_tty_write -->tty->ops->write即(driver->ops->write) n_tty_read没有直接掉用下一层的read,使用了tty->read_buf进行交互。 ---------------------------------------------------------------------------------------------------------- Tty驱动程序: structuart_driver { structuart_state    *state; structtty_driver    *tty_driver; }; uart_register_driver -->tty_register_driver intuart_register_driver(structuart_driver *drv) { drv->state = kzalloc(sizeof(structuart_state) * drv->nr, GFP_KERNEL); //分配uart_state,一个端口对应一个 normal = alloc_tty_driver(drv->nr); //分配tty_driver drv->tty_driver = normal; normal->owner        = drv->owner; normal->driver_name    = drv->driver_name; normal->name        = 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; //安全设置值,参考ddr3 P542 termios结构。 normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600; normal->flags        = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; normal->driver_state    = drv; tty_set_operations(normal, &uart_ops); //里面执行了uart_driver ->tty_driver->ops =uart_ops * initialise the UART state(s). //初始化所有端口uart_state for (i = 0; inr; i++) { structuart_state *state = drv->state + i; structtty_port *port = &state->port; tty_port_init(port); port->ops = &uart_port_ops; port->close_delay    = 500;    /* .5 seconds */ port->closing_wait    = 30000;    /* 30 seconds */ tasklet_init(&state->tlet, uart_tasklet_action, (unsigned long)state); } retval = tty_register_driver(normal); } uart_add_one_port注册一个port,核心作用可以看做赋值了uart_port,其中包含了最低层的操作函数集。 structuart_port { conststructuart_ops    *ops; }; uart_write -->uart_start -->__uart_start -->port->ops->start_tx ---------------------------------------------------------------------------------------------------------- TI Omap分析: dra6xx_init–>omap_serial_init -->omap_serial_init_port omap_serial_init_port初始化了uart,并赋值到oh->dev_attr。注册了“omap_uart”设备。 在serial_omap_init注册了其驱动: staticint __initserial_omap_init(void) { int ret; ret =uart_register_driver(&serial_omap_reg); ret =platform_driver_register(&serial_omap_driver); } 匹配成功调用serial_omap_probe,serial_omap_probe调用uart_add_one_port注册了端口。端口的操作函数集:serial_omap_pops。 读: serial_omap_irq  -->receive_chars -->tty_flip_buffer_push -->flush_to_ldisc -->disc->ops->receive_buf ---------------------------------------------------------------------------------------------------------- 补充知识: 线路规程是可以设置的,默认的就是tty_ldisc_N_TTY,下面看一个新的: 先注册一个线路规程:(就是加到全局变量tty_ldiscs里) staticint __initserport_init(void) { intretval; retval = tty_register_ldisc(N_MOUSE, &serport_ldisc); } //就是tty_ldiscs[N_MOUSE] = serport_ldisc; 应用层通过: ldisc = N_MOUSE; if (ioctl(fd, TIOCSETD, &ldisc)) 对应内核会调用tty_ioctl  -->tiocsetd -->tty_set_ldisc 这样有什么用呢? 例如串口触摸屏: UART -->serport_ldisc(修改线路规程) --> SERIO --> INPUT DEVICE --> EVENT 具体参考代码:serport.c (注册新的线路规程)、touchit213.c(注册serio驱动) 需要注意的: Serio设备是在serport_ldisc_read里面注册的,也就是在使用之前,必须先调用read一下,才会注册设备,然后serio才会匹配成功,匹配成功之后会调用其connect函数。在connect里面注册input device,没有指定输入设备event,使用通用的eventX. 读操作: serial_omap_irq  -->receive_chars -->tty_flip_buffer_push -->flush_to_ldisc -->disc->ops->receive_buf(即serport_ldisc_receive)-->直接调用serio_interrupt -->serio->drv->interrupt(即touchit213_interrupt) -->input_sync (touchit213_interrupt只是假设的) 写操作: 直接调用serport_serio_writ -->serport->tty->ops->write
本文档为【Linux uart驱动及应用】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_496339
暂无简介~
格式:doc
大小:51KB
软件:Word
页数:0
分类:互联网
上传时间:2019-03-19
浏览量:3