先来分析一下串口打开的过程:

  • 1、用户调用open函数打开串口设备文件;
  • 2、在内核中通过tty子系统,把open操作层层传递到串口驱动程序中;
  • 3、在串口驱动程序中的xx_open最终实现这个操作。

这里主要有2个点需要我们重点分析,一个是open函数的传递过程,而是串口驱动程序XXX_open函数的实现。

1.open函数传递

  • 打开uart_register_driver函数,里面就是实现注册串口驱动,在最后有一个tty_register_driver函数,这个函数实际上就是注册一个字符设备。在注册过程中有一个重要的结构:
static const struct file_operations tty_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_fops结构,里面的tty_open就是响应用户的open操作的。这这个open函数里面肯定不是直接完成串口打开的,它调用了uart_ops里面的open函数:
static const struct tty_operations 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    = uart_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 = uart_tiocmget,.tiocmset  = uart_tiocmset,
#ifdef CONFIG_CONSOLE_POLL.poll_init    = uart_poll_init,.poll_get_char    = uart_poll_get_char,.poll_put_char    = uart_poll_put_char,
#endif
};
  • 可以看到最终调用的是uart_open函数,这个函数中使用uart_startup(state, 0);实现串口的打开,这个最终又是由s3c24xx_serial_ops里面的s3c24xx_serial_startup函数来实现的。下面分析这个函数。

2.串口打开流程分析


static int s3c24xx_serial_startup(struct uart_port *port)
{struct s3c24xx_uart_port *ourport = to_ourport(port);int ret;dbg("s3c24xx_serial_startup: port=%p (%08lx,%p)\n",port->mapbase, port->membase);rx_enabled(port) = 1;  // 使能接收ret = request_irq(ourport->rx_irq, s3c24xx_serial_rx_chars, 0,s3c24xx_serial_portname(port), ourport);   // 为数据接收注册中断程序if (ret != 0) {printk(KERN_ERR "cannot get irq %d\n", ourport->rx_irq);return ret;}ourport->rx_claimed = 1;  // 使能发送dbg("requesting tx irq...\n");tx_enabled(port) = 1;ret = request_irq(ourport->tx_irq, s3c24xx_serial_tx_chars, 0,s3c24xx_serial_portname(port), ourport);   // 为数据发送注册中断程序if (ret) {printk(KERN_ERR "cannot get irq %d\n", ourport->tx_irq);goto err;}ourport->tx_claimed = 1;dbg("s3c24xx_serial_startup ok\n");/* the port reset code should have done the correct* register setup for the port controls */if (port->line == 2) {s3c2410_gpio_cfgpin(S3C2410_GPH(6), S3C2410_GPH6_TXD2);s3c2410_gpio_pullup(S3C2410_GPH(6), 1);s3c2410_gpio_cfgpin(S3C2410_GPH(7), S3C2410_GPH7_RXD2);s3c2410_gpio_pullup(S3C2410_GPH(7), 1);}return ret;err:s3c24xx_serial_shutdown(port);return ret;
}

它完成下面的工作:

  • 1、使能接收rx_enabled
  • 2、为数据接收注册中断程序request_irq
  • 3、使能发送tx_enabled
  • 4、为数据发送注册中断程序request_irq

Linux串口驱动程序(3)-打开设备相关推荐

  1. Linux串口驱动程序(4)-数据发送

    1.tty数据发送调用关系 怎么样才能找到发送数据所使用的函数呢?打开uart_register_driver函数,找到里面的tty_register_driver,转到定义,这里调用了tty_fop ...

  2. Linux串口驱动程序(1)-tty驱动程序架构

    1.tty概念分析 在Linux系统中,终端是一类字符型设备,它包括多种类型,通常使用tty来简称各种类型的终端设备.由于串口也是一种终端,因此这里引入终端这个概念 串口终端(/dev/ttyS*) ...

  3. Linux串口驱动程序(6)-串口驱动实现

    在Linux驱动开发中,一般都不会从0开始写,我们做的更多的是移植和修改,有时候还需要对驱动程序进行优化.当然具备移植.修改驱动能力的基础是能够读懂驱动程序,同时需要对这个驱动程序的核心功能非常了解. ...

  4. Linux内核深入理解中断和异常(8):串口驱动程序

    Linux内核深入理解中断和异常(8):串口驱动程序 rtoax 2021年3月 /*** start_kernel()->setup_arch()->idt_setup_early_tr ...

  5. linux文件控制驱动程序,Linux设备驱动程序学习(6)-高级字符驱动程序操作[(3)设备文件的访问控制]...

    Linux设备驱动程序学习(6) -高级字符驱动程序操作[(3)设备文件的访问控制] 提供访问控制对于一个设备节点来的可靠性来说有时是至关重要的.这部分的内容只是在open和release方法上做些修 ...

  6. linux两个进程同时打开串口,linux串口操作及设置详解

    串口操作需要的头文件 #include /*标准输入输出定义*/ #include /*标准函数库定义*/ #include /*Unix标准函数定义*/ #include #include #inc ...

  7. Unix/Linux操作系统分析实验四 设备驱动: Linux系统下的字符设备驱动程序编程

    Unix/Linux操作系统分析实验一 进程控制与进程互斥 Unix/Linux操作系统分析实验二 内存分配与回收:Linux系统下利用链表实现动态内存分配 Unix/Linux操作系统分析实验三 文 ...

  8. linux usbnet网络驱动,[技术资料]基于usb设备的linux网络驱动程序开发

    1 引言 做为开放源代码 (open source) 运动重要组成部分,linux操作系统吸引了数以万计的程序员共同开发.由于linux比较完整的继承了各种unix版本的稳定和高效,并且克服和改进了传 ...

  9. Linux设备驱动程序 三 字符设备驱动

    Linux设备驱动程序 三 字符设备驱动 笔记 第三章 字符驱动设备 本章会编写一个完整的字符设备,字符设备简单,易于理解, 名字是scull:Simple Caracter Utility for ...

最新文章

  1. CSS grid 的用法
  2. 自从用完 Gradle 后,有点嫌弃 Maven 了!
  3. 人本质要好,要善良,要真诚,有格局和胸怀,有能力,有眼光,能讲故事,能找到人,能搞到钱...
  4. vs2015上使用github进行版本控制
  5. Centos 6.5下的OPENJDK卸载和SUN的JDK安装、环境变量配置
  6. 开放原子超级链动态内核上线,十分钟可搭建一条区块链
  7. linux语言换成英语,把Linux的默认语言改为英语
  8. html5监听动画结束,js判断css动画是否完成 animation,transition
  9. webpack代理解决跨域
  10. Sps的content menu 和 smart-tag的问题
  11. 【机器学习】机器学习从零到掌握之十三 -- 教你理解Logistics回归之梯度上升算法
  12. 程序员的进阶课-架构师之路(6)-链表
  13. cfe刷机教程 斐讯k3_2019斐讯K3全版本免拆机免降级刷机教程
  14. 2016年考研数学一解析 ​​​
  15. php实现ps修图,ps皮肤处理精修方法
  16. 基于springboot编写的小程序幸运转盘抽奖功能
  17. Mac重装系统-使用Mac笔记本制作U盘启动盘
  18. L1-023 输出GPLT (20分) 给定一个长度不超过10000的、仅由英文字母构成的字符串。请将字符重新调整顺序,按GPLTGPLT....这样的顺序输出,并忽略其它字符。当然,四种字符(不区分
  19. np.array的axis进行横向纵向的求和运算
  20. Hard-Margin SVM(支持向量机)

热门文章

  1. matlab天线仿真实验报告,天线实验报告(共10篇).doc
  2. 【深度学习】:非极大值抑制(NMS)详解
  3. 通信原理——CDMA
  4. Acrobat_8_Pro_SC 激活老是提示你输入的授权码无效
  5. java 笛卡尔积_笛卡儿积的java实现
  6. 速学堂Java300集第五章作业
  7. 活字格低代码开发平台怎么样?靠谱吗?
  8. python多因素电力预测——基于LSTM神经网络
  9. 助力数据运营 | 京东支付-猎户数据监控平台
  10. 一步步教你轻松学逻辑回归模型算法