订阅
纠错
加入自媒体

技术文章:基于Linux的tty架构及UART驱动详解

2021-02-05 17:06
一口Linux
关注

2.2.3. struct uart_state

每一个uart端口对应着一个uart_state,该结构体将uart_port与对应的circ_buf联系起来。uart_state有两个成员在底层串口驱动会用到:xmit和port。

用户空间程序通过串口发送数据时,上层驱动将用户数据保存在xmit;而串口发送中断处理函数就是通过xmit获取到用户数据并将它们发送出去。串口接收中断处理函数需要通过port将接收到的数据传递给线路规程层。

struct uart_state {
      struct  tty_port  port;
     
      enum uart_pm_state   pm_state;
      struct circ_buf     xmit;
     
      struct uart_port     *uart_port; 对应于一个串口设备
};
2.2.4. struct uart_port

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

struct uart_port {
       spinlock_t              lock;                    port lock
       unsigned long           iobase;                  in/out[bwl]
       unsigned char __iomem   *membase;                read/write[bwl]
       unsigned int            (*serial_in)(struct uart_port *, int);
       void                    (*serial_out)(struct uart_port *, int, int);
       void                    (*set_termios)(struct uart_port *,
                                              struct ktermios *new,
                                              struct ktermios *old);
       int                     (*handle_irq)(struct uart_port *);
       void                    (*pm)(struct uart_port *, unsigned int state,
                                     unsigned int old);
       void                    (*handle_break)(struct uart_port *);
       unsigned int            irq;                     irq number
       unsigned long           irqflags;                irq flags  
       unsigned int            uartclk;                 base uart clock
       unsigned int            fifosize;                tx fifo size
       unsigned char           x_char;                  xon/xoff char
       unsigned char           regshift;                reg offset shift
       unsigned char           iotype;                  io access style
       unsigned char           unused1;
#define UPIO_PORT               (0)
#define UPIO_HUB6               (1)
#define UPIO_MEM                (2)
#define UPIO_MEM32              (3)
#define UPIO_AU                 (4)                      Au1x00 and RT288x type IO
#define UPIO_TSI                (5)                      Tsi108/109 type IO
       unsigned int            read_status_mask;        driver specific
       unsigned int            ignore_status_mask;      driver specific
       struct uart_state       *state;                  pointer to parent state
       struct uart_icount      icount;                  statistics
       struct console          *cons;                   struct console, if any
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
       unsigned long           sysrq;                   sysrq timeout
#endif
       upf_t                   flags;
#define UPF_FOURPORT            ((__force upf_t) (1 << 1))
#define UPF_SAK                 ((__force upf_t) (1 << 2))
#define UPF_SPD_MASK            ((__force upf_t) (0x1030))
#define UPF_SPD_HI              ((__force upf_t) (0x0010))
#define UPF_SPD_VHI             ((__force upf_t) (0x0020))
#define UPF_SPD_CUST            ((__force upf_t) (0x0030))
#define UPF_SPD_SHI             ((__force upf_t) (0x1000))
#define UPF_SPD_WARP            ((__force upf_t) (0x1010))
#define UPF_SKIP_TEST           ((__force upf_t) (1 << 6))
#define UPF_AUTO_IRQ            ((__force upf_t) (1 << 7))
#define UPF_HARDPPS_CD          ((__force upf_t) (1 << 11))
#define UPF_LOW_LATENCY         ((__force upf_t) (1 << 13))
#define UPF_BUGGY_UART          ((__force upf_t) (1 << 14))
#define UPF_NO_TXEN_TEST        ((__force upf_t) (1 << 15))
#define UPF_MAGIC_MULTIPLIER    ((__force upf_t) (1 << 16))
Port has hardware-assisted h/w flow control (iow, auto-RTS *not* auto-CTS)
#define UPF_HARD_FLOW           ((__force upf_t) (1 << 21))
Port has hardware-assisted s/w flow control
#define UPF_SOFT_FLOW           ((__force upf_t) (1 << 22))
#define UPF_CONS_FLOW           ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ           ((__force upf_t) (1 << 24))
#define UPF_EXAR_EFR            ((__force upf_t) (1 << 25))
#define UPF_BUG_THRE            ((__force upf_t) (1 << 26))
The exact UART type is known and should not be probed.  
#define UPF_FIXED_TYPE          ((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF       ((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT          ((__force upf_t) (1 << 29))
#define UPF_DEAD                ((__force upf_t) (1 << 30))
#define UPF_IOREMAP             ((__force upf_t) (1 << 31))
#define UPF_CHANGE_MASK         ((__force upf_t) (0x17fff))
#define UPF_USR_MASK            ((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))
       unsigned int            mctrl;                   current modem ctrl settings
       unsigned int            timeout;                 character-based timeout
       unsigned int            type;                    port type
       const struct uart_ops   *ops;
       unsigned int            custom_divisor;
       unsigned int            line;                    port index
       resource_size_t         mapbase;                 for ioremap
       struct device           *dev;                    parent device
       unsigned char           hub6;                    this should be in the 8250 driver
       unsigned char           suspended;
       unsigned char           irq_wake;
       unsigned char           unused[2];
       void                    *private_data;           generic platform data pointer
};
2.2.5. struct uart_ops

struct uart_ops涵盖了驱动可对串口的所有操作

struct uart_ops {
       unsigned int    (*tx_empty)(struct uart_port *);
       void            (*set_mctrl)(struct uart_port *, unsigned int mctrl);
       unsigned int    (*get_mctrl)(struct uart_port *);
       void            (*stop_tx)(struct uart_port *);
       void            (*start_tx)(struct uart_port *);
       void            (*throttle)(struct uart_port *);
       void            (*unthrottle)(struct uart_port *);
       void            (*send_xchar)(struct uart_port *, char ch);
       void            (*stop_rx)(struct uart_port *);
       void            (*enable_ms)(struct uart_port *);
       void            (*break_ctl)(struct uart_port *, int ctl);
       int             (*startup)(struct uart_port *);
       void            (*shutdown)(struct uart_port *);
       void            (*flush_buffer)(struct uart_port *);
       void            (*set_termios)(struct uart_port *, struct ktermios *new,
                                      struct ktermios *old);
       void            (*set_ldisc)(struct uart_port *, int new);
       void            (*pm)(struct uart_port *, unsigned int state,
                             unsigned int oldstate);
       int             (*set_wake)(struct uart_port *, unsigned int state);
       
        * Return a string describing the type of the port
       
       const char      *(*type)(struct uart_port *);
       
        * Release IO and memory resources used by the port.
        * This includes iounmap if necessary.
       
       void            (*release_port)(struct uart_port *);
       
        * Request IO and memory resources used by the port.
        * This includes iomapping the port if necessary.
       
       int             (*request_port)(struct uart_port *);
       void            (*config_port)(struct uart_port *, int);
       int             (*verify_port)(struct uart_port *, struct serial_struct *);
       int             (*ioctl)(struct uart_port *, unsigned int, unsigned long);
#ifdef CONFIG_CONSOLE_POLL
       int             (*poll_init)(struct uart_port *);
       void            (*poll_put_char)(struct uart_port *, unsigned char);
       int             (*poll_get_char)(struct uart_port *);
#endif
};

2.3. 关键流程2.3.1. 注册流程2.3.1.1. 注册uart_driver

此接口在uart driver中调用,用来注册uart_driver到kernel中,调用阶段在uart driver的初始阶段,例如:module_init(), uart_driver的注册流程图

图3.3uart driver注册流程

注册过程主要做了以下操作:

1、根据driver支持的最大设备数,申请n个uart_state空间,每一个uart_state都有一个uart_port。2、分配一个tty_driver,并将uart_driver->tty_driver指向它。3、对tty_driver进行设置,其中包括默认波特率、检验方式等,还有一个重要的ops,结构体tty_operation的注册,它是tty核心与串口驱动通信的接口。4、初始化每一个uart_state的tty_port;5、注册tty_driver。注册uart_driver实际上是注册tty_driver,与用户空间打交道的工作完全交给tty_driver,这一部分是内核实现好的不需要修改2.3.1.2. 添加uart_port

此接口用于注册一个uart port 到uart driver上,通过注册,uart driver就可以访问对应的uart port,进行数据收发。该接口在uart driver中的probe函数调用,必须保证晚于uart_register_drver的注册过程。

<上一页  1  2  3  4  下一页>  
声明: 本文由入驻维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。

发表评论

0条评论,0人参与

请输入评论内容...

请输入评论/评论长度6~500个字

您提交的评论过于频繁,请输入验证码继续

暂无评论

暂无评论

    人工智能 猎头职位 更多
    扫码关注公众号
    OFweek人工智能网
    获取更多精彩内容
    文章纠错
    x
    *文字标题:
    *纠错内容:
    联系邮箱:
    *验 证 码:

    粤公网安备 44030502002758号