《精通Linux设备驱动程序开发》——串行设备驱动程序

一、相关简介

 1、UART(串行异步收发器)常用来实现串行通信。在PC兼容机硬件上,UART是super I/O芯片组的一部分。(图6-1  PC串行端口连接图)


 2、尽管RS-232通信信道是常见的串行硬件,内核的子系统还是用通用化的方式组织在一起,以便服务不同的用户。



二、层次架构

 1、内核开发者用如下的构建模块去构造分层次的串行架构:

   1)、关注UART或其他底层串行硬件特征的底层驱动程序。

   2)、和底层驱动程序接口的tty驱动程序层。tty驱动程序将上层驱动程序和形形色色的硬件进行了隔离。

   3)、加工用于和tty驱动程序交换数据的线路规程。线路规程勾勒串行层的行为,有助于复用底层的代码来支持不同的技术。


 2、串行子系统层间链接关系图(P119  图6-2)


 3、串行子系统与内核源文件的映射关系(P120  图6-3)



三、UART驱动程序

 1、UART驱动程序围绕三个关键的数据结构展开,这三个关键的数据结构哦都定义在include/linux/serial_core.h中。

   1)、特定UART相关的驱动程序结构,struct_uart_driver:

       struct_uart_driver {

           struct module  *ower;

           const  char  *driver_name;

           const  char  *dev_name;

            /*  .  .  .  */

            int  major;

            int  minor;

            /*  .  .  .  */

            struct  tty_driver  *tty_driver;

       };

   2)、struct  uart_port。UART驱动程序拥有的每个端口都存在uart_port结构的一个实例。

       struct  uart_port {

          spinlock_t  lock;

          unsigned  int  iobase;

          unsigned  char  __iomem  *membase;

          unisgend  int  irq;

          unisgned  int  uartclk;

          unsigned  char  fifosize;

          unsigned  char  x_char;

          /*  .  .  .  */

       };

   3)、struct  uart_ops。这个结构是每个UART驱动程序必须支持的物理硬件上可完成的操作的入口函数的超集。

       struct  uart_ops {

           uint  (*tx_empty)(struct  uart_port  *);

           void  (*set_mctrl)(struct  uart_port  *,  unsigned  int  mctrl);

           uint  (*get_mctrl)(struct  uart_port  *);

           void  (*stop_tx)(struct  uart_port  *);

           void  (*start_tx)(struct  uart_port  *);

           /*  .  .  .  */

           void  (*shutdown)(struct  uart_port  *);

           void  (*set_termios)(struct  uart_port  *,  struct  termios  *new,  struct  termios  *old);

           /*  .  .  .  */

           void  (*config_port)(struct  uart_driver  *,  int);


 2、UART驱动程序为了将自身和内核联系起来,必须完成两个重要的步骤。

   1)、通过调用uart_register_driver(struct  uart_driver  *);向串行核心注册。

   2)、调用uart_add_one_port(struct  uart_driver  *,  struct  uart_port  *)注册其支持的每个接口。


 3、设备实例:手机

   1)、Linux手机上的USB_UART端口(P123  图6-5)。

   2)、USB_UART上的寄存器(P123  表6-1)。

   3)、平台由平台设备和平台驱动程序组成。

   4)、代码清单6-1:Linux手机的USB_UART驱动程序。


 4、RS-485



四、TTY驱动程序

 1、tty驱动程序的核心结构和注册函数。有三个结构非常重要。

   1)、定义于include/linux/tty.h中的struct  tty_struct。此结构包含了和打开的tty相关的所欲哦状态信息。其结构成员众多下面列出一些重要的成员:

      struct  tty_driver {

          int  magic;

          struct  tty_driver  *driver;

          struct  tty_ldisc  ldisc;

          /*  .  .  .   */

          struct  tty_filp_buffer  flip;

          /*  .  .  .   */

          wait_queue_head_t  write_wait;

          wait_queue_head_t  read_wait;

          /*  .  .  .   */

       };

   2)、tty_struct中内嵌的struct  tty_flip_buffer或flip缓冲区。这是数据收集和处理机制的中枢:

      struct  tty_flip_buffer {

         /*  .  .  .  */

         struct  semaphore  pty_sem;

         char  *char_buf_ptr;

         /*  .  .  .  */

         unsigned  char  char_buf[2*TTY_FLIPBUF_SIZE];

         /*  .  .  .  */

      };

      在最近的内核中,struct  tty_flip_buffer结构体有些改动,目前由缓冲区头部(tty_buhead)和缓冲区链表(tty_buffer)组成:

      struct_tty_bufhead {

         /*  .  .  .  */

         struct  semaphore  pty_sem;

         struct  tty_buffer  *head,  tail,  free;

          /*  .  .  .  */

       };

       struct  tty_buffer {

          struct  tty_buffer  *next;

          struct  *char_buf_ptr;

          /*  .  .  .  */

          unsigned  long  data[0];

       };

   3)、定义在include/linux/tty_driver.h文件中的struct  tty_driver。它规定了tty驱动程序和高层之间的编程接口:

      struct  tty_driver [

          int  magic;

          /*  .  .  .  */

          int  major;

          int  minor_start;

          /*  .  .  .  */

          int  (*open)(struct  tty_struct  *tty,  struct  file  *flip);

          void  (*close)(struct  tty_struct  *tty,  struct  file  *flip);

          int  (*write)(struct  tty_struct  *tty,  const  unsigned  char  *buf,  int  count);

          void  (*ut_char)(struct  tty_struct  *tty, unsigned  char  ch);

          /*  .  .  .  .  */


 2、tty驱动程序需要两个步骤才能向内核注册自身:

   1)、通过调用tty_register_driver(struct  tty_driver  *tty_d)向tty核心注册自身。

   2)、调用下面的代码注册它支持的每个单独的tty:

       tty_register_device(struct  tty_driver  *tty_d,  unsigned  device_index,  struct  device  *device);



五、线路规程

 1、线路规程提供了一套灵活的机制,使得用户运行不同的应用程序时,能顾使用相同的串行驱动程序。底层和物理驱动和tty驱动负责从硬件上收发数据,而线路规程则负责处

       理这些数据,并在内核空间和用户kona进之间传递数据。


 2、串行子程序支持17种标准的线路规程。线路规程也实现通过串行传输协议实现的网络接口。


 3、设备实例:触摸控制器

   1)、打开与关闭

      I、为了创建线路规程,需要定义struct  tty_idisc,并向内核注册指定的入口函数集。

      II、代码清单6-2:线路规程操作。

      III、代码清单6-3:打开线路规程。

   2)、读数据过程

      I、对于中断驱动的设备,读取数据的过程通常由一前一后两个线程组成

           由于发起读数据请求而从用户空间发起的底层线程。

           由中断处理程序(接受来自设备的数据)唤醒的底层线程。

      II、线路规程读数据过程(P137  图6-5)。

      III、代码清单6-4:n_touch_receive_buf()方法。

      IV、代码清单6-5:唤醒读线程和中止串行驱动程序。

   3)、写数据过程

   4)、I/O控制

      I、当应用程序打开串行设备时,它通常可向其发出一下三类ioctl。

           串行设备驱动程序支持的命令。

           tty驱动程序支持的命令。

           关联的线程规程支持的命令。

   5)、其他操作

   6)、修改线程规程。

      I、打码清单6-6:从用户空间修改线程规程。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值