Wei Dongshan uboot_kernel_root file system study notes 5.8-Lesson 005_Character device driver_Section 008_Key driver of interrupt mode of character device driver_Write code

A drv_open function analysis

Configure a pin as an external trigger interrupt source:
(1) Pin label-void *dev_id
(2) Sensitive edge-unsigned long irqflags
(3) Interrupt label-unsigned int irq;
(4) Interrupt type-irq_handler_t handler
(5) ) Device name -const char *devname The
above parameters are request_irqset by function in the linux kernel .

[1] request_irqFunction call

request_irq(IRQ_EINT0,  buttons_irq, IRQT_BOTHEDGE, "S2", &pins_desc[0]);

[2] request_irqFunction internal processing: call the setup_irqfunction to initialize the interrupt.
Among them,
irq= (3) interrupt label-unsigned int irq = IRQ_EINT0
action->handler = (4) function called after the interrupt occurs-irq_handler_t handler = buttons_irq
action->flags = (2) sensitive edge-unsigned long irqflags = IRQT_BOTHEDGE
action->name = (5) Device name-const char *devname = “S2” You can take any value as you
like action->next = NULL;
action->dev_id = (1) Pin label-void *dev_id = &pins_desc[0 ] Any value can be selected, the purpose is to determine which driver to uninstall

int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char *devname, void *dev_id)
{
	...
	retval = setup_irq(irq, action);
	...
}

[3] setup_irqFunction internal processing: use set_typefunction processing

int setup_irq(unsigned int irq, struct irqaction *new)
{
	...
	if (desc->chip && desc->chip->set_type)
		desc->chip->set_type(irq,new->flags & IRQF_TRIGGER_MASK);
	...
}

Among them, desc->chipwhere is it defined?
arch\arm\plat-s3c24xx\irq.c\void __init s3c24xx_init_irq(void), As defined in [1] IRQ_EINT0, desc->chip corresponds to s3c_irq_eint0t4.

void __init s3c24xx_init_irq(void)
{
	...
	/* external interrupts */
	
	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
		irqdbf("registering irq %d (ext int)\n", irqno);
		set_irq_chip(irqno, &s3c_irq_eint0t4);
		set_irq_handler(irqno, handle_edge_irq);
		set_irq_flags(irqno, IRQF_VALID);
	}
	
	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
		set_irq_chip(irqno, &s3c_irqext_chip);
		set_irq_handler(irqno, handle_edge_irq);
		set_irq_flags(irqno, IRQF_VALID);
	}
	...
}

View s3c_irq_eint0t4definition:

static struct irq_chip s3c_irq_eint0t4 = {
	.name		= "s3c-ext0",
	.ack		= s3c_irq_ack,
	.mask		= s3c_irq_mask,
	.unmask		= s3c_irq_unmask,
	.set_wake	= s3c_irq_wake,
	.set_type	= s3c_irqext_type,
};

[4] set_typeFunction = s3c_irqext_typeFunction The
previous calling code is:

new->flags=action->flags =	(2)敏感沿-unsigned long irqflags=IRQT_BOTHEDGE
desc->chip->set_type(irq,new->flags & IRQF_TRIGGER_MASK);

The definition of the function is:

s3c_irqext_type(unsigned int irq, unsigned int type)
{
	...
	if ((irq >= IRQ_EINT0) && (irq <= IRQ_EINT3))
	{
		gpcon_reg = S3C2410_GPFCON;
		extint_reg = S3C24XX_EXTINT0;
		gpcon_offset = (irq - IRQ_EINT0) * 2;
		extint_offset = (irq - IRQ_EINT0) * 4;
	}
	...
	/* Set the external interrupt to pointed trigger type */
	switch (type)
	{
		case IRQT_NOEDGE:
			printk(KERN_WARNING "No edge setting!\n");
			break;

		case IRQT_RISING:
			newvalue = S3C2410_EXTINT_RISEEDGE;
			break;

		case IRQT_FALLING:
			newvalue = S3C2410_EXTINT_FALLEDGE;
			break;
		//与前面request_irq函数调用一致
		case IRQT_BOTHEDGE:
			newvalue = S3C2410_EXTINT_BOTHEDGE;
			break;

		case IRQT_LOW:
			newvalue = S3C2410_EXTINT_LOWLEV;
			break;

		case IRQT_HIGH:
			newvalue = S3C2410_EXTINT_HILEV;
			break;

		default:
			printk(KERN_ERR "No such irq type %d", type);
			return -1;
	}
}

Two drv_close function analysis

Function purpose: release interrupt source

  1. free_irq function call
irq=(3)中断标号-unsigned int irq = IRQ_EINT0
dev_id = (1)引脚标号-void *dev_id = &pins_desc[0]

free_irq(IRQ_EINT0, &pins_desc[0]);

The free_irq function definition:

void free_irq(unsigned int irq, void *dev_id)

Three buttons_irq interrupt service function analysis-wake-up function

  1. Function declaration format: static irqreturn_t buttons_irq(int irq, void *dev_id)
    Note: You can see the dev_idfunction here : Determine the interrupt source
  2. return value:return IRQ_RETVAL(IRQ_HANDLED);
  3. Wake-up function:wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */

Four drv_read function analysis-sleep function:

  1. Sleep function call
/* 如果没有按键动作, 休眠 */
wait_event_interruptible(button_waitq, ev_press);
  1. Sleep function prototype
#define wait_event_interruptible(wq, condition)				\
({									\
	int __ret = 0;							\
	if (!(condition))						\								//condition数值为0的时候休眠
		__wait_event_interruptible(wq, condition, __ret);	\
	__ret;								\
})
  1. Parameter declaration

[1]ev_press parameters:

/* 中断事件标志, 中断服务程序将它置1:表示唤醒
third_drv_read将它清0:表示休眠 */
static volatile int ev_press = 0;

[2] button_waitq parameter:
represents the process hanging in the queue

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

Five drive test 1

When the app program executes the read function: if the interrupt function does not occur, the sleep process is executed;
if an interrupt occurs, the process is awakened

  1. How to call drv_openfunctions after the development board loads the driver ?
    exec 5</dev/buttonsMeaning: Turn on the device /dev/buttonsand locate to 5

    Note: The shell process number shown in the figure below is 770
    Insert picture description here
    /proc/770/fd: fd — This is a directory that contains the file descriptors of each file opened by the current process. These file descriptors point to the actual files A symbolic link; the
    Insert picture description here
    execution effect of the driver /dev/buttons opened by the shell process :
    Insert picture description here

  2. Call the close function?
    carried out:exec 5<&-
    Insert picture description here
    Insert picture description here

Six drive test 2

  1. Executing the test program (execution in the background): ./app &
    Insert picture description here
    As can be seen from the figure: the driver and the test program are executed in the background. Among them, the test program is in a sleep state (S) to
    Insert picture description here
    view the CPU resources occupied by each process: topcommand (ctrl+c to exit)
    Insert picture description here

Guess you like

Origin blog.csdn.net/xiaoaojianghu09/article/details/104303719