訂閱
糾錯(cuò)
加入自媒體

技術(shù)文章:基于Linux的tty架構(gòu)及UART驅(qū)動(dòng)詳解

2.2.3. struct uart_state

每一個(gè)uart端口對(duì)應(yīng)著一個(gè)uart_state,該結(jié)構(gòu)體將uart_port與對(duì)應(yīng)的circ_buf聯(lián)系起來(lái)。uart_state有兩個(gè)成員在底層串口驅(qū)動(dòng)會(huì)用到:xmit和port。

用戶(hù)空間程序通過(guò)串口發(fā)送數(shù)據(jù)時(shí),上層驅(qū)動(dòng)將用戶(hù)數(shù)據(jù)保存在xmit;而串口發(fā)送中斷處理函數(shù)就是通過(guò)xmit獲取到用戶(hù)數(shù)據(jù)并將它們發(fā)送出去。串口接收中斷處理函數(shù)需要通過(guò)port將接收到的數(shù)據(jù)傳遞給線(xiàn)路規(guī)程層。

struct uart_state {
      struct  tty_port  port;
     
      enum uart_pm_state   pm_state;
      struct circ_buf     xmit;
     
      struct uart_port     *uart_port; 對(duì)應(yīng)于一個(gè)串口設(shè)備
};
2.2.4. struct uart_port

uart_port用于描述串口端口的I/O端口或I/O內(nèi)存地址、FIFO大小、端口類(lèi)型、串口時(shí)鐘等信息。實(shí)際上,一個(gè)uart_port實(shí)現(xiàn)對(duì)應(yīng)一個(gè)串口設(shè)備。

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_M(jìn)EM                (2)
#define UPIO_M(jìn)EM32              (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_M(jìn)ASK            ((__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_M(jìn)AGIC_M(jìn)ULTIPLIER    ((__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_M(jìn)ASK         ((__force upf_t) (0x17fff))
#define UPF_USR_M(jìn)ASK            ((__force upf_t) (UPF_SPD_M(jìn)ASK|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涵蓋了驅(qū)動(dòng)可對(duì)串口的所有操作

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. 關(guān)鍵流程2.3.1. 注冊(cè)流程2.3.1.1. 注冊(cè)u(píng)art_driver

此接口在uart driver中調(diào)用,用來(lái)注冊(cè)u(píng)art_driver到kernel中,調(diào)用階段在uart driver的初始階段,例如:module_init(), uart_driver的注冊(cè)流程圖

圖3.3uart driver注冊(cè)流程

注冊(cè)過(guò)程主要做了以下操作:

1、根據(jù)driver支持的最大設(shè)備數(shù),申請(qǐng)n個(gè)uart_state空間,每一個(gè)uart_state都有一個(gè)uart_port。2、分配一個(gè)tty_driver,并將uart_driver->tty_driver指向它。3、對(duì)tty_driver進(jìn)行設(shè)置,其中包括默認(rèn)波特率、檢驗(yàn)方式等,還有一個(gè)重要的ops,結(jié)構(gòu)體tty_operation的注冊(cè),它是tty核心與串口驅(qū)動(dòng)通信的接口。4、初始化每一個(gè)uart_state的tty_port;5、注冊(cè)tty_driver。注冊(cè)u(píng)art_driver實(shí)際上是注冊(cè)tty_driver,與用戶(hù)空間打交道的工作完全交給tty_driver,這一部分是內(nèi)核實(shí)現(xiàn)好的不需要修改2.3.1.2. 添加uart_port

此接口用于注冊(cè)一個(gè)uart port 到uart driver上,通過(guò)注冊(cè),uart driver就可以訪(fǎng)問(wèn)對(duì)應(yīng)的uart port,進(jìn)行數(shù)據(jù)收發(fā)。該接口在uart driver中的probe函數(shù)調(diào)用,必須保證晚于uart_register_drver的注冊(cè)過(guò)程。

<上一頁(yè)  1  2  3  4  下一頁(yè)>  
聲明: 本文由入駐維科號(hào)的作者撰寫(xiě),觀(guān)點(diǎn)僅代表作者本人,不代表OFweek立場(chǎng)。如有侵權(quán)或其他問(wèn)題,請(qǐng)聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請(qǐng)輸入評(píng)論內(nèi)容...

請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字

您提交的評(píng)論過(guò)于頻繁,請(qǐng)輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無(wú)評(píng)論

暫無(wú)評(píng)論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號(hào)
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號(hào)