Interrupt tasklet -29 below

Interrupt the tasklet below

tasklet related knowledge points

What is a tasklet?

tasklet is a commonly used method for interrupt processing. tasklet is a special soft interrupt. The following mechanisms for handling interrupts include work queues and soft interrupts.

How to use tasklet s to design interrupts?

Interrupt occurrence, dealing with some urgent things, calling tasklet, Chinese below, doing more time-consuming things below the interrupt

Linux divides interrupts into two parts, one is the upper part and the other is the lower part. In the upper part, we only deal with urgent matters. At the same time, we can call tasklet to start interrupts. The more time-consuming ones should be dealt with below. After calling tasklet, the functions bound by tasklet will not be executed immediately, but after the interrupt, After a very short uncertain time to execute.

tasklet definition

Tasklet by tasklet_struct structure indicates that each structure represents a tasklet separately. In < Linux / interrupt h> Defined as:

struct tasklet_struct
{
	struct tasklet_struct *next;
	unsigned long state;
	atomic_t count;
	void (*func)(unsigned long);
	unsigned long data;
};	

  • Next: the next tasklet in the linked list, which is convenient for managing and setting tasklets;
  • State: status of the tasklet.
  • count: indicates whether the tasklet is active. If it is 0, it is active. If it is not 0, it is inactive
  • void(*func)(unsigned long): the func member in the structure is the binding function of tasklet, and data is its only parameter.
  • date: parameter passed during function execution

tasklet correlation function

  • tasklet schedule function

    Role: scheduling tasklet s

Function prototype:

void tasklet_schedule(struct tasklet struct *t)

Parameters:

  • Pointer to tasklet struct structure.
  • tasklet_init function

    Function: dynamically initialize tasklet

Function prototype:

void tasklet_init(struct tasklet struct *t, void(*func)(unsigned long), unsigned long data);

Parameters:

  • *t: Point to tasklet_ Pointer to struct structure.
  • func: tasklet bound function.
  • data: parameters passed during function execution.
  • tasklet_kill function

Function: delete a tasklet

Function prototype:

tasklet_kill(struct tasklet_struct*t)

Parameters:

  • Point to tasklet_ Pointer to struct structure
  • Note: this function will wait for the tasklet to finish executing, and then remove it. This function may cause sleep, so it is prohibited to use it in interrupt context.

Use the following interrupt design steps

  • Step 1: define a tasklet structure
  • Step 2: dynamically initialize the tasklet
  • Step 3: write the function bound by tasklet
  • Step 4: call tasklet above the interrupt
  • Step 5: delete the tasklet when uninstalling the module

Code click screen trigger

  • driver1.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>

int gpio_num;
int irq = 0;
struct device_node *test_device_node;
struct property *test_node_property;
struct tasklet_struct key_tesk;


struct of_device_id of_match_table[] = {

    {.compatible = "test_keys"},
    {}

};

irq_handler_t test_key(int irq, void *args){

    printk("test_key start \n");

    tasklet_schedule(&key_tesk);
    printk("test_key end \n");

    return IRQ_HANDLED;

}

void test(unsigned long data){
    int i = data;
    while (i--)
    {
        printk("task_key long time is %d \n", i);
    }
    
}

int beep_probe(struct platform_device *pdev){

    int ret = 0;


    printk("beep_probe The match succeeded \n");
    test_device_node = of_find_node_by_path("/test_key");
    if (test_device_node == NULL)
    {
        printk("of_find_node_by_path is error \n");
        return -1;
    }
    
    gpio_num = of_get_named_gpio(test_device_node, "touch-gpio", 0);
    if (gpio_num < 0)
    {
        printk("of_get_named_gpio is error \n");
        return -1;
    }
    
    gpio_direction_input(gpio_num);

    
    //irq = gpio_to_irq(gpio_num);

    irq = irq_of_parse_and_map(test_device_node, 0);

    printk("irq is %d \n", irq);

    ret = request_irq(irq, test_key, IRQF_TRIGGER_RISING, "test_key", NULL);
    if (ret < 0)
    {
        printk("request_irq is error \n");
        return ret;
    }

    tasklet_init(&key_tesk, test, 100);
    

    return 0;
}

int beep_remove(struct platform_device *pdev){
    printk("beep_remove \n");
    return 0;
}

const struct platform_device_id  beep_idtable = {
    .name = "test_keys"
};

struct platform_driver beep_device =
{
    .probe = beep_probe,
    .remove = beep_remove,
    .driver = {
        .name = "123",
        .owner = THIS_MODULE,
        .of_match_table = of_match_table
    },
    .id_table = &beep_idtable
};

static int beep_driver_init(void){
    printk(KERN_EMERG "hello world enter \n");
    int ret = 0;
    ret = platform_driver_register(&beep_device);
    if (ret < 0)
    {
        printk("platform_driver_register fail\n");
    }

    printk("platform_driver_register ok\n");
    
    return 0;
}

static void beep_driver_exit(void){
    printk(KERN_EMERG "hello world exit! \n");
    tasklet_kill(&key_tesk);
    free_irq(irq, NULL);
    platform_driver_unregister(&beep_device);
}

module_init(beep_driver_init);
module_exit(beep_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("LIYU");

Code of the device tree
Comment the following code

	touch-gpio = <&gpio1 20 IRQ_TYPE_EDGE_RISING>;
	interrupt-parent = <&gpio1>;
    interrupts = <20 IRQ_TYPE_LEVEL_LOW>;

Then add the following code to the root node

test_key {
		compatible = "test_keys";
		pinctrl-names = "default";
		pinctrl-0 = <&i2c1_xfer>;
        reg = <0x38>;
		touch-gpio = <&gpio1 20 IRQ_TYPE_EDGE_RISING>;
		interrupt-parent = <&gpio1>;
        interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
	
	};

Keywords: queue Embedded system kernel

Added by fezzik on Sun, 30 Jan 2022 01:47:48 +0200