19.串口驅動程序學習(一)

            串口驅動程序學習linux

  本文主要實現對串口驅動程序初始化的分析ios

1、串口驅動中的數據結構數據結構

  儘管一個特定的UART設備驅動徹底能夠按照tty驅動的設計方法來設計,即定義tty_driver並實現tty_operations其中的成員函數,可是Linux已經在文件serial_core.c中實現了UART設備的通用tty驅動層,稱爲串口核心層,這樣,UART驅動的主要任務變成了實現serial_core.c中定義的一組uart_xxx接口而非tty_xxx接口。app

1.1下圖描述了串行系統間的層次結構關係,能夠歸納爲:函數

  用戶應用層 --> 線路規劃層 --> TTY層 --> 底層驅動層 --> 物理硬件層學習

  

1.2下圖是串口核心層在整個tty源文件關係及數據流向中的位置:this

  

其中的xxx_uart.c在此處就是drivers/tty/serial/samsung.c和s3c6400.cspa

2、串口驅動中的數據結構設計

  

1.4使用到的數據結構3d

Uart驅動程序主要圍繞三個關鍵的數據結構展開(include/linux/serial_core.h中定義):

  1. UART驅動程序結構:struct uart_driver
  2. UART端口結構: struct uart_port
  3. UART相關操做函數結構: struct uart_ops

1.4.1其中一個串口驅動對應一個struct uart_driver固然一個驅動是能夠對應多個設備的:

 1 struct uart_driver {
 2     struct module        *owner;
 3     const char        *driver_name;
 4     const char        *dev_name;
 5     int             major;
 6     int             minor;
 7     int             nr;    //端口個數
 8     struct console        *cons;
 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 };

 

其中的uart_state是設備狀態結構結構體:

1 struct uart_state {
2     struct tty_port        port;
3     int            pm_state;
4     struct circ_buf        xmit;
5     struct tasklet_struct    tlet;
6     struct uart_port    *uart_port;
7 };

 

   在uart_open()中:

   tty->driver_data = state;

   在其餘uart_xxx()中:

   struct uart_state *state = tty->driver_data;

   就能夠獲取設備私有信息結構體。

1.4.2uart_port用於描述一個UART端口(直接對應於一個串口)的I/O端口或者IO內存地址等信息--->即一個uart_port對應一個端口

 1 struct uart_port {
 2     spinlock_t        lock;            /* port lock */
 3     unsigned long        iobase;            /* in/out[bwl] */
 4     unsigned char __iomem    *membase;        /* read/write[bwl] */
 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 };

 

1.4.3uart_ops定義了針對UART的一系列操做

 1 struct uart_ops {
 2     unsigned int    (*tx_empty)(struct uart_port *);
 3     void        (*set_mctrl)(struct uart_port *, unsigned int mctrl);
 4     unsigned int    (*get_mctrl)(struct uart_port *);
 5     void        (*stop_tx)(struct uart_port *);
 6     void        (*start_tx)(struct uart_port *);
 7     void        (*send_xchar)(struct uart_port *, char ch);
 8     void        (*stop_rx)(struct uart_port *);
 9     void        (*enable_ms)(struct uart_port *);
10     void        (*break_ctl)(struct uart_port *, int ctl);
11     int        (*startup)(struct uart_port *);
12     void        (*shutdown)(struct uart_port *);
13     void        (*flush_buffer)(struct uart_port *);
14     void        (*set_termios)(struct uart_port *, struct ktermios *new,
15                        struct ktermios *old);
16     void        (*set_ldisc)(struct uart_port *, int new);
17     void        (*pm)(struct uart_port *, unsigned int state,
18                   unsigned int oldstate);
19     int        (*set_wake)(struct uart_port *, unsigned int state);
20 
21     /*
22      * Return a string describing the type of the port
23      */
24     const char *(*type)(struct uart_port *);
25 
26     /*
27      * Release IO and memory resources used by the port.
28      * This includes iounmap if necessary.
29      */
30     void        (*release_port)(struct uart_port *);
31 
32     /*
33      * Request IO and memory resources used by the port.
34      * This includes iomapping the port if necessary.
35      */
36     int        (*request_port)(struct uart_port *);
37     void        (*config_port)(struct uart_port *, int);
38     int        (*verify_port)(struct uart_port *, struct serial_struct *);
39     int        (*ioctl)(struct uart_port *, unsigned int, unsigned long);
40 #ifdef CONFIG_CONSOLE_POLL
41     void    (*poll_put_char)(struct uart_port *, unsigned char);
42     int        (*poll_get_char)(struct uart_port *);
43 #endif
44 };

 

UART信息結構: struct uart_info

2、串口初始化分析

  

分析過程:

2.1進入到內核的Samsung.c文件中

  找到內核模塊加載函數:module_init(s3c24xx_serial_modinit);

  能夠看到加載模塊直接調用platform_driver_register,註冊了 開發板串口這個平臺驅動。

  由於把uart驅動註冊爲platform驅動,當平臺驅動與平臺設備進行匹配的時候會調用平臺總線的match函數,匹配成功後就會調用平臺驅動的xxx_probe()函數來進行一系列的初始化工做。

 1 int s3c24xx_serial_probe(struct platform_device *dev,
 2              struct s3c24xx_uart_info *info)
 3 {
 4     struct s3c24xx_uart_port *ourport;
 5     int ret;
 6 
 7     dbg("s3c24xx_serial_probe(%p, %p) %d\n", dev, info, probe_index);
 8 
 9     ourport = &s3c24xx_serial_ports[probe_index];
10     probe_index++;
11 
12     dbg("%s: initialising port %p...\n", __func__, ourport);
13 
14     ret = s3c24xx_serial_init_port(ourport, info, dev);
15     if (ret < 0)
16         goto probe_err;
17 
18     dbg("%s: adding port\n", __func__);
19     uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
20     platform_set_drvdata(dev, &ourport->port);
21 
22     ret = device_create_file(&dev->dev, &dev_attr_clock_source);
23     if (ret < 0)
24         printk(KERN_ERR "%s: failed to add clksrc attr.\n", __func__);
25 
26     ret = s3c24xx_serial_cpufreq_register(ourport);
27     if (ret < 0)
28         dev_err(&dev->dev, "failed to add cpufreq notifier\n");
29 
30     return 0;
31 
32  probe_err:
33     return ret;
34 }
相關文章
相關標籤/搜索