Skip to content

Day13 - GPIO IRQ Debounce with Workqueue

🎯 Objective

Implement a GPIO driver with:

  • Interrupt handling
  • Software debounce
  • Event queue (ring buffer)
  • Blocking read + poll support

🧩 Step 1 - Add Delayed Work

struct delayed_work btn_dwork;
unsigned int debounce_ms;

Init:

INIT_DELAYED_WORK(&mydev->btn_dwork, mygpio_btn_dwork_handler);

🧩 Step 2 - Modify ISR

mod_delayed_work(system_wq,
                 &mydev->btn_dwork,
                 msecs_to_jiffies(mydev->debounce_ms));

🧩 Step 3 - Implement Debounce Handler

  • Read GPIO
  • Compare with last state
  • Generate event

🧩 Step 4 - Add Ring Buffer

#define EVENT_BUFFER_SIZE 16

event_buff[]
event_head
event_tail

🧩 Step 5 - Wake Up Reader

wake_up_interruptible(&mydev->read_queue);

🧩 Step 6 - Implement read()

Behavior:

  • Blocking: wait event
  • Non-blocking: return -EAGAIN

🧩 Step 7 - Implement poll()

poll_wait(...)
return POLLIN if data available

🧪 Testing

1. Blocking read

cat /dev/mygpio

Press button → should output event


2. Non-blocking

python3 -c "
import os
fd = os.open('/dev/mygpio', os.O_RDONLY | os.O_NONBLOCK)
try:
    print(os.read(fd, 64))
except BlockingIOError:
    print('No data')
"

3. poll()

python3
import select, os

fd = os.open("/dev/mygpio", os.O_RDONLY)

p = select.poll()
p.register(fd, select.POLLIN)

while True:
    events = p.poll()
    print("EVENT:", os.read(fd, 64))

4. Stress test

  • Rapid button press
  • Ensure:
  • no crash
  • no stuck read
  • events reasonable

✅ Expected Result

  • No duplicate bounce events
  • Stable press/release detection
  • poll() wakes immediately
  • read() blocks correctly