Kobox:key_wq.c-v1 How to use the work queue Workqueue

Source: Internet
Author: User

Kobox:key_wq.c-v1

Description

TQ2440 main drivers, four key-driven handling

KEY_WQ.C and Key.c categories are similar, with the main driving force of the difference between KEY.C:

The KEY.C uses a timer to prevent key jitter when the interrupt occurs with a 100ms call to the timer handler function

KEY_WQ.C Use the Task Force column. Schedule shared work queues in the kernel, delay 100ms in the work queue, and infer key state to prevent key jitter


Problem:

Only the kernel shares the work queue and does not delay the case. The program will run normally:

/* Use the kernel Shared Queue to dispatch immediately. Delay put in the interrupt function */
Schedule_work (&gpio_key_work[key]);//normal operation


Use three other cases. The program will be blown off:

/* Use kernel Shared Queue, delay schedule */
schedule_delayed_work (&gpio_key_work[key], key_timer_delay2);//Will Oops


/* Use a separate queue. Delay Scheduling */
queue_delayed_work (&key_wq[key], &gpio_key_work[key], key_timer_delay2);//the same collapse!


/* Use a kernel Shared queue. Dispatch immediately, delay put into the interrupt function */
queue_work (&key_wq[key], &gpio_key_work[key]);//the same collapse!

It's not clear why now.


Source code such as the following:

#include "key.h" #define S3c_addr_base0xf6000000#define s3c_addr (x) (S3c_addr_base + (x)) #define S3C2410_PA_UART ( 0x50000000) #define S3C2410_PA_GPIO (0x56000000) #define S3C_VA_UARTS3C_ADDR (0x01000000)/* UART */#define S3c24xx_pa_ Uarts3c2410_pa_uart#define S3c24xx_va_uarts3c_va_uart#define S3c24xx_pa_gpios3c2410_pa_gpio#define S3C24XX_VA_ GPIO ((S3c24xx_pa_gpio-s3c24xx_pa_uart) + s3c24xx_va_uart) #define S3C2410_GPIOREG (x) ((x) + S3c24xx_va_gpio) #define S3c2410_gpbcon S3c2410_gpioreg (0x10) #define S3c2410_gpbdat s3c2410_gpioreg (0x14) #define S3C2410_GPBUP S3c2410_gpior EG (0x18) #define S3c2410_gpfcon s3c2410_gpioreg (0x50) #define S3c2410_gpfdat s3c2410_gpioreg (0x54) #define S3c2410_ Gpfup S3c2410_gpioreg (0x58) #define S3C2410_EXTINT0 s3c2410_gpioreg (0x88) #define S3C2410_EXTINT1 S3c2410_gpioreg (0x8 C) #define S3C2410_EXTINT2 s3c2410_gpioreg (0x90) #define S3C2410_CPUIRQ_OFFSET (+) #define S3C2410_IRQ (x) ((x) + s3c2410 _CPUIRQ_OFFSET)/* Main CPU Interrupts */#define IRQ_EINT0 s3c2410_IRQ (0)/*/#define IRQ_EINT1 S3C2410_IRQ (1)/* */#define IRQ_EINT2 S3C2410_IRQ (2)/*/#define Irq_e Int4t7 S3C2410_IRQ (4)/*/#define IRQ_EINT4 S3C2410_IRQ (+)//*/#define Irqf_disabled0x00000020#defin E irqf_shared0x00000080#define irqf_probe_shared0x00000100#define __irqf_timer0x00000200#define IRQF_ Percpu0x00000400#define Irqf_nobalancing0x00000800#define Irqf_irqpoll0x00001000#define IRQF_ONESHOT0x00002000# Define Irqf_no_suspend0x00004000#define irqf_force_resume0x00008000#define Irqf_no_thread0x00010000#define IRQF_ early_resume0x00020000typedef struct Gpiores{int irqnum;/* interrupt number */unsigned int ctrlreg;/* control register for setting multiplexing as Gpio */unsigned int ctrlbit; /* Which one of the control registers, used to reuse as Gpio */unsigned int trigreg;/* interrupt mode register. Set how interrupts are triggered */unsigned int trigbit;/* interrupt mode register which one, set the triggering mode of the interrupt */unsigned int irqflag;/* shared or not shared, register interrupted flag */char irqname[32] */* Break name */unsigned int gpfpin;/* gpf pin */char reserved[10];/* reserved */}gpiores; #define ARRAY_SIZE (arr) (sizeof (ARR)/si Zeof(arr) [0]) unsigned int presscnt[4] = {0, 0, 0, 0};/* defines a work_queue array */struct work_struct gpio_key_work[4];static struct WORKQUEUE_ struct *KEY_WQ[4] = {NULL, NULL, NULL, null};static void Gpio_key_wq0_handler (struct work_struct *work), static void Gpio_k Ey_wq1_handler (struct work_struct *work), static void Gpio_key_wq2_handler (struct work_struct *work), static void Gpio_ Key_wq3_handler (struct work_struct *work);/* Defines an array of function pointers that handle the above four Work_queue */int (*gpio_key_wq_handler[4]) (struct Work_struct *work) = {Gpio_key_wq0_handler,gpio_key_wq1_handler,gpio_key_wq2_handler,gpio_key_wq3_handler,}; static int Kobox_key_open (struct inode *inode, struct file *file) {return 0;} static int kobox_key_release (struct inode *inode, struct file *file) {return 0;} Static long kobox_key_ioctl (struct file *file, unsigned int cmd, unsigned long arg) {return 0;} static int kobox_key_read (struct file *file, char __user *buff, size_t count, loff_t *pos) {PRINTK ("Enter [%s][%d]\n", __fu NCTION__,__LINE__); Copy_to_user (bUff, &presscnt[0], sizeof (PRESSCNT)); return 0;} /*GPF Related registers: Gpfcon 0x56000050 r/w Configures the pins of Port F 0x0gpfdat 0x56000054 r/w The data register for Port F Undef . Gpfup 0x56000058 r/w pull-up Disable register for Port F 0x000k1:gpf1-eint1:gpf1 [3:2] xx = Input01 = Output = Eint  [1] one = RESERVEDK2:GPF4-EINT4:GPF4 [9:8] xx = Input01 = Output = eint[4] one = RESERVEDK3:GPF2-EINT2:GPF2 [5:4] xx = Input01 = output = EINT2] one = reservedk4:gpf0-eint0:gpf0 [1:0] = Input01 = output = eint[0] one = Rese  Rved*/gpiores key_gpio_res[4] ={{irq_eint1, S3c2410_gpfcon, 2, S3c2410_extint0, 5, NULL, "Key1", 1},/* key1 */{irq_eint4,  S3c2410_gpfcon, 8, s3c2410_extint0, irqf_shared, Key2, 4},/* key2 */{irq_eint2, S3c2410_gpfcon, 4, S3c2410_extint0, 9, NULL, "Key3", 2},/* Key3 */{irq_eint0, S3c2410_gpfcon, 0, s3c2410_extint0, 1, NULL, "Key4", 0},/* Key4 */}; #define KEY  _timer_delay1 (HZ/50)//press the button to shake delay 20 milliseconds #define KEY_TIMER_DELAY2 (HZ/10)           Press the button to lift the jitter delay 100 ms # define Key_count 4static void Set_gpio_as_eint (void) {int i;unsigned uival = 0;for (i=0; i<arr Ay_size (Key_gpio_res); i++) {uival = Readl (Key_gpio_res[i].ctrlreg); Uival &= ~ (0x01 << key_gpio_res[i].ctrlbit); Uival |= (0x01 < < (key_gpio_res[i].ctrlbit + 1)); Writel (Uival, Key_gpio_res[i].ctrlreg);} return;} static void Set_gpio_as_gpio (void) {int i;unsigned uival = 0;for (i=0; i<array_size (key_gpio_res); i++) {uival = Readl ( Key_gpio_res[i].ctrlreg) Uival &= ~ (0x01 << key_gpio_res[i].ctrlbit); Uival &= ~ (0x01 << (key_gpio_ Res[i].ctrlbit + 1)); Writel (Uival, Key_gpio_res[i].ctrlreg);} return;} static irqreturn_t kobox_gpio_irq_handle (int irq, void *dev_id) {int key;//disable_irq_nosync (IRQ);p RINTK ("IRQ =%d\n", IRQ), if (dev_id) printk ("dev_id:%s\n", dev_id), switch (IRQ) {case Irq_eint1:key = 0;break;case Irq_eint4:key = 1;break; Case Irq_eint2:key = 2;break;case Irq_eint0:key = 3;BREAK;DEFAULT:PRINTK ("Invalid irq:%d\n", IRQ); Return Irq_handLED; }/* to shake: After the delay of 100ms. Read the key state in the Buttons_timer, assuming it is still pressed. It means that the use of the timer is a normal press, and then using the work queue, tasklet in the way to handle *//* using the kernel Shared Queue, delay scheduling *///schedule_delayed_work (&gpio_key_work[ Key], key_timer_delay2),//oops/* use the kernel Shared Queue, dispatch immediately, delay put into the interrupt function */schedule_work (&gpio_key_work[key]),//Run normal/* use a separate queue. Delay Dispatch *///queue_delayed_work (&key_wq[key], &gpio_key_work[key], key_timer_delay2);//The same collapse!/* use the kernel Shared Queue, dispatch immediately, The delay is put into the interrupt function *///queue_work (&key_wq[key], &gpio_key_work[key]);//The same collapse!return irq_retval (irq_handled);} /*GPF Related registers: Gpfcon 0x56000050 r/w Configures the pins of Port F 0x0gpfdat 0x56000054 r/w The data register for Port F Undef . Gpfup 0x56000058 r/w pull-up Disable register for Port F 0x000k1:gpf1-eint1:gpf1 [3:2] xx = Input01 = Output = Eint  [1] one = RESERVEDK2:GPF4-EINT4:GPF4 [9:8] xx = Input01 = Output = eint[4] one = RESERVEDK3:GPF2-EINT2:GPF2 [5:4] xx = Input01 = output = EINT2] one = reservedk4:gpf0-eint0:gpf0 [1:0] = Input01 = output = eint[0] one = Rese rved*//* the function returns0 means that the key is pressed and the return non-0 means that it is not pressed again, which is caused by a level glitch. It's a noise signal, so. The function returns 0, indicating that a key is pressed and returns a non-0 representation of the jitter */static int get_gpio_portf_value (unsigned int pin) {int ret;unsigned int uival = 0;PRINTK ("I AM @ [%s][%d], pin:%d\n ", __function__,__line__, pin); uival = Readl (s3c2410_gpfdat); ret = (0x1 << pin) & Uival;prin TK ("I AM @ [%s][%d], ret:%d\n", __function__,__line__, ret); return ret;} static void Gpio_key_wq0_handler (struct work_struct *work) {int ret;unsigned int pin;/* interrupted after 100ms will not cause, run the function */printk ("I am At [%s][%d]\n, __function__, __line__), Msleep (+);p in = key_gpio_res[0].gpfpin;/* The pin is set by Eintx Gpio */set_gpio_as_ Gpio ();/* Reads the value of the corresponding pin Gpio. Returning 0 means the key is actually pressed, and returning 1 indicates jitter */ret = Get_gpio_portf_value (PIN), if (0 = = ret) {presscnt[0]++;p rintk ("Key0 pressed:presscnt[0]:% D\n ", presscnt[0]);} /* Set pin back to Eintx */set_gpio_as_eint (); return;} The static void Gpio_key_wq1_handler (struct work_struct *work) {int ret;unsigned int pin;/* is interrupted after 100ms is not caused. Run the function */printk ("I am at [%s][%d]\n", __function__, __line__); Msleep (+);p in = key_gpio_res[1].gpfpin;/* The PIN is set by Eintx Gpio */set_gpio_as_gpio ();/* Read the value of the corresponding pin Gpio, return 0 means the key is actually pressed, return 1 for jitter */ret = Get_gpio_portf_value (PIN); if (0 = = ret) {presscnt[1]++;p rintk ("Key1 pressed:presscnt[1]:%d\n", presscnt[1]);} /* Set pin back to Eintx */set_gpio_as_eint (); return;} static void Gpio_key_wq2_handler (struct work_struct *work) {int ret;unsigned int pin;/* interrupted after 100ms will not cause, run the function */printk ("I am At [%s][%d]\n, __function__, __line__), Msleep (+);p in = key_gpio_res[2].gpfpin;/* The pin is set by Eintx Gpio */set_gpio_as_ Gpio ();/* Reads the value of the corresponding PIN Gpio and returns 0 to indicate that the key is actually pressed. Return 1 indicates jitter */ret = Get_gpio_portf_value (PIN), if (0 = = ret) {presscnt[2]++;p rintk ("Key2 pressed:presscnt[2]:%d\n", presscnt [2]);} /* Set pin back to Eintx */set_gpio_as_eint (); return;} static void Gpio_key_wq3_handler (struct work_struct *work) {int ret;unsigned int pin;/* interrupted after 100ms will not cause, run the function */printk ("I am At [%s][%d]\n, __function__, __line__), Msleep (+);p in = key_gpio_res[3].gpfpin;/* The pin is set by Eintx Gpio */set_gpio_as_ Gpio ();/* Reads the value of the corresponding pin Gpio. Returning 0 means the key is actually pressed. Return 1 indicates jitter */ret = Get_gpio_portf_value (PIN); if (0 = = RET) {presscnt[3]++;p rintk ("Key3 pressed:presscnt[3]:%d\n", presscnt[3]);} /* Set pin back to Eintx */set_gpio_as_eint (); return;} static int Request_irq_for_gpio (void) {int i;int ret;unsigned uival;int nouse;for (i=0; i<array_size (key_gpio_res); I + +) {/* Set interrupt Trigger mode: Falling Edge is active, triggering interrupt. To infer whether */uival = Readl (Key_gpio_res[i].trigreg) is still being pressed according to the value of the Gpio, Uival |= (0x1 << (key_gpio_res[i].trigbit)); Uival & amp;= ~ (0x1 << (key_gpio_res[i].trigbit + 1)) Writel (Uival, Key_gpio_res[i].trigreg);/* Register Interrupt */ret = REQUEST_IRQ ( Key_gpio_res[i].irqnum, Kobox_gpio_irq_handle, Key_gpio_res[i].irqflag, Key_gpio_res[i].irqname, (void *) Key_gpio _res[i].irqname); if (ret) PRINTK ("[func:%s][line:%d] Request_irq failed, ret:%d!\n", __function__,__line__,ret); ELSEPRINTK ("[func:%s][line:%d] request_irq OK, irq:%d!\n", __function__,__line__, Key_gpio_res[i].irqnum); Key_wq[i] = Create_workqueue (Key_gpio_res[i].irqname), if (!key_wq[i]) {PRINTK ("Create_workqueue key_wq[%d] failed!\n", i);} /* Initialize the work queue. Used in response to the second half of the interrupt, after the interrupt response 100ms dispatch to go jitter */init_work (&gpio_key_work[i], gpio_key_wq_handler[i]);} return 0;} struct File_operations kobox_key_operations = {. Owner = This_module,.open = Kobox_key_open,.read = Kobo X_key_read,.release = Kobox_key_release,.unlocked_ioctl = Kobox_key_ioctl,};//gpb0int major;int minor;struct cdev C Dev;struct class *kobox_key_class;struct Device *pstdev = NULL, #define GPIO_KEY_NAME "Kobox_key" int __init key_drv_init ( void) {int error;dev_t dev;printk ("# # # #enter key_drv_init!\n"); major = Register_chrdev (0, Gpio_key_name, &kobox_ Key_operations); if (major < 0) {PRINTK ("can ' t register major number\n"); return major;} /* Create class */kobox_key_class = Class_create (This_module, Gpio_key_name), if (Is_err (Kobox_key_class)) {PRINTK (" Class_create failed!\n "); goto fail;} /* Create/dev/kobox_gpio */pstdev = device_create (Kobox_key_class, NULL, MKDEV (major, 0), NULL, gpio_key_name); Pstdev) {PRINTK ("device_create failed!\n"); goto Fail1;} /* Set GPF0/1/2/4 as extern interrupt pins*/set_gpio_as_eint (); Request_irq_for_gpio ();p rintk ("# # # #key_drv_init ok!\n"); return 0;fail1:class_destroy (Kobox _key_class); Fail:unregister_chrdev (Major, Gpio_key_name); return-1;} void __exit key_drv_exit (void) {PRINTK ("Exit Gpio drv!\n");d Evice_destroy (Kobox_key_class, MKDEV (major, 0)); class_ Destroy (Kobox_key_class); Unregister_chrdev (Major, Gpio_key_name); return;} Module_init (Key_drv_init); Module_exit (Key_drv_exit); Module_license ("GPL");


Kobox:key_wq.c-v1 How to use the work queue Workqueue

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.