Arm driver basics: poll mechanism implementation process

Source: Internet
Author: User

Poll Function

The poll function originated from SVR3 and was initially confined to stream devices. SVR4 removes this restriction and allows poll to work on any descriptive word. Poll provides similar functions as select, but it can provide additional information when processing stream devices.

1. # include <poll. h>

2. int poll (struct pollfd * fdarray, unsigned long nfds, int timeout );

3. Return: Number of ready descriptors, 0-Timeout,-1-Error

The first parameter is a pointer to the first element of a structure array. Each array element is a pollfd structure used to specify conditions for testing a specified describe fd.

Struct pollfd {

Int fd; // descriptor to check

Short events; // events of interest on fd

Short revents; // events that occurred on fd

};

The conditions to be tested are specified by the events member, and the returned results are stored in revents. Common conditions and meanings are described as follows:

Available poll function test values

Constant Description
POLLIN Normal or priority with data readable
POLLRDNORM Common Data readable
POLLRDBAND Data Reading with priority
POLLPRI High-priority data readable
POLLOUT Common Data writable
POLLWRNORM Common Data writable
POLLWRBAND Data with writable priority
POLLERR Error occurred
POLLHUP Suspended
POLLNVAL The description is not an open file.

 

Note: The last three returned results can only be stored in revents as descriptive words, but cannot be used as test conditions in events.

The second parameter nfds is used to specify the length of the fdarray.

The last timeout parameter specifies the waiting time before the poll function returns. The value is as follows:

 

Timeout value Description
INFTIM Always wait
0 Return immediately without blocking the process
> 0 Number of milliseconds to wait for a specified number

 

 

Poll function call and kernel implementation process:

The kernel function do_pollfd (pfd, pt) calls the poll function in the driver. if the poll function in the driver returns 0, the kernel will execute the if () statement to determine whether to jump out, run schedule_timeout (_ timeout) to sleep the process for five seconds. If the process is interrupted within these five seconds, run the interrupt function to wake up the process (wait_event_interruptible (button_irq, ev_press) in the read function )), after the read function in the driver is executed, return to the application to continue running.

 

Driver code:

 

Forth_drv.c

# Include <linux/module. h> # include <linux/kernel. h> # include <linux/fs. h> # include <linux/init. h> # include <linux/delay. h> # include <linux/irq. h> # include <asm/uaccess. h> # include <asm/irq. h> # include <asm/io. h> # include <asm/arch/regs-gpio.h> # include <asm/hardware. h> # include <linux/poll. h> static struct class * forthdrv_class; static struct class_device * forthdrv_class_dev; volatile unsigned long * gpfcon; volat Ile unsigned long * gpfdat; volatile unsigned long * gpgcon; volatile unsigned long * gpgdat; static DECLARE_WAIT_QUEUE_HEAD (button_waitq);/* indicates the interrupt event. The interrupt service sets it to 1, forth_drv_read clears it 0 */static volatile int ev_press = 0; struct pin_desc {unsigned int pin; unsigned int key_val;};/* key value: 0x01 when pressed, 0x02, 0x03, 0x04 * // * key value: 0x81, 0x82, 0x83, 0x84 */static unsigned char key_val; struct pin_desc pins_desc [4] = {S3C2410_GPF0, 0x01}, {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x03}, {S3C2410_GPG11, 0x04 },}; /** determine the key value */static irqreturn_t buttons_irq (int irq, void * dev_id) {struct pin_desc * pindesc = (struct pin_desc *) dev_id; unsigned int pinval; pinval = s3c2410_gpio_getpin (pindesc-> pin); if (pinval) {/* release */key_val = 0x80 | pindesc-> key_val ;} else {/* press */key_val = pindesc-> key_val;} ev_press = 1; /* Indicates that */wake_up_interruptible (& button_waitq) is interrupted;/* wake up the sleep process */return IRQ_RETVAL (IRQ_HANDLED);} static int forth_drv_open (struct inode * inode, struct file * file) {/* configure GPF0, 2 for the input pin * // * configure GPG3, 11 for the input pin */request_irq (IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2 ", & pins_desc [0]); request_irq (response, buttons_irq, IRQT_BOTHEDGE, "S3", & pins_desc [1]); request_irq (IRQ_EINT11, buttons_irq, IRQT_BOTHE DGE, "S4", & pins_desc [2]); request_irq (IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", & pins_desc [3]); return 0 ;} ssize_t forth_drv_read (struct file * file, char _ user * buf, size_t size, loff_t * ppos) {if (size! = 1) return-EINVAL;/* if there is no button action, sleep */wait_event_interruptible (button_waitq, ev_press);/* if there is a button action, return the key value */copy_to_user (buf, & key_val, 1); ev_press = 0; return 1;} int forth_drv_close (struct inode * inode, struct file * file) {free_irq (IRQ_EINT0, & pins_desc [0]); free_irq (IRQ_EINT2, & pins_desc [1]); free_irq (IRQ_EINT11, & pins_desc [2]); free_irq (IRQ_EINT19, & pins_desc [3]); return 0 ;} static unsigned forth_drv_poll (struct file * file, poll_table * wait) {unsigned int mask = 0; poll_wait (file, & button_waitq, wait); // does not sleep immediately if (ev_press) mask | = POLLIN | POLLRDNORM; return mask;} static struct file_operations sencod_drv_fops = {. owner = THIS_MODULE,/* This is a macro. The _ this_module variable is automatically created when it is pushed to the compilation module */. open = forth_drv_open ,. read = forth_drv_read ,. release = forth_drv_close ,. poll = example,}; int major; static int forth_drv_init (void) {major = example (0, "forth_drv", & sencod_drv_fops); forthdrv_class = class_create (THIS_MODULE, "forth_drv"); forthdrv_class_dev = class_device_create (forthdrv_class, NULL, MKDEV (major, 0), NULL, "buttons "); /*/dev/buttons */gpfcon = (volatile unsigned long *) ioremap (0x56000050, 16); gpfdat = gpfcon + 1; gpgcon = (volatile unsigned long *) ioremap (0x56000060, 16); gpgdat = gpgcon + 1; return 0;} static void forth_drv_exit (void) {Merge (major, "forth_drv"); class_device_unregister (Register ); class_destroy (forthdrv_class); iounmap (gpfcon); iounmap (gpgcon); return 0;} module_init (modules); module_exit (forth_drv_exit); MODULE_LICENSE ("GPL ");

 

 

Application code:

Forthdrvtest. c

#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <poll.h>/* forthdrvtest   */int main(int argc, char **argv){    int fd;    unsigned char key_val;    int ret;    struct pollfd fds[1];        fd = open("/dev/buttons", O_RDWR);    if (fd < 0)    {        printf("can't open!\n");    }    fds[0].fd     = fd;    fds[0].events = POLLIN;    while (1)    {        ret = poll(fds, 1, 5000);        if (ret == 0)        {            printf("time out\n");        }        else        {            read(fd, &key_val, 1);            printf("key_val = 0x%x\n", key_val);        }    }        return 0;}

 

 

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.