UART Device Driver

Source: Internet
Author: User

Although the driver of a specific UART device can completely follow 14.2 ~ The 14.5 method is designed to define tty_driver and implement the member functions. However, Linux has implemented the universal tty driver layer (called the serial port core layer) of the UART device in the file serial_core.c ), in this way, the main task of UART driver is transformed into serial-core. A set of uart_xxx interfaces defined in C instead of tty_xxx interfaces, as shown in 14.5.
Serial_core.c serial port core layer can be regarded as 14.2 ~ Section 14.5 tty device driver instance, which implements the TTY driver for UART devices.
Tip: the layering of Linux drivers is embodied in many types of device drivers. For example, in the last chapter of IDE device drivers, the kernel implements a general ide layer for processing block device I/O requests. The specific ide only needs to use interfaces such as ide_xxx, and even does not need to care about the complex block device driver structure.

 

Figure 14.5 serial port core layer

The serial port core layer provides the following three structures for serial port device drivers:
1. uart_driver
Uart_driver contains the driver name, device name, device number, and other information of the serial device. It encapsulates tty_driver, so that the underlying UART driver does not need to care about tty_driver. Its definition is shown in code list 14.13.
Code List 14.13 uart_driver struct
1 struct uart_driver
2 {
3 struct module * owner;
4 const char * driver_name; // driver name
5 const char * dev_name; // device name
6 const char * devfs_name; // The Name Of The Device File System
7 int Major; // master device number
8 int minor; // device number
9 int NR;
10 struct console * cons;
11
12/* private, the underlying driver should not access these members and should be initialized to null */
13 struct uart_state * State;
14 struct tty_driver * tty_driver;
15 };
A tty driver must register/deregister tty_driver, while a UART driver is transformed to register/deregister uart_driver, using the following interface:
Int uart_register_driver (struct uart_driver * DRV );
Void uart_unregister_driver (struct uart_driver * DRV );
In fact, uart_register_driver () and uart_unregister_driver () contain tty_register_driver () and tty_unregister_driver () operations, as shown in code list 14.14.
Code List 14.14 uart_register_driver () and uart_unregister_driver () Functions
1 int uart_register_driver (struct uart_driver * DRV)
2 {
3 struct tty_driver * normal = NULL;
4 int I, retval;
5...
6/* allocate tty_driver */
7 normal = alloc_tty_driver (DRV-> nr );
8 If (! Normal)
9 goto out;
10 DRV-> tty_driver = normal;
11/* initialize tty_driver */
12 normal-> owner = DRV-> owner;
13 normal-> driver_name = DRV-> driver_name;
14 normal-> devfs_name = DRV-> devfs_name;
15 normal-> name = DRV-> dev_name;
16 normal-> major = DRV-> Major;
17 normal-> minor_start = DRV-> minor;
18 normal-> type = tty_driver_type_serial;
19 normal-> subtype = serial_type_normal;
20 normal-> init_termios = tty_std_termios;
21 normal-> init_termios.c_cflag = b9600 | cs8 | cread | hupcl | clocal;
22 normal-> flags = tty_driver_real_raw | tty_driver_no_devfs;
23 normal-> driver_state = DRV;
24 tty_set_operations (normal, & uart_ops );
25
26...
27/* register the TTY driver */
28 retval = tty_register_driver (normal );
29 out:
30 if (retval <0 ){
31 put_tty_driver (normal );
32 kfree (DRV-> State );
33}
34 return retval;
35}
36
37 void uart_unregister_driver (struct uart_driver * DRV)
38 {
39 struct tty_driver * P = DRV-> tty_driver;
40 tty_unregister_driver (p);/* log out of the TTY driver */
41 put_tty_driver (P );
42 kfree (DRV-> State );
43 DRV-> tty_driver = NULL;
44}
2. uart_port
Uart_port is used to describe the I/O port or I/O memory address, FIFO size, and port TYPE OF A UART port (directly corresponding to a serial port). Its definition is as follows: code list 14.15.
Code List 14.15 uart_port struct
1 struct uart_port
2 {
3. spinlock_t lock;/* port lock */
4 unsigned int iobase;/* IO port base address */
5 unsigned char _ iomem * membase;/* IO memory base address */
6 unsigned int IRQ;/* interrupt Number */
7 unsigned int uartclk;/* UART clock */
8 unsigned char bytes osize;/* Transfer FIFO size */
9 unsigned char x_char;/* Xon/xoff character */
10 unsigned char regshift;/* Register shift */
11 unsigned char iotype;/* IO access type */
12
13 # define upio_port (0)/* IO port */
14 # define upio_hub6 (1)
15 # define upio_mem (2)/* IO memory */
16 # define upio_mem32 (3)
17 # define upio_au (4)/* au1x00 type Io */
18
19 unsigned int read_status_mask;/* Driver-related */
20 unsigned int ignore_status_mask;/* Driver-related */
21 struct uart_info * Info;/* point to parent information */
22 struct uart_icount icount;/* count */
23
24 struct console * cons;/* console struct */
25 # ifdef config_serial_core_console
26 unsigned long sysrq;/* sysrq timeout */
27 # endif
28
29 upf_t flags;
30
31 # define upf_fourport (_ force upf_t) (1 <1 ))
32 # define upf_sak (_ force upf_t) (1 <2 ))
33 # define upf_spd_mask (_ force upf_t) (0x1030 ))
34 # define upf_spd_hi (_ force upf_t) (0x0010 ))
35 # define upf_spd_vhi (_ force upf_t) (0x0020 ))
36 # define upf_spd_cust (_ force upf_t) (0x0030 ))
37 # define upf_spd_shi (_ force upf_t) (0x1000 ))
38 # define upf_spd_warp (_ force upf_t) (0x1010 ))
39 # define upf_skip_test (_ force upf_t) (1 <6 ))
40 # define upf_auto_irq (_ force upf_t) (1 <7 ))
41 # define upf_hardpps_cd (_ force upf_t) (1 <11 ))
42 # define upf_low_latency (_ force upf_t) (1 <13 ))
43 # define upf_buggy_uart (_ force upf_t) (1 <14 ))
44 # define upf_magic_multiplier (_ force upf_t) (1 <16 ))
45 # define upf_cons_flow (_ force upf_t) (1 <23 ))
46 # define upf_0000_irq (_ force upf_t) (1 <24 ))
47 # define upf_boot_autoconf (_ force upf_t) (1 <28 ))
48 # define upf_ioremap (_ force upf_t) (1 <31 ))
49
50 # define upf_change_mask (_ force upf_t) (0x17fff ))
51 # define upf_usr_mask (_ force upf_t)
52 (upf_spd_mask | upf_low_latency ))
53 unsigned int mctrl;/* Current modem control settings */
54 unsigned int timeout;/* character-Based Timeout */
55 unsigned int type;/* port type */
56 const struct uart_ops * OPS;/* UART operation set */
57 unsigned int custom_divisor;
58 unsigned int line;/* port Index */
59 unsigned long mapbase;/* base address after ioremap */
60 struct device * dev;/* parent device */
61 unsigned char hub6;
62 unsigned char unused [3];
63 };
The serial port core layer provides the following functions to add one port:
Int uart_add_one_port (struct uart_driver * DRV, struct uart_port * port );
The above function should be called after uart_register_driver (). One of the most important functions of uart_add_one_port () is to encapsulate tty_register_device ().
The "inverse function" of uart_add_one_port () is uart_remove_one_port (), where tty_unregister_device () is called, and the prototype is:
Int uart_remove_one_port (struct uart_driver * DRV, struct uart_port * port );
Although the uart_info member of uart_port does not need to be processed in the driver, the data from the user is stored in xmit (circ_buf, I .e. the ring buffer area) during transmission, therefore, when the UART driver sends data (generally in the sending interrupt handler), it needs to obtain the upper-layer characters from the circ_buf.
3. uart_ops
Uart_ops defines a series of operations for UART, including sending, receiving, and line settings. If the tty_operations in tty_driver are abstract to the serial port, uart_ops is directly oriented to the serial port UART, its definition is shown in code list 14.16. This level of Linux driver is very similar to the relationship between classes and derived classes in object-oriented programming. The Derived classes are more specific to specific things, while the base classes are at a higher abstraction level.
Code List 14.16 uart_ops struct
1 struct uart_ops
2 {
3 unsigned int (* tx_empty) (struct uart_port *);
4 void (* set_mctrl) (struct uart_port *, unsigned int mctrl );
5 unsigned int (* get_mctrl) (struct uart_port *);
6 void (* stop_tx) (struct uart_port *); // stop sending
7 void (* start_tx) (struct uart_port *); // start sending
8 void (* send_xchar) (struct uart_port *, char ch); // send xchar
9 void (* stop_rx) (struct uart_port *); // stop receiving
10 void (* enable_ms) (struct uart_port *);
11 void (* break_ctl) (struct uart_port *, int CTL );
12 INT (* startup) (struct uart_port *);
13 void (* shutdown) (struct uart_port *);
14 void (* set_termios) (struct uart_port *, struct termios * New, struct termios
15 * Old); // set termios
16 void (* PM) (struct uart_port *, unsigned int state, unsigned int oldstate );
17 int (* set_wake) (struct uart_port *, unsigned int State );
18
19/* return 1 string describing the port type */
20 const char * (* type) (struct uart_port *);
21
22/* release the IO and memory resources used by the port. If necessary, perform the iounmap operation */
23 void (* release_port) (struct uart_port *);
24/* IO and memory resources used by the Applied port */
25 int (* request_port) (struct uart_port *);
26
27 void (* config_port) (struct uart_port *, INT );
28 int (* verify_port) (struct uart_port *, struct serial_struct *);
29 int (* IOCTL) (struct uart_port *, unsigned int, unsigned long );
30 };
Serial_core.c defines tty_operations instances, including uart_open (), uart_close (), uart_write (), uart_send_xchar () and other member functions (such as code list 14.17 ), these functions use the member functions in the uart_ops struct to perform specific operations. In code list 14.18, The uart_send_xchar () member functions of tty_operations use start_tx () and send_xchar () in uart_ops () example of a member function.
Code List 14.17 tty_operations instance of the serial port core layer
1 static struct tty_operations uart_ops =
2 {
3. Open = uart_open, // open the serial port
4. Close = uart_close, // close the serial port
5. Write = uart_write, // serial port sending
6. put_char = uart_put_char ,//...
7. flush_chars = uart_flush_chars,
8. write_room = uart_write_room,
9. chars_in_buffer = uart_chars_in_buffer,
10. flush_buffer = uart_flush_buffer,
11. IOCTL = uart_ioctl,
12. Throttle = uart_throttle,
13. unthrottle = uart_unthrottle,
14. send_xchar = uart_send_xchar,
15. set_termios = uart_set_termios,
16. Stop = uart_stop,
17. Start = uart_start,
18. hangup = uart_hangup,
19. break_ctl = uart_break_ctl,
20. wait_until_sent = uart_wait_until_sent,
21 # ifdef config_proc_fs
22. read_proc = uart_read_proc, // READ function of the proc entry
23 # endif
24. tiocmget = uart_tiocmget,
25. tiocmset = uart_tiocmset,
26 };
Code List 14.18 relations between tty_operations and uart_ops at the serial port core layer
1 static void uart_send_xchar (struct tty_struct * tty, char ch)
2 {
3 struct uart_state * State = tty-> driver_data;
4 struct uart_port * Port = state-> port;
5 unsigned long flags;
6 // If the send_xchar member function is implemented in uart_ops
7 if (Port-> OPS-> send_xchar)
8 port-> OPS-> send_xchar (port, CH );
9 else // The send_xchar member function is not implemented in uart_ops
10 {
11 port-> x_char = CH; // xchar value assignment
12 if (CH)
13 {
14 spin_lock_irqsave (& Port-> lock, flags );
15 port-> OPS-> start_tx (port); // send xchar
16 spin_unlock_irqrestore (& Port-> lock, flags );
17}
18}
19}

Note: The entire call process is: the system calls write ()-> uart_write () (tty_driver)-> port-> OPS-> start_tx ();
After using the interface of the Universal Serial Port tty driver layer in the serial port core layer, the main tasks of a serial port driver include:
• Defines instances of uart_driver, uart_ops, uart_port, and other struct types, and initializes them according to the specific hardware and driver conditions where appropriate, of course, the driver of the specific device xxx can set these structures in the newly defined xxx_uart_driver, xxx_uart_ops, and xxx_uart_port.
• During module initialization, uart_register_driver () and uart_add_one_port () are called to register the UART driver and add ports. When the module is uninstalled, uart_unregister_driver () and uart_remove_one_port () are called () to log out of the UART driver and remove the port.
• Implement uart_ops member functions based on the datasheet of specific hardware. The implementation of these functions becomes the main task of UART driver.

 

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/dongliqiang2006/archive/2009/09/09/4536293.aspx

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.