[Beijing Xunwei] i.MX6ULL Terminator Linux RS232/485 driver experiment UART driver framework under Linux

1 uart_driver structure

In Linux, uart, like I2C and SPI, provides a serial port driver framework. You only need to compile the driver according to the provided serial port framework functions. Generally speaking, the serial port driver has been implemented, all we need to do is to add the corresponding device node in the device tree file. When the device and the driver are successfully matched, the serial port can work normally.
In Linux, the uart_driver structure is used to describe the serial port, uart_driver is defined in the include/linux/serial_core.h file, and the content is as follows:

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 };

Generally, there are several serial ports on the development board, and each serial port driver needs to define a uart_driver structure to represent.
Like other devices, when the uart_driver structure is created, it is then registered in the kernel. Use the uart_register_driver function to complete the registration behavior. The function prototype is as follows: the
int uart_register_driver(struct uart_driver *drv)
parameter drv is to create the uart_driver structure to be registered, and return 0, indicating success, and returning a negative value on failure.
Since there is a registration function, there is also a cancellation function uart_unregister_driver. The function prototype is as follows: the
void uart_unregister_driver(struct uart_driver *drv)
parameter drv is the uart_driver structure to be cancelled, and there is no return value.

2 uart_port structure

uart_port is used to describe the I/O port or I/O memory address, FIFO size, port type and other information of a UART port (corresponding directly to a serial port).
uart_port is defined in the include/linux/serial_core.h file, part of the content is as follows:

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 }; 

In the uart_port structure, we mainly focus on the ops member. The ops member contains the specific driver function of the serial port, which will be explained in detail later.
Every UART has a uart_port structure, how to combine uart_port and uart_driver, use uart_add_one_port function, the function prototype is as follows:

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

drv: the uart_driver structure corresponding to uart_port,
uport: the uart_port structure to be added to the uart_driver structure.
Return value: 0, indicating success, negative value, indicating failure.
When uninstalling the UART driver, you also need to remove the uart_port from the corresponding uart_driver, and use the uart_remove_one_port function to implement it. The function prototype is as follows:
int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
drv: uart_driver corresponding to the uart_port to be uninstalled.
uport: uart_port to be uninstalled.
Return value: 0, indicating success, negative value, indicating failure.

3 uart_ops structure

The uart_ops structure contains the specific driver functions in the UART framework. The Linux system sends and receives data and ultimately calls the functions in ops. ops is a structure pointer variable of type uart_ops, uart_ops is defined in the include/linux/serial_core.h file, and the content is as follows:

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 driver writers need to implement uart_ops, because uart_ops is the bottom UART driver interface, which actually deals with UART registers. For the specific meaning of these functions in the uart_ops structure, please refer to the Documentation/serial/driver document.

Insert picture description here

Guess you like

Origin blog.csdn.net/BeiJingXunWei/article/details/112600374