linux uart驱动——相关数据结构以及API(二)

一、核心数据结构
      串口驱动有3个核心数据结构,它们都定义在<#include linux/serial_core.h>
1、uart_driver
     uart_driver包含了串口设备名、串口驱动名、主次设备号、串口控制台(可选)等信息,还封装了tty_driver(底层串口驱动无需关心tty_driver)。

   1:  struct uart_driver {
   2:      struct module    *owner;      /* 拥有该uart_driver的模块,一般为THIS_MODULE */
   3:      const char    *driver_name; /* 串口驱动名,串口设备文件名以驱动名为基础 */
   4:      const char    *dev_name;      /* 串口设备名 */
   5:      int             major;          /* 主设备号 */
   6:      int             minor;          /* 次设备号 */
   7:      int             nr;          /* 该uart_driver支持的串口个数(最大) */
   8:      struct console    *cons;    /* 其对应的console.若该uart_driver支持serial console,否则为NULL */
   9:   
  10:      /*
  11:       * these are private; the low level driver should not
  12:       * touch these; they should be initialised to NULL
  13:       */
  14:      struct uart_state    *state;
  15:      struct tty_driver    *tty_driver;
  16:  };

2、uart_port
      uart_port用于描述串口端口的I/O端口或I/O内存地址、FIFO大小、端口类型、串口时钟等信息。实际上,一个uart_port实例对应一个串口设备

   1:  struct uart_port {
   2:      spinlock_t        lock;            /* port lock 串口端口锁 */
   3:      unsigned long        iobase;        /* in/out[bwl] io端口基地 */
   4:      unsigned char __iomem    *membase;/* read/write[bwl] IO内存基地址,经映射(如ioremap)后的IO内存虚拟基地址 */
   5:      unsigned int        (*serial_in)(struct uart_port *, int); 
   6:      void            (*serial_out)(struct uart_port *, int, int);
   7:      void            (*set_termios)(struct uart_port *,
   8:                                 struct ktermios *new,
   9:                                 struct ktermios *old);
  10:      void            (*pm)(struct uart_port *, unsigned int state,
  11:                        unsigned int old);
  12:      unsigned int        irq;            /* irq number */
  13:      unsigned long        irqflags;        /* irq flags  */
  14:      unsigned int        uartclk;        /* base uart clock */
  15:      unsigned int        fifosize;        /* tx fifo size */
  16:      unsigned char        x_char;            /* xon/xoff char */
  17:      unsigned char        regshift;        /* reg offset shift */
  18:      unsigned char        iotype;            /* io access style */
  19:      unsigned char        unused1;
  20:   
  21:  #define UPIO_PORT        (0)
  22:  #define UPIO_HUB6        (1)
  23:  #define UPIO_MEM        (2)
  24:  #define UPIO_MEM32        (3)
  25:  #define UPIO_AU            (4)            /* Au1x00 type IO */
  26:  #define UPIO_TSI        (5)            /* Tsi108/109 type IO */
  27:  #define UPIO_DWAPB        (6)            /* DesignWare APB UART */
  28:  #define UPIO_RM9000        (7)            /* RM9000 type IO */
  29:  #define UPIO_DWAPB32        (8)            /* DesignWare APB UART (32 bit accesses) */
  30:   
  31:      unsigned int        read_status_mask;    /* driver specific */
  32:      unsigned int        ignore_status_mask;    /* driver specific */
  33:      struct uart_state    *state;            /* pointer to parent state */
  34:      struct uart_icount    icount;            /* statistics */
  35:   
  36:      struct console        *cons;            /* struct console, if any */
  37:  #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
  38:      unsigned long        sysrq;            /* sysrq timeout */
  39:  #endif
  40:   
  41:      upf_t            flags;
  42:   
  43:  #define UPF_FOURPORT        ((__force upf_t) (1 << 1))
  44:  #define UPF_SAK            ((__force upf_t) (1 << 2))
  45:  #define UPF_SPD_MASK        ((__force upf_t) (0x1030))
  46:  #define UPF_SPD_HI        ((__force upf_t) (0x0010))
  47:  #define UPF_SPD_VHI        ((__force upf_t) (0x0020))
  48:  #define UPF_SPD_CUST        ((__force upf_t) (0x0030))
  49:  #define UPF_SPD_SHI        ((__force upf_t) (0x1000))
  50:  #define UPF_SPD_WARP        ((__force upf_t) (0x1010))
  51:  #define UPF_SKIP_TEST        ((__force upf_t) (1 << 6))
  52:  #define UPF_AUTO_IRQ        ((__force upf_t) (1 << 7))
  53:  #define UPF_HARDPPS_CD        ((__force upf_t) (1 << 11))
  54:  #define UPF_LOW_LATENCY        ((__force upf_t) (1 << 13))
  55:  #define UPF_BUGGY_UART        ((__force upf_t) (1 << 14))
  56:  #define UPF_NO_TXEN_TEST    ((__force upf_t) (1 << 15))
  57:  #define UPF_MAGIC_MULTIPLIER    ((__force upf_t) (1 << 16))
  58:  #define UPF_CONS_FLOW        ((__force upf_t) (1 << 23))
  59:  #define UPF_SHARE_IRQ        ((__force upf_t) (1 << 24))
  60:  /* The exact UART type is known and should not be probed.  */
  61:  #define UPF_FIXED_TYPE        ((__force upf_t) (1 << 27))
  62:  #define UPF_BOOT_AUTOCONF    ((__force upf_t) (1 << 28))
  63:  #define UPF_FIXED_PORT        ((__force upf_t) (1 << 29))
  64:  #define UPF_DEAD        ((__force upf_t) (1 << 30))
  65:  #define UPF_IOREMAP        ((__force upf_t) (1 << 31))
  66:   
  67:  #define UPF_CHANGE_MASK        ((__force upf_t) (0x17fff))
  68:  #define UPF_USR_MASK        ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
  69:   
  70:      unsigned int        mctrl;            /* current modem ctrl settings */
  71:      unsigned int        timeout;        /* character-based timeout */
  72:      unsigned int        type;            /* port type */
  73:      const struct uart_ops    *ops;
  74:      unsigned int        custom_divisor;
  75:      unsigned int        line;            /* port index */
  76:      resource_size_t        mapbase;        /* for ioremap */
  77:      struct device        *dev;            /* parent device */
  78:      unsigned char        hub6;            /* this should be in the 8250 driver */
  79:      unsigned char        suspended;
  80:      unsigned char        irq_wake;
  81:      unsigned char        unused[2];
  82:      void            *private_data;        /* generic platform data pointer */
  83:  };.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

uart_iconut为串口信息计数器,包含了发送字符计数、接收字符计数等。在串口的发送中断处理函数和接收中断处理函数中,我们需要管理这些计数。

   1:  struct uart_icount {
   2:      __u32    cts;
   3:      __u32    dsr;
   4:      __u32    rng;
   5:      __u32    dcd;
   6:      __u32    rx;      /* 发送字符计数 */
   7:      __u32    tx;      /* 接受字符计数 */
   8:      __u32    frame;   /* 帧错误计数 */
   9:      __u32    overrun; /* Rx FIFO溢出计数 */
  10:      __u32    parity;  /* 帧校验错误计数 */
  11:      __u32    brk;     /* break计数 */
  12:      __u32    buf_overrun;
  13:  };

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

uart_stat有两个成员在底层串口驱动会用到:xmit和port。用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过xmit获取到用户数据并将它们发送出去。串口接收中断处理函数需要通过port将接收到的数据传递给行规则层。

   1:  /*
   2:   * This is the state information which is persistent across opens.
   3:   */
   4:  struct uart_state {
   5:      struct tty_port        port;
   6:   
   7:      int            pm_state;
   8:      struct circ_buf        xmit;
   9:   
  10:      struct tasklet_struct    tlet;
  11:      struct uart_port    *uart_port;
  12:  };
 

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

3、uart_ops

uart_ops涵盖了串口驱动可对串口设备进行的所有操作

   1:  /*
   2:   * This structure describes all the operations that can be
   3:   * done on the physical hardware.
   4:   */
   5:  struct uart_ops {
   6:      unsigned int    (*tx_empty)(struct uart_port *);/* 串口的Tx FIFO缓存是否为空 */
   7:      void        (*set_mctrl)(struct uart_port *, unsigned int mctrl);/* 设置串口modem控制 */
   8:      unsigned int    (*get_mctrl)(struct uart_port *); /* 获取串口modem控制 */
   9:      void        (*stop_tx)(struct uart_port *);/* 禁止串口发送数据 */
  10:      void        (*start_tx)(struct uart_port *);/* 使能串口发送数据 */
  11:      void        (*send_xchar)(struct uart_port *, char ch);/* 发送xChar */
  12:      void        (*stop_rx)(struct uart_port *);/* 禁止串口接收数据 */
  13:      void        (*enable_ms)(struct uart_port *);/* 使能modem的状态信号 */
  14:      void        (*break_ctl)(struct uart_port *, int ctl); /* 设置break信号 */
  15:      int        (*startup)(struct uart_port *);/* 启动串口,应用程序打开串口设备文件时,该函数会被调用 */
  16:      void        (*shutdown)(struct uart_port *);/* 关闭串口,应用程序关闭串口设备文件时,该函数会被调用 */
  17:      void        (*flush_buffer)(struct uart_port *);
  18:      void        (*set_termios)(struct uart_port *, struct ktermios *new,
  19:                         struct ktermios *old);/* 设置串口参数 */
  20:      void        (*set_ldisc)(struct uart_port *, int new);
  21:      void        (*pm)(struct uart_port *, unsigned int state,
  22:                    unsigned int oldstate);/* 串口电源管理 */
  23:      int        (*set_wake)(struct uart_port *, unsigned int state);
  24:      void        (*wake_peer)(struct uart_port *);
  25:   
  26:      /*
  27:       * Return a string describing the type of the port
  28:       */
  29:      const char *(*type)(struct uart_port *);/* 返回一描述串口类型的字符串 */
  30:   
  31:      /*
  32:       * Release IO and memory resources used by the port.
  33:       * This includes iounmap if necessary.
  34:       */
  35:      void        (*release_port)(struct uart_port *);/* 释放串口已申请的IO端口/IO内存资源,必要时还需iounmap */
  36:   
  37:      /*
  38:       * Request IO and memory resources used by the port.
  39:       * This includes iomapping the port if necessary.
  40:       */
  41:      int        (*request_port)(struct uart_port *); /* 申请必要的IO端口/IO内存资源,必要时还可以重新映射串口端口 */
  42:      void        (*config_port)(struct uart_port *, int);/* 执行串口所需的自动配置 */
  43:      int        (*verify_port)(struct uart_port *, struct serial_struct *);/* 验证串口所需的自动配置 */
  44:      int        (*ioctl)(struct uart_port *, unsigned int, unsigned long);
  45:  #ifdef CONFIG_CONSOLE_POLL
  46:      void    (*poll_put_char)(struct uart_port *, unsigned char);
  47:      int        (*poll_get_char)(struct uart_port *);
  48:  #endif
  49:  };

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

二、串口驱动API

1、uart_register_driver

   1:  /  * 功能:uart_register_driver用于将串口驱动uart_driver注册到内核(串口核心层)中,通常在模块初始化函数调用该函数。   
   2:     * 参数 drv:要注册的uart_driver  
   3:     * 返回值:  成功,返回0;否则返回错误码  
   4:  */   
   5:    int uart_register_driver(struct uart_driver *drv)   

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

2、uart_unregister_driver

   1:  /* 功能:    uart_unregister_driver用于注销我们已注册的uart_driver,通常在模块卸载函数调用该函数
   2:   * 参数 drv:要注销的uart_driver
   3:  
   4:   * 返回值:  成功,返回0;否则返回错误码
   5:   */
   6:  void uart_unregister_driver(struct uart_driver *drv)
   7:   

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

3、uart_add_one_port

   1:  /* 功能:    uart_add_one_port用于为串口驱动添加一个串口端口,通常在探测到设备后(驱动的设备probe方法)调用该函数
   2:   * 参数 drv:串口驱动
   3:   *      port:要添加的串口端口
   4:  
   5:   * 返回值:  成功,返回0;否则返回错误码
   6:   */
   7:  int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

4、uart_remove_one_port

   1:  /* 功能:     uart_remove_one_port用于删除一个已添加到串口驱动中的串口端口,通常在驱动卸载时调用该函数
   2:   * 参数 drv: 串口驱动
   3:   *      port: 要删除的串口端口
   4:   * 返回值:   成功,返回0;否则返回错误码
   5:   */
   6:  int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

5、uart_write_wakeup

   1:  /* 功能:     uart_write_wakeup唤醒上层因向串口端口写数据而阻塞的进程,通常在串口发送中断处理函数中调用该函数
   2:   * 参数 port:需要唤醒写阻塞进程的串口端口
   3:   */
   4:  void uart_write_wakeup(struct uart_port *port)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

6、uart_suspend_port

   1:  /* 功能:     uart_suspend_port用于挂起特定的串口端口
   2:   * 参数 drv: 要挂起的串口端口所属的串口驱动
   3:   *      port:要挂起的串口端口
   4:   * 返回值:   成功返回0;否则返回错误码
   5:   */
   6:  int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

7、uart_resume_port

   1:  /* 功能:     uart_resume_port用于恢复某一已挂起的串口
   2:   * 参数 drv: 要恢复的串口端口所属的串口驱动
   3:   *      port:要恢复的串口端口
   4:   * 返回值:   成功返回0;否则返回错误码
   5:   */
   6:  int uart_resume_port(struct uart_driver *drv, struct uart_port *port)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

8、uart_get_baud_rate

   1:  /* 功能:        uart_get_baud_rate通过解码termios结构体来获取指定串口的波特率
   2:   * 参数 port:  要获取波特率的串口端口
   3:   *     termios:当前期望的termios配置(包含串口波特率)
   4:   *     old:    以前的termios配置,可以为NULL
   5:   *     min:    可接受的最小波特率
   6:   *     max:    可接受的最大波特率
   7:   * 返回值:     串口的波特率
   8:   */
   9:  unsigned int
  10:  uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
  11:  struct ktermios *old, unsigned int min, unsigned int max)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

9、uart_get_divisor

   1:  /* 功能:     uart_get_divisor用于计算某一波特率的串口时钟分频数(串口波特率除数)
   2:   * 参数 port:要计算时钟分频数的串口端口
   3:   *      baud:期望的波特率
   4:   *返回值:    串口时钟分频数
   5:   */
   6:  unsigned int uart_get_divisor(struct uart_port *port, unsigned int baud)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

10、uart_update_timeout

   1:  /* 功能:      uart_update_timeout用于更新(设置)串口FIFO超时时间
   2:   * 参数 port: 要更新超时时间的串口端口
   3:   *     cflag:termios结构体的cflag值
   4:   *     baud: 串口的波特率
   5:   */
   6:  void uart_update_timeout(struct uart_port *port, unsigned int cflag, unsigned int baud)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

11、uart_match_port

   1:  /* 功能:uart_match_port用于判断两串口端口是否为同一端口
   2:   * 参数 port1、port2:要判断的串口端口
   3:   * 返回值:不同返回0;否则返回非0
   4:   */
   5:  int uart_match_port(struct uart_port *port1, struct uart_port *port2)

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

12、uart_console_write

   1:  /* 功能:        uart_console_write用于向串口端口写一控制台信息
   2:  
   3:   * 参数 port:    要写信息的串口端口
   4:   *     s:       要写的信息
   5:   *     count:   信息的大小
   6:   *     putchar: 用于向串口端口写字符的函数,该函数函数有两个参数:串口端口和要写的字符
   7:   */
   8:  void uart_console_write(struct uart_port *port, const char *s,
   9:  unsigned int count,
  10:  void (*putchar)(struct uart_port *, int))
  11:   

.csharpcode,.csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff }
.csharpcode pre { margin: 0em }
.csharpcode .rem { color: #008000 }
.csharpcode .kwrd { color: #0000ff }
.csharpcode .str { color: #006080 }
.csharpcode .op { color: #0000c0 }
.csharpcode .preproc { color: #cc6633 }
.csharpcode .asp { background-color: #ffff00 }
.csharpcode .html { color: #800000 }
.csharpcode .attr { color: #ff0000 }
.csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em }
.csharpcode .lnum { color: #606060 }

时间: 2024-10-14 13:46:03

linux uart驱动——相关数据结构以及API(二)的相关文章

【linux驱动笔记】字符设备驱动相关数据结构与算法

欢迎转载,转载时需保留作者信息,谢谢. 邮箱:[email protected] 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http://blog.csdn.net/xiayulewa   1.1.1.   设备号 alloc_chrdev_region(&dev, 0, 1, "buttons") /  register_chrdev_region: 动态申请设备号, 设备号组成了链表节点. 最后的结果为:所有的ch

(转)FS_S5PC100平台上Linux Camera驱动开发详解(二)

4-3 摄像头的初始化流程及v4l2子设备驱动 这个问题弄清楚了以后下面就来看获得Camera信息以后如何做后续的处理: 在fimc_init_global调用结束之后我们获得了OV9650的信息,之后在probe函数里面就会继续调用一个函数:fimc_configure_subdev(). 这个函数的实现如下: /*        * Assign v4l2 device and subdev to fimc        * it is called per every fimc ctrl

Linux嵌入式驱动学习之路(十二)按键驱动-poll机制

实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键信息,则自己退出. 首先应用程序执行poll函数 kernel中的sys_poll do_sys_poll init_poll_funcptr-->do_poll do_poll for(;;) { if(do_pollfd(pfd,pt)) { count++; //如果驱动的poll返回非0值,

Linux 设备驱动之 UIO 机制(二)

一个设备驱动的主要任务有两个: 1. 存取设备的内存 2. 处理设备产生的中断 对于第一个任务,UIO 核心实现了mmap()可以处理物理内存(physical memory),逻辑内存(logical memory), 虚拟内存(virtual memory).UIO驱动的编写是就不需要再考虑这些繁琐的细节. 第二个任务,对于设备中断的应答必须在内核空间进行.所以在内核空间有一小部分代码 用来应答中断和禁止中断,但是其余的工作全部留给用户空间处理. 如果用户空间要等待一个设备中断,它只需要简单

linux设备驱动归纳总结

前言: (总结已经基本写完,这段时间我会从新排版和修正.错误总会有的,望能指正!) 前段时间学习了嵌入式驱动,趁着没开始找工作,这段时间我会每天抽出时间来复习. 我的总结是根据学习时的笔记(李杨老师授课).<linux内核设计与实现>第三版.<linux设备驱动程序>第三版和<linux设备驱动开发详解>第一版来归纳的.文章中涉及一些自己的想法,并不能保证所说的一定正确. 我也是一位linux初学者,在这里发博也是想跟大家分享技术,同时也希望别人能够指正错误. 我把一些

Linux网络设备驱动结构概述

网络设备驱动相比字符型设备的驱动要复杂一些,除了总体上驱动的框架有一些相似外,有很多地方都是不同,但网络设备驱动有一个很大的特点就是有固定的框架可以遵循,具体的框架会在后边详细的叙述.1.网络协议接口层在网络协议接口层,只提供了两个抽象函数dev_queue_xmit()与 netif_rx(),之所以称之为抽象函数,是因为这两个函数抽象了很多底层的操作,不管是那个芯片它在网络协议结构的操作函数都是这两个函数,采用这样的抽象后,给上层带来了很多的方便,给上层协议提供统一的数据包收发接口,无论上层

Linux网络驱动架构

网络设备介绍 网络设备是计算机体系结构中必不可少的一部分,处理器如果想与外界通信,通常都会选择网络设备作为通信接口.众所周知,在 OSI(Open Systems Interconnection,开放网际互连)中,网络被划分为七个层次,从下到上分别是物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.我们所讲的网络设备也包括两个层次,一层叫做 MAC(Media Access Control)层,对应于 OSI 的数据链路层:另一层叫做 PHY(Physical Layer)层,对应于物

Linux kernel 之 uart 驱动解析

uart 是一种非常之常见的总线,比如DEBUG信息输出,小数据量数据传输,485,以及蓝牙的控制,GPS,很多都是通过uart 进行数据传输并进行控制. 在Linux kernel 内部,uart 通常是作为 一个 tty 设备对其进行控制,也是就是一个字符设备文件,可对其进行读写操作. kernel version 4.4.12 首先先看一下基本的 结构体 和 API 操作. // include/linux/serial_core.h // uart 驱动结构体 struct uart_d

Linux设备驱动核心理论(二)

7.Linux设备驱动中的并发控制 7.1 并发与竞态 并发(concurrency)指的是多个执行单元同时.并行被执行,而并发的执行单元对共享资源(硬件资源和软件上的全局变量.静态变量等)的访问则很容易导致竞态(race conditions). 1.对称多处理器(SMP)的多个CPU SMP是一种紧耦合.共享存储的系统模型,其体系结构如下图,它的特点是多个CPU使用共同的系统总线,因此可访问共同的外设和存储器. 2.单CPU内进程与抢占它的进程 Linux 2.6内核支持抢占调度,一个进程内