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 这个文档。