当前位置:网站首页>11、 UART & TTY driver

11、 UART & TTY driver

2021-01-23 20:25:55 itread01

  Linux In the system UART Drive and TTY There is a close relationship between the two , They don't look like I2C and SPI The driver is a single module , We should analyze them as a whole .UART The driver part depends on the hardware platform , and TTY The driver has nothing to do with the specific platform . The analysis of this paper is based on IMX6DL Hardware platform and Kernel 3.0.35 edition , Although UART Part of it depends on the platform , But no matter which hardware platform , The driving ideas are the same , The following is divided into modules to introduce .

One 、UART Drive

UART The main driver files involved in driver are imx.c、serial_core.c Two files . First, we find the entry function of the driver module_init(imx_serial_init), In the function imx_serial_init Call me uart_register_driver Registered a driver with the core , In this function, in addition to the routine initialization drive , There are two key points of function calls that we need to pay attention to , Here's the picture :

 

First, the call tty_set_operations Will uart_ops This one tty The operation function set of the device is set to tty Driving , Call at the same time tty_register_driver The function is registered with the core tty Drive , among uart_ops The data types and contents of are as follows :

 

 

When calling tty_open Function will call here uart_open, How to call , We'll analyze it later .imx_serial_init It also calls platform_driver_register Registered a platform device with the core , therefore UART Drivers are both platform devices and character devices . When the drive matches the device, it calls serial_imx_probe Function , In this function, in addition to specific platform related serial port settings , For example, call platform_get_resource Get interrupt resources , Assignment sport->timer.functioni = mx_timeout Set the timer , Another key operation is sport->port.ops = &imx_pops, Assigned the underlying operation function of the specific hardware platform , Among them imx_pops The structure is as follows :

 

 

 

The functions in this architecture are all related to the specific hardware platform , Data receiving of serial port 、 Register interrupt receive function 、 Use DMA Receiving data and other operations are completed in the above function , These functions are constructed by NXP Official supply , Is the closest function to the underlying hardware .

Just like other drivers , When the serial port device is turned on ,uart_open Function gets the call , stay tty_open The function calls uart_startup Function to start the serial port , as follows :

 

 

stay uart_startup In a function, by uport->ops->startup(uport); Indirect call to imx_startup Function , Because we've passed ahead sport->port.ops = &imx_pops The serial port function of the related hardware platform is assigned to the abstract serial port function , So here we turn to analysis imx_startup Look what's going on inside .

stay imx_startup By calling request_irq(sport->rxirq, imx_rxint, 0, DRIVER_NAME, sport) Registered serial port interrupt receive function imx_rxint, The serial port interrupt send function is the same , At the same time, if the board level file is set to enable DMA, Also initialized for DMA Data processing related work queues , Here's the picture :

 

 

We are not configured to use DMA, So only the interrupt receive function is analyzed imx_rxint.Imx_rxint The function is as follows :

 

 

 

 

imx_rxint Function reads the value of the data register in the loop , And call two key functions at the end of the function , The difference is tty_insert_flip_char(tty, rx, flg) and tty_flip_buffer_push(tty), among tty_insert_flip_char The function puts the received character into tty In block , Here's the picture :

 

 

and tty_flip_buffer_push(tty) It's going to be tty The data of data block is pushed into the line regulation , We will talk about the related knowledge of the line regulation later , This function is similar to notification tty Go to the line procedure to get the data from the serial port , The function is as follows :

 

 

One of the key operations is to call the work queue , When is the work queue registered or initialized , We'll talk about it later tty When will we analyze . To sum up , If only tty_insert_flip_char In the case of a function ,tty There is no way to get serial port data , You have to use tty_flip_buffer_push Function to push the data into the line specification . thus ,UART To TTY This is the end of our analysis , Next, analyze TTY Framework .

One 、TTY Drive

TTY The driver does not depend on the specific hardware platform , The main files involved are tty_io.c、tty_ldisc.c.TTY The driver framework contains a core module called circuit protocol ,TTY The driver cannot be driven directly from UART Access to information , All information must be obtained from ldisc( Line procedure acquisition ). First let's look at tty Related initialization , Register before UART When driving , At the same time called tty_register_driver(normal) Function registers a tty Drive , In this function... Is called cdev_init(&driver->cdev, &tty_fops), Bound to the device tty The set of operating functions of the device ,tty_fops The data type of is struct file_operations, The variable is shown in the figure below :

 

 

So when the application layer turns on a tty When the device calls... In this function set tty_open Function , Next let's look at tty_open What's in the function . stay tty_open Call... In the function tty_init_dev(driver, index, 0) Function pair tty The device is initialized , stay tty_init_dev The function calls again initialize_tty_struct(tty, driver, idx) Function pair tty The related structure is initialized , As shown in the figure below :

 

 

There are three areas that we need to focus on , The first is tty_ldisc_init(tty), Call this function to complete the initialization of the line procedure , stay tty_ldisc_init In this function, we call tty_ldisc_get Get the line protocol , stay tty_ldisc_get Function by calling get_ldops(disc) Get the operation function of the line regulation , As shown in the figure :

 

 

 

 

 

 

among tty_ldiscs It's a global array , The array element type is struct tty_ldisc_ops, That is, the set of operation functions of the line rules , The type is shown in the figure below :

 

 

When is the operation function of the line procedure initialized , We'll analyze it later .

         stay initialize_tty_struct The second function call we need to focus on is tty_buffer_init(tty),,

Calling the function is complete tty Block related initialization , As shown in the figure below :

 

 

A work queue is also initialized in the initialization function ,INIT_WORK(&tty->buf.work, flush_to_ldisc).

When is this work queue called ? It's just in front of us imx_rxint When the receive function is interrupted , Calling tty_flip_buffer_push, In this function, through schedule_work(&tty->buf.work) The work queue is scheduled . thus ,TTY And also UART I got in touch with .

stay initialize_tty_struct What we need to focus on in the function is tty->ops = driver->ops Sentence . Previously, we analyzed that , Call when serial port is registered tty_set_operations Function , Through driver->ops = op Will tty Is assigned to uart Drive , Here, we take out the registered function and assign it to tty Device , It's an application layer operation tty Device is operation uart Serial port . stay tty_init_dev In function , In addition to initialization tty Outside the device , And call tty_ldisc_setup(tty, tty->link) The function sets the line regulation . stay tty_ldisc_setup The function calls tty_ldisc_open Function , In this function, we use ld->ops->open(tty) It turns on the line protocol , But where is the assignment of the operation function of the line regulation ? Keep the question , Next, we analyze the initialization process related to the line protocol .

Remember the global array we mentioned earlier tty_ldiscs Do you ? The element type of this array is the operation function of the circuit specification . We do a global search in the core code , Found in tty_register_ldisc It is set in the function , Here's the picture :

 

 

If you call this function , It will set the line protocol to the global array tty_ldiscs in , So tty_register_ldisc Where is the function called ? The answer is , stay tty_ldisc_begin Function is called , Here's the picture :

 

 

and tty_ldisc_N_TTY The variable is the operation function of the line procedure , Variable assignment is shown in the figure below :

 

 

tty_ldisc_begin This function is called console_init call , Then who's calling again console_init Well ? The answer is /init/main.c In Archives ,asmlinkage void __init start_kernel(void) The function called console_init. and start_kernel Function is the core entry function . That is to say , When it comes to the core , It's initialized the first time tty The line rules of the company , The related operation functions of the line regulation are assigned . Where is the operation function of the line procedure called ?

         We talked about ,tty The driver cannot get data directly from the serial port , The source of the data is the route regulation , Then the read-write function of call line protocol can only be tty Operation function of , So let's take a look at things that have never been analyzed before tty_read and tty_write Function . Let's start with tty_read Function , Here's the picture :

 

 

Sure enough , stay tty_read Medium pass ld->ops->read Calling the line protocol read Function , That's the call tty_ldisc_N_TTY Of ntty_read Function . Let's see tty_write Function , Here's the picture :

 

 

It's the same call to the line protocol n_tty_write Function .

To sum up , When it comes to the core , The first is to set the operation function of the line regulation , And then in tty When the driver registered, it was set tty Operation function of , And turn it on later tty Call when the device is on tty_open Function , stay open In a function, by get_ldops(disc) Get the operation function of the line regulation . When the application layer calls tty_read When I read the data, I called n_tty_read Got a number of

版权声明
本文为[itread01]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/01/20210123202442237p.html

随机推荐