【北京迅为】i.MX6ULL终结者Linux RS232/485驱动实验Linux下的UART驱动框架

1 uart_driver结构体

在Linux中uart和I2C、SPI一样,提供了串口驱动框架,只需要按照提供的串口框架函数编译驱动即可。一般来说串口驱动都已经实现好了,我们需要做的就是在设备树文件中,添加相应的设备节点。当设备和驱动匹配成功后,串口就能够正常工作。
在Linux中,用uart_driver结构体来描述串口,uart_driver 定义在include/linux/serial_core.h 文件中,内容如下:

295 struct uart_driver {
    
     
296        struct module *owner; /* 模块所属者 */ 
297        const char *driver_name; /* 驱动名字 */ 
298        const char *dev_name; /* 设备名字 */ 
299        int major; /* 主设备号 */ 
300        int minor; /* 次设备号 */ 
301        int nr; /* 设备数 */ 
302        struct console *cons; /* 控制台 */ 
303 
304        /* 
305        * these are private; the low level driver should not 
306        * touch these; they should be initialised to NULL 
307        */ 
308        struct uart_state *state; 
309        struct tty_driver *tty_driver; 
310 };

一般在开发板上有几个串口,每个串口驱动都需要定义一个uart_driver结构体来表示。
同其他设备一样,当uart_driver结构体创建好后,然后注册到内核中去。使用uart_register_driver 函数来完成注册行为,函数原型如下:
int uart_register_driver(struct uart_driver *drv)
参数drv就是创建好要注册的uart_driver结构体,返回0,表示成功,失败返回负值。
既然有注册函数,同样的也有注销函数uart_unregister_driver,函数原型如下:
void uart_unregister_driver(struct uart_driver *drv)
参数drv是要注销的uart_driver结构体,没有返回值。

2 uart_port结构体

uart_port用于描述一个UART端口(直接对应于一个串口)的I/O端口或I/O内存地址、FIFO大小、端口类型等信息。
uart_port 定义在 include/linux/serial_core.h 文件,部分内容如下:

117 struct uart_port {
    
     
118        spinlock_t lock; /* port lock */ 
119     unsigned long iobase; /* in/out[bwl] */ 
120        unsigned char __iomem *membase; /* read/write[bwl] */ 
...... 
235        const struct uart_ops *ops; 
236        unsigned int custom_divisor; 
237        unsigned int line; /* port index */ 
238        unsigned int minor; 
239        resource_size_t mapbase; /* for ioremap */ 
240        resource_size_t mapsize; 
241        struct device *dev; /* parent device */ 
...... 
250 }; 

在uart_port结构体中主要关注ops成员,ops成员包含了串口的具体驱动函数,后面具体了解。
每个UART都有一个uart_port结构体,那么uart_port和uart_driver是如何结合起来的,要用到uart_add_one_port 函数,函数原型如下:

int uart_add_one_port(struct uart_driver *drv, 
struct uart_port *uport)

drv:与uart_port对应的uart_driver结构体,
uport:要添加到uart_driver结构体中的uart_port结构体。
返回值:0,表示成功,负值,表示失败。
卸载UART驱动时,也需要将uart_port从相应的uart_driver中移除,使用uart_remove_one_port 函数来实现,函数原型如下:
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
drv:要卸载的uart_port对应的uart_driver。
uport:要卸载的uart_port。
返回值:0,表示成功,负值,表示失败。

3 uart_ops结构体

uart_ops结构体中包含了UART框架中具体的驱动函数,Linux 系统收发数据最终调用的都是 ops 中的函数。ops 是 uart_ops类型的结构体指针变量,uart_ops 定义在 include/linux/serial_core.h 文件中,内容如下:

49 struct uart_ops {
    
     
50         unsigned int (*tx_empty)(struct uart_port *); 
51     void (*set_mctrl)(struct uart_port *, unsigned int mctrl); 
52         unsigned int (*get_mctrl)(struct uart_port *); 
53         void (*stop_tx)(struct uart_port *); 
54         void (*start_tx)(struct uart_port *); 
55         void (*throttle)(struct uart_port *);
56         void (*unthrottle)(struct uart_port *); 
57         void (*send_xchar)(struct uart_port *, char ch); 
58         void (*stop_rx)(struct uart_port *); 
59         void (*enable_ms)(struct uart_port *); 
60         void (*break_ctl)(struct uart_port *, int ctl); 
61         int (*startup)(struct uart_port *); 
62         void (*shutdown)(struct uart_port *); 
63         void (*flush_buffer)(struct uart_port *); 
64         void (*set_termios)(struct uart_port *, struct ktermios *new, 
65         struct ktermios *old); 
66         void (*set_ldisc)(struct uart_port *, struct ktermios *); 
67         void (*pm)(struct uart_port *, unsigned int state, 
68         unsigned int oldstate); 
69 
70         /* 
71         * Return a string describing the type of the port 
72         */ 
73         const char *(*type)(struct uart_port *); 
74 
75         /* 
76         * Release IO and memory resources used by the port. 
77         * This includes iounmap if necessary. 
78         */ 
79         void (*release_port)(struct uart_port *); 
80 
81         /* 
82         * Request IO and memory resources used by the port. 
83         * This includes iomapping the port if necessary. 
84         */ 
85         int (*request_port)(struct uart_port *); 
86         void (*config_port)(struct uart_port *, int); 
87         int (*verify_port)(struct uart_port *, struct serial_struct *); 
88         int (*ioctl)(struct uart_port *, unsigned int, unsigned long); 
89         #ifdef CONFIG_CONSOLE_POLL 
90         int (*poll_init)(struct uart_port *); 
91         void (*poll_put_char)(struct uart_port *, unsigned char); 
92         int (*poll_get_char)(struct uart_port *); 
93         #endif 
94 };

UART 驱动编写人员需要实现 uart_ops,因为 uart_ops 是最底层的 UART 驱动接口,是实实在在的和 UART 寄存器打交道的。关于 uart_ops 结构体中的这些函数的具体含义请参考Documentation/serial/driver 这个文档。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/BeiJingXunWei/article/details/112600374