Interrupt independent key

1, Fundamentals of interruption

1. What is interruption

Interrupt means that the CPU needs to stop the execution of the current program, turn to deal with emergencies, and return to the original program after processing.

2. Hardware interrupt and software interrupt

Hardware interrupt generally refers to the interrupt request sent by the peripheral and the interrupt generated by the internal hardware (calculation overflow, divisor 0, power failure, etc.)
Software interrupt, typically the lower half of the interrupt handler

3. Interrupt priority

According to the importance and urgency of interrupt events, the system divides interrupt sources into several levels, and the one with high priority shall be executed first.

2, Hardware connection of key

There are five independent buttons on the base plate. Take HOME and BACK as examples. Let's take a look at the schematic diagram, as shown in the figure below.

It can be seen from the hardware connection that the IO interrupt in the default state is high. Therefore, it can be judged that the following interrupt triggering mode should be falling edge triggering.

Two network UARTS_ Ring and SIM_DET.
The corresponding GPIO is "EXYNOS4_GPX1(1)" and the interrupt number is "XEINT9"
The corresponding GPIO is "EXYNOS4_GPX1(2)" and the interrupt number is "XEINT10"


You can see that the pin configuration for external interrupt mode needs to be set to 0xF.
Finally, let's take a look at another part. In Chapter 56 of the Datasheet, find Debouncing Filter, which is the part of 4412 for automatic anti shake of keys. As shown in the figure below, you can see that there is its own anti shake.

3, Interrupt correlation function

1.request_irq

Linux interrupts need to be applied before use. The interrupt application function is "request_irq", which is in the header file "include/linux/interrupt.h", as shown in the following figure.

Interrupt request function_ irq(unsigned int irq, irq_handler_t handler,
unsigned long flags,const char *name, void *dev) have the following parameters.
Parameter unsigned int irq: irq is the interrupt number
Parameter irq_handler_t handler: handler is the processing function registered with the system
Parameter unsigned long flags: irqflags is the trigger flag bit
Parameter const char *name: devname is the interrupt name, which can be viewed through "cat/proc/interrupts" after registration
Parameter void *dev: dev_id is the device

2. free_irq

Corresponding to the above interrupt application function is the interrupt release function free_irq, which needs to be called when unloading the driver, as shown in the following figure, is also in the header file "include/linux/interrupt.h".

Interrupt release function extern void free_irq(unsigned int, void *); The parameters are as follows.
Parameter 1: irq is the interrupt number
Parameter 2: dev_id is the device

3.irqreturn_t

After an interrupt is generated, the interrupt handler irqreturn will be called_ t. This function is also in the header file
"include/linux/interrupt.h" is shown in the following figure.

This function is extern irqreturn_t no_action(int cpl, void *dev_id);
The interrupt function type is irqreturn_t
Parameter int cpl: interrupt number
Parameter void *dev_id: device

4. Interrupt number

In the initialization file "drivers / GPIO / GPIO exynos4. C", as shown in the following figure

vim drivers/gpio/gpio-exynos4.c


The two interrupt pins selected belong to "GPX1", so as shown in the above figure, the basic value of interrupt number is IRQ_EINT(8), then GPX1CON[0] and GPX1CON[1] correspond to the interrupt number IRQ_EINT(9) and IRQ_EINT(10).

If you want to call other external interrupts, you can also check the interrupt number in this way, but only if the interrupt is not occupied.

4, Experimental operation

The actual application of external interrupts is generally integrated in some similar sound cards, graphics cards and other bus devices. The actual application is to call the header files and functions mentioned above, apply for interrupts during driver initialization, and then write interrupt function processing functions for specific drivers. For example, the volume button in the sound card is integrated into the sound card of the key part code, and the key can be adjusted to turn up the volume accordingly.

A simple character driver is registered here. In this way, it will be easy for everyone to understand. The function to be completed is to print data after the key interrupt is generated.

1. Registered equipment

As shown in the figure below, add the code for registering the device in the platform file "arch / arm / Mach exynos / Mach itop4412. C".

vim arch/arm/mach-exynos/mach-itop4412.c


For simplicity, you can force the registration of devices without defining macro variables. (not written #ifdef)

2. Add the code called by the device

It's still in the last file

3.menuconfig configuration

Then open the menuconfig configuration file and uninstall the drivers that use these two interrupts.
Device Drivers —>
Input device support —>
Keyboards —>
Cancel GPIO Buttons - >

After the reset, recompile the kernel, and burn the generated binary zImage file to the development board to replace the original kernel.

4. Write driver

1. Drive fixed header file

As shown in the figure below, for the header file part, the driver who writes 4412 in the future can add these header files to the front of the code.

/* Later, the write driver can load the header file in front of the code */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>

/* Interrupt function header file */
#include <linux/interrupt.h>
#include <linux/irq.h>

2. Application function irq_probe

First of all, interrupt IO is detected, whether it is occupied or not. The way of processing is usually to apply for IO to see if it is successful. After the application is successful, GPIO is configured as a pull up mode, and then gpio_ is called. Free release it.

The parameter "irq_type_edge_failing" is used, which represents falling edge triggering. This macro is defined in the header file "include/linux/irq.h", as shown in the following figure.

3.Makefile

The omission is the same as the previous one

4.itop4412_irq.c

/* Later, the write driver can load the header file in front of the code */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/miscdevice.h>
#include <linux/platform_device.h>
#include <mach/regs-gpio.h>
#include <asm/io.h>
#include <linux/regulator/consumer.h>
#include <linux/delay.h>

/* Interrupt function header file */
#include <linux/interrupt.h>
#include <linux/irq.h>

#define IRQ_DEBUG

#ifndef IRQ_DEBUG
#define DPRINTK(x...) printk("IRQ_CTL DEBUG:" x)
#else
#define DPRINTK(x...)
#endif

#define DRIVER_NAME "irq_test"

MODULE_LICENSE("Dual BSD/GPL");


/* Define interrupt handling functions */
static irqreturn_t eint9_interrupt(int irq,void *dev_id)
{
	printk("%s(%d)\n",__FUNCTION__,__LINE__);
	return IRQ_HANDLED;
}

static irqreturn_t eint10_interrupt(int irq,void *dev_id)
{
	printk("%s(%d)\n",__FUNCTION__,__LINE__);
	/*The above uses a special code "printk" ("% s (% d) \ n", _function _, _line);
	"This code is very useful in debugging, that is, print the current function and the corresponding line,
	 The effect can be seen in the later test.*/
	return IRQ_HANDLED;
}

static int irq_probe(struct platform_device *pdev)
{
	int ret;
	char *banner = "irq_test Initialize!\n";
	
	printk(banner);
	
	/* First IO */
	ret = gpio_request(EXYNOS4_GPX1(1),"EINT9");
	if(ret)
	{
		printk("%s:request GPIO %d for EINT9 failed,ret = %d!\n",DRIVER_NAME,EXYNOS4_GPX1(1),ret);
		return ret;
	}
	
	s3c_gpio_cfgpin(EXYNOS4_GPX1(1),S3C_GPIO_SFN(0xF));
	s3c_gpio_setpull(EXYNOS4_GPX1(1),S3C_GPIO_PULL_UP);
	gpio_free(EXYNOS4_GPX1(1));
	
	/* Second IO*/
	ret = gpio_request(EXYNOS4_GPX1(2),"EINT10");
	if(ret)
	{
		printk("%s:request GPIO %d for EINT10 failed,ret = %d!\n",DRIVER_NAME,EXYNOS4_GPX1(2),ret);
		return ret;
	}
	
	s3c_gpio_cfgpin(EXYNOS4_GPX1(2),S3C_GPIO_SFN(0xF));
	s3c_gpio_setpull(EXYNOS4_GPX1(2),S3C_GPIO_PULL_UP);
	gpio_free(EXYNOS4_GPX1(2));
	
	/* interrupt */
    ret = request_irq(IRQ_EINT(9),eint9_interrupt,IRQ_TYPE_EDGE_FALLING,"eint9",pdev);
	if(ret < 0)
	{
		printk("Request IRQ %d failed,%d\n",IRQ_EINT(9),ret);
		goto exit;
	}
	
	ret = request_irq(IRQ_EINT(10),eint10_interrupt,IRQ_TYPE_EDGE_FALLING,"eint10",pdev);
	if(ret < 0)
	{
		printk("Request IRQ %d failed,%d\n",IRQ_EINT(10),ret);
		goto exit;
	}
	return 0;
exit:
	return ret;
}


static int irq_remove(struct platform_device *pdev)
{
	free_irq(IRQ_EINT(9),pdev); // Release interrupt
	free_irq(IRQ_EINT(10),pdev); // Release interrupt
	
	return 0;
}

static int irq_suspend(struct platform_device *pdev,pm_message_t state)
{
	DPRINTK("irq suspend:power off!\n");
	return 0;
}

static int irq_resume(struct platform_device *pdev)
{
	DPRINTK("irq resume:power on!\n");
	return 0;
}

/* Entry function and exit function of driver module */
static struct platform_driver irq_driver = {
	.probe = irq_probe,
	.remove = irq_remove,
	.suspend = irq_suspend,
	.resume = irq_resume,
	.driver = {
			.name = DRIVER_NAME,
			.owner = THIS_MODULE,
	},
};



static void __exit irq_test_exit(void)
{
	platform_driver_unregister(&irq_driver); // Unload driver
}

static int __init irq_test_init(void)
{
	return platform_driver_register(&irq_driver); // Register driver
}

module_init(irq_test_init);
module_exit(irq_test_exit);

5. Compilation

New folder

mkdir irq_test


compile;

6. Development board operation

1. Load drive

insmod itop4412_irq.ko

2. View the interruption of the application

cat /proc/interrupts

3. Test

Press the HOME and BACK buttons a few times, and the following printing information will appear

Finally, use the command "cat /proc/interrupts" to view the applied interrupts, as shown in the figure below. It has been detected that the two interrupts have been triggered several times respectively.

Keywords: Linux Embedded system

Added by SerpentSword on Sun, 16 Jan 2022 22:01:14 +0200