Serial Port driver in Linux

Source: Internet
Author: User

 
After reading the serial port driver for two days, I finally watched the driver of a great god. I wanted to write a blog by myself and suddenly found that it was also the content of the great god, so repost it. Address: http://blog.csdn.net/wulong117/article/details/7378265

The serial port driver is really not simple, but it is easy to clarify the overall thinking.

The original article is as follows:

I. Core Data Structure the serial port driver has three core data structures, they are all defined in <# include Linux/serial_core.h> 1. uart_driveruart_driver contains information such as the serial device name, serial driver name, Primary and Secondary device number, and serial console (optional, tty_driver is also encapsulated (the underlying serial driver does not need to care about tty_driver ). Struct uart_driver {struct module * owner;/* module that owns the uart_driver, which is generally this_module */const char * driver_name;/* serial port driver name, the name of the serial device file is base */const char * dev_name;/* serial device name */INT Major;/* main device Number */INT minor; /* Device Number */int nr;/* Number of serial ports supported by uart_driver (max) */struct console * cons;/* corresponding console. if the uart_driver supports the serial console, otherwise it is null * // ** these are private; the low level driver shoshould not * touch these; th Ey shoshould be initialised to null */struct uart_state * State; struct tty_driver * tty_driver ;}; 2. uart_portuart_port describes the I/O port or I/O memory address, FIFO size, port Type, serial clock, and other information of the serial port. In fact, a uart_port instance corresponds to a serial port device struct uart_port {spinlock_t lock;/* serial port lock */unsigned int iobase; /* IO port base address */unsigned char _ iomem * membase;/* IO memory base address, Io memory virtual base address after ing (such as ioremap) */unsigned int IRQ; /* interrupt Number */unsigned int uartclk;/* serial clock */unsigned int serial osize;/* serial FIFO buffer size */unsigned char x_char; /* Xon/xoff character */unsigned char regshift;/* Register shift */unsigned char iotype;/* IO access mode */unsigned ch Ar unused1; # define upio_port (0)/* IO port */# define upio_hub6 (1) # define upio_mem (2)/* IO memory */# define upio_mem32 (3) # define upio_au (4)/* au1x00 type Io */# define upio_tsi (5)/* tsi108/109 type Io */# define upio_dwapb (6) /* designware apb uart */# define upio_rm9000 (7)/* rm9000 type Io */unsigned int read_status_mask;/* RX error status */unsigned int ignore_status_mask; /* ignored RX error St ATUS */struct uart_info * Info;/* pointer to parent info */struct uart_icount icount;/* counter */struct console * cons; /* console struct */# ifdef config_serial_core_console unsigned long sysrq;/* sysrq timeout */# endif upf_t flags; # define upf_fourport (_ force upf_t) (1 <1) # define upf_sak (_ force upf_t) (1 <2) # define upf_spd_mask (_ force upf_t) (0x1030 )) # define upf_spd_hi (_ force upf_t) (0x0010) # define upf_spd_vhi (_ force upf_t) (0x0020) # define upf_spd_cust (_ force upf_t) (0x0030 )) # define upf_spd_shi (_ force upf_t) (0x1000) # define upf_spd_warp (_ force upf_t) (0x1010 )) # define upf_skip_test (_ force upf_t) (1 <6) # define upf_auto_irq (_ force upf_t) (1 <7 )) # define upf_hardpps_cd (_ force upf_t) (1 <11) # define upf_low_latency (_ force upf_t) (1 <13) # define Upf_buggy_uart (_ force upf_t) (1 <14) # define upf_magic_multiplier (_ force upf_t) (1 <16 )) # define upf_cons_flow (_ force upf_t) (1 <23) # define upf_1__irq (_ force upf_t) (1 <24 )) # define upf_boot_autoconf (_ force upf_t) (1 <28) # define upf_fixed_port (_ force upf_t) (1 <29 )) # define upf_dead (_ force upf_t) (1 <30) # define upf_ioremap (_ force upf_t) (1 <31) # define up F_change_mask (_ force upf_t) (0x17fff) # define upf_usr_mask (_ force upf_t) (upf_spd_mask | upf_low_latency) unsigned int mctrl; /* Current moden settings */unsigned int timeout;/* character-Based Timeout */unsigned int type;/* port type */const struct uart_ops * OPS; /* serial port operation function set */unsigned int custom_divisor; unsigned int line;/* port Index */resource_size_t mapbase;/* IO memory physical base address, available for ioremap */struct device * Dev;/* parent device */unsigned char hub6;/* This shoshould be In the 8250 driver */unsigned char suincluded; unsigned char unused [2]; void * private_data; /* port private data, usually the Platform Data Pointer */}; uart_iconut is the serial port information counter, including the sending Character Count and receiving Character Count. In the serial sending interrupt handler and receiving interrupt handler, we need to manage these counts. Struct uart_icount {_ u32 CTS; _ u32 DSR; _ u32 RNG; _ u32 DCD; _ u32 RX;/* Sending Character Count */_ u32 TX; /* accept Character Count */_ u32 frame;/* frame error count */_ u32 overrun;/* rx fifo overflow count */_ u32 parity; /* frame verification error count */_ u32 BRK;/* break count */_ u32 buf_overrun;}; two uart_info members are used in the underlying serial port driver: xmit and TTY. When a user space program sends data through the serial port, the upper-layer driver saves the user data in xmit, And the interrupt processing function of the serial port sends the user data through xmit and sends them out. The serial port receiving interrupt processing function must pass the received data to the row rule layer through TTY. /* The uart_info instance is valid only when the serial port is opened. It may be released by the serial port core layer when the serial port is closed. Therefore, when using uart_port's uart_info member, you must ensure that the serial port is enabled. Both the underlying driver and the core driver can modify the uart_info instance. * This is the State information which is only valid when the port * is open; it may be freed by the core driver once the device has * been closed. either the low level driver or the core can modify * stuff here. */struct uart_info {struct tty_struct * tty; struct circ_buf xmit; uif_t flags;/** definitions for Info-> flags. these are _ private _ to serial_core, and * are specific to this structure. t Hey may be queried by low level drivers. */# define uif_check_cd (_ force uif_t) (1 <25) # define uif_cts_flow (_ force uif_t) (1 <26 )) # define uif_normal_active (_ force uif_t) (1 <29) # define uif_initialized (_ force uif_t) (1 <31 )) # define uif_suincluded (_ force uif_t) (1 <30) int blocked_open; struct tasklet_struct tlet; wait_queue_head_t open_wait ;}; 3. uart_opsuart_ops covers all operations that a serial driver can perform on a serial device. /** This structure describes all the operations that can be * done on the physical hardware. */struct uart_ops {unsigned int (* tx_empty) (struct uart_port *);/* Whether the Tx FIFO cache of the serial port is empty */void (* set_mctrl) (struct uart_port *, unsigned int mctrl);/* Set serial modem control */unsigned int (* get_mctrl) (struct uart_port *);/* Get serial modem control */void (* stop_tx) (struct uart_port *);/* disable serial port sending data */void (* start_tx) (struct Uart_port *);/* enable the serial port to send data */void (* send_xchar) (struct uart_port *, char ch);/* Send xchar */void (* stop_rx) (struct uart_port *);/* disable serial port to receive data */void (* enable_ms) (struct uart_port *);/* enable modem Status Signal */void (* break_ctl) (struct uart_port *, int CTL);/* set the break signal */INT (* startup) (struct uart_port *);/* Start the serial port. When the application opens the serial port device file, this function will be called */void (* shutdown) (struct uart_port *);/* When the application closes the serial port device file, this function will be called Use */void (* set_termios) (struct uart_port *, struct ktermios * New, struct ktermios * Old);/* Set serial port parameters */void (* pm) (struct uart_port *, unsigned int state, unsigned int oldstate);/* serial port power management */INT (* set_wake) (struct uart_port *, unsigned int State ); /**/const char * (* type) (struct uart_port *);/* returns a string describing the serial port type */void (* release_port) (struct uart_port *); /* release the IO port/IO memory resources applied by the serial port. If necessary, you must use iounmap */INT (* Request_port) (struct uart_port *);/* apply for necessary IO port/IO memory resources, and re-map the serial port */void (* config_port) (struct uart_port *, INT);/* automatically configure the serial port */INT (* verify_port) (struct uart_port *, struct serial_struct *); /* verify the information of the new serial port */INT (* IOCTL) (struct uart_port *, unsigned int, unsigned long);/* IO control */}; ii. Serial Port driver api1 and uart_register_driver/* functions: uart_register_driver is used to register the serial port driver uart_driver to the kernel (Serial Port core layer). This function is usually called in the module initialization function. * Parameter DRV: uart_driver to be registered * return value: Success, return 0; otherwise Return Error Code */INT uart_register_driver (struct uart_driver * DRV) 2. uart_unregister_driver/* function: uart_unregister_driver is used to deregister the uart_driver we have registered. Normally, the module uninstalls the function and calls this function * parameter DRV: uart_driver to be deregistered * return value: Success, return 0; otherwise, the error code */void uart_unregister_driver (struct uart_driver * DRV) is returned. 3. uart_add_one_port/* function: uart_add_one_port is used to add a serial port to the serial port driver, this function is usually called after a device is detected (the probe method of the driver) * parameter DRV: serial port driver * Port: Serial port to be added * return value: Success, return 0; otherwise Return Error Code */INT uart_add_one_port (struct uart_driver * DRV, struct uart_port * port) 4, uart_remove_one_port/* function: uart_remove_one_port is used to delete a serial port that has been added to the serial driver. Generally, this function * parameter DRV: serial driver * port: serial port to be deleted * returned value: success, returns 0; otherwise, returns the error code */INT uart_remove_one_port (struct uart_driver * DRV, struct uart_port * port) 5, uart_write_wakeup: uart_write_wakeup is used to wake up the process that is blocked by writing data to the serial port. This function is usually called in the interrupt processing function sent by the serial port. * Parameter port: the serial port of the write blocking process */void uart_write_wakeup (struct uart_port * port) 6. uart_suspend_port/* function: uart_suspend_port is used to suspend a specific serial port * parameter DRV: serial driver * port: serial port to be suspended * return value: 0 if the port is successfully returned; otherwise, the error code */INT uart_suspend_port (struct uart_driver * DRV, struct uart_port * port) 7. uart_resume_port/* function: uart_resume_port is used to restore a suspended serial port * parameter DRV: the serial port driver of the serial port to be recovered * Port: serial port to be restored * return value: 0 for success; otherwise Return Error Code */INT uart_resume _ Port (struct uart_driver * DRV, struct uart_port * port) 8. uart_get_baud_rate/* function: uart_get_baud_rate obtains the baud rate of the specified serial port by decoding the termios struct. * parameter Port: the serial port * termios: The current expected termios configuration (including the serial port baud rate) * Old: the previous termios configuration, which can be null * min: acceptable minimum baud rate * max: acceptable maximum baud rate * returned value: Serial Port baud rate */unsigned intuart_get_baud_rate (struct uart_port * port, struct ktermios * termios, struct ktermios * old, unsigned int min, unsigned int max) 9. uart_get_divisor/* function: uart_get_divisor is used to calculate the serial clock frequency (in addition to the serial baud rate) of a certain baud rate. * parameter port: the serial port for calculating the clock frequency * Baud: expected baud rate * return value: serial clock frequency */unsigned int uart_get_divisor (struct uart_port * port, unsigned int baud) 10, uart_update_timeout/* function: uart_update_timeout is used for update (setting) serial FIFO timeout * parameter port: serial port to update the timeout * cflag: cflag value of the termios struct * Baud: Serial Port baud rate */void uart_update_timeout (struct uart_port * port, unsigned int cflag, UN Signed int baud) 11, uart_match_port/* function: uart_match_port is used to determine whether the two serial ports are the same * parameter port1, port2: the serial port to be judged * return value: different return 0; otherwise, a non-0 */INT uart_match_port (struct uart_port * port1, struct uart_port * port2) 12, uart_console_write/* function is returned. uart_console_write is used to write console information to the serial port: serial Port ** S: Information to be written * count: Information size * putchar: A function used to write characters to a serial port. This function has two parameters: serial Port and character to be written */void uart_console_write (struct uart_port * port, const Char * s, unsigned int count, void (* putchar) (struct uart_port *, INT )) iii. Serial Port driver example this serial port driver example is developed independently for the serial port 2 (uart2) of the S3C2410 processor. Because I tested the driver through the GRPS expansion board of the 2410s Development Board of botron (the driver has passed the test), so I called the serial port to be the gps_uart. The driver regards the serial port as a platform device. Platform can be viewed as a pseudo-bus used to associate lightweight devices integrated into the on-chip system with the driver model of Linux devices, it contains the following two parts (the declarations about platform are in # include <Linux/platform_device.h>. The specific implementation is in drivers/base/platform. c): 1. platform device. We need to define a platform_device instance struct platform_device {const char * Name;/* device name */int id;/* device ID */struct device Dev for each device; /* Device */u32 num_resources;/* Number of resources used by the device */struct resource * resource;/* Resource array */}; there are two ways to create a platform_device instance for our device: Fill in a platform_device struct and use platform_device_register (register one at a time) or platform_add_devices (register multiple platform devices at a time) register platform_device to the kernel. More simply, use platform_device_register_simpl E to create and register our platform_device. 2. Platform driver. The platform device is managed by the platform driver. When the device is added to the system, the probe method of platform_driver will be called to see that the corresponding device is added or registered to the kernel. when the device is removed from the system, the Remove Method of platform_driver is called for cleanup, such as removing some instances of the device and canceling some items that have been registered in the system. Struct platform_driver {int (* probe) (struct platform_device *); int (* remove) (struct platform_device *); void (* shutdown) (struct platform_device *); INT (* suspend) (struct platform_device *, pm_message_t State); int (* suspend_late) (struct platform_device *, destination State); int (* resume_early) (struct platform_device *); INT (* resume) (struct platform_device *); struct device_driver driver;}; more details For more information about platform, see related online articles. The entire process of applying for and releasing the I/O memory zone in the example driver is as follows: insmod upls_uart.ko → GPRS _ init_module () → reset () → GPRS _ uart_probe () → reset () → maid () → request_mem_region () rmmod maid () → uart_unregister_driver () → maid () → example () → release_mem_region () the entire process of applying for and releasing IRQ Resources in the example driver is as follows: Open/dev/upls_uart → upls_uart_startup () → request_irq () Close/dev/upls_uart → upls_uart_shutdown () → free_irq ()

 


 

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.