How do I use request_threaded_irq so that the interrupt handler is called when the handler is running with a thread?
I am trying to write a simple interrupt handler for GPIO in linux kernel. I use request_threaded_irq
to get interrupt context handler and thread handler.
My problem is that the work done by the handler with the thread has a big impact on the call times of the interrupt handler.
Code to set up an interrupt:
gpio_request(93, "test")
gpio_direction_input(93);
gpio_request(33, "mirror");
gpio_direction_output(33, 1);
request_threaded_irq(gpio_to_irq(93),
interrupt_handler,
threaded_interrupt_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_TIMER,
"test", NULL);
Here I am simply asking gpio 93 to trigger an interrupt on rising and falling edges. I also ask gpio 33 to be used as a mirror, see below.
(In my setup, I set the sync source to gpio 93).
The interrupt handler code is as follows:
static irqreturn_t interrupt_handler(int irq, void *data)
{
int state = gpio_get_value(93);
gpio_set_value(33, state);
return IRQ_WAKE_THREAD;
}
Here, the interrupt handler simply mirrors the gpio 93 input as the output for gpio 33. This allows me to control the effective call rate on interrupt_handler
.
Finally, the threaded handler:
static irqreturn_t threaded_interrupt_handler(int irq, void *data)
{
/* doing msleep here is apparently problematic... */
msleep(1);
return IRQ_HANDLED;
}
In an interrupt handler with threads, calling msleep
(or actually doing the work) is problematic: looking through the scope in the output of gpio 33, I see that the speed of the callback interrupt_handler
changes drastically when threaded_interrupt_handler
sleeping or doing too much work.
How can I configure / use request_threaded_irq()
so that the interrupt handler is always called "on" even if the thread handler is how big a job?
source to share
In the end, I understand what's going on. According to this answer on SO, the interrupt is masked by interrupt handling and an interrupt handler with a thread.
So, it seems I misunderstood the point request_threaded_irq
: it really needs to be used to keep the interrupt handling in the task scheduled by the scheduler.
For my needs, I really wanted to just wait_queue. I am removing the interleaved interrupt handler for my code and changing the interrupt handler to something like:
static wait_queue_head_t wq;
static irqreturn_t interrupt_handler(int irq, void *data)
{
int state = gpio_get_value(93);
gpio_set_value(33, state);
wake_up_interruptible(&wq);
return IRQ_HANDLED;
}
The interrupt handler is now called with the correct time!
source to share