The goal
Configure gpio pins on Raspberry Pi to trigger an interrupt.Usability
Big: Interfacing devices, for example ov7670 8-bit camera. Connecting own devices to gpio pins, testing data transfer protocols, etc.Code
Hardware
Description
Linux kernel api provides access to gpio pins, you can configure it as input/output, set/read value and attach current pin to an interrupt.
Most information about gpio in kernel space you can find here.
Kernel compilation and module compilation, here.
Linux kernel programming guide will be helpful too.
Fire interrupt flags are:
IRQF_TRIGGER_RISING
IRQF_TRIGGER_FALLING
IRQF_TRIGGER_HIGH
IRQF_TRIGGER_LOW
As far now, I could trigger interrupt only in FALLING or RISING (or both) modes, when I try configure interrupt as LOW or HIGH error is generated.
Use case
I assume that you have already compiled m_test.ko and sent it to Raspberry pi.
Follow this steps, to do first gpio interrupt test.
Connect via ssh to your Raspberry Pi on two sessions.
On first session, run command:
pi@raspberrypi ~ $ tail -f /var/log/messagesOn second one, check registered interrupts:
pi@raspberrypi ~ $ cat /proc/interrupts CPU0 3: 58033 ARMCTRL BCM2708 Timer Tick 32: 749423 ARMCTRL dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1 52: 325 ARMCTRL BCM2708 GPIO catchall handler 65: 5141 ARMCTRL ARM Mailbox IRQ 66: 1 ARMCTRL VCHIQ doorbell 75: 1 ARMCTRL 77: 7303 ARMCTRL bcm2708_sdhci (dma) 79: 0 ARMCTRL bcm2708_i2c.0, bcm2708_i2c.1 80: 0 ARMCTRL bcm2708_spi.0 83: 19 ARMCTRL uart-pl011 84: 13684 ARMCTRL mmc0 FIQ: usb_fiq Err: 0Now, insert our kernel module:
pi@raspberrypi ~/test $ ls m_test.ko pi@raspberrypi ~/test $ sudo insmod m_test.koOn first console, you can see:
Apr 10 21:04:34 raspberrypi kernel: [ 2645.083228] Hello ! Apr 10 21:04:34 raspberrypi kernel: [ 2645.083262] Mapped int 187Now, between gpio_17 (P5 header, pin 11) and 3.3V put 4.7k resistor. Wait a little bit, disconnect from 3.3V and put it between gpio_17 and ground.
On first console you can see:
Apr 10 21:07:17 raspberrypi kernel: [ 2808.374082] Interrupt [187] for device some_device was triggered !. Apr 10 21:07:17 raspberrypi kernel: [ 2808.384400] Interrupt [187] for device some_device was triggered !. Apr 10 21:07:17 raspberrypi kernel: [ 2808.394015] Interrupt [187] for device some_device was triggered !. Apr 10 21:07:17 raspberrypi kernel: [ 2808.394055] Interrupt [187] for device some_device was triggered !. Apr 10 21:07:17 raspberrypi kernel: [ 2808.404416] Interrupt [187] for device some_device was triggered !. Apr 10 21:07:17 raspberrypi kernel: [ 2808.414070] Interrupt [187] for device some_device was triggered !. Apr 10 21:07:17 raspberrypi kernel: [ 2808.424419] Interrupt [187] for device some_device was triggered !.It's so many, because pin is very sensitive, in fact, when you only insert in gpio_17 a couple of wire held in hand, the interrupts will be generated too.
Now when module is loaded, check once again registered interrupts:
pi@raspberrypi ~ $ cat /proc/interrupts CPU0 3: 65849 ARMCTRL BCM2708 Timer Tick 32: 867027 ARMCTRL dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1 52: 412 ARMCTRL BCM2708 GPIO catchall handler 65: 5945 ARMCTRL ARM Mailbox IRQ 66: 1 ARMCTRL VCHIQ doorbell 75: 1 ARMCTRL 77: 7472 ARMCTRL bcm2708_sdhci (dma) 79: 0 ARMCTRL bcm2708_i2c.0, bcm2708_i2c. 80: 0 ARMCTRL bcm2708_spi.0 83: 19 ARMCTRL uart-pl011 84: 14550 ARMCTRL mmc 187: 412 GPIO Some gpio pin description FIQ: usb_fiq Err: 0There is one more row in registered interrupts:
187: 412 GPIO Some gpio pin descriptionNow unload module:
pi@raspberrypi ~ $ sudo rmmod m_testWatch first console:
Apr 10 21:10:27 raspberrypi kernel: [ 2998.254507] GoodbyeAnd once again registered interrupts:
pi@raspberrypi ~ $ cat /proc/interrupts CPU0 3: 67321 ARMCTRL BCM2708 Timer Tick 32: 890623 ARMCTRL dwc_otg, dwc_otg_pcd, dwc_otg_hcd:usb1 52: 412 ARMCTRL BCM2708 GPIO catchall handler 65: 6107 ARMCTRL ARM Mailbox IRQ 66: 1 ARMCTRL VCHIQ doorbell 75: 1 ARMCTRL 77: 7491 ARMCTRL bcm2708_sdhci (dma) 79: 0 ARMCTRL bcm2708_i2c.0, bcm2708_i2c.1 80: 0 ARMCTRL bcm2708_spi.0 83: 19 ARMCTRL uart-pl011 84: 14729 ARMCTRL mmc0 187: 412 GPIO FIQ: usb_fiq Err: 0412 is number which describes, how many times interrupt was triggered.
Thank you !!!!
ReplyDeleteHi, thanks for the tutorial. How would you implement the debounce feature via software? Thanks in advance.
ReplyDeletehttp://raspberrypi.stackexchange.com/questions/8544/gpio-interrupt-debounce/8556#8556
DeleteHi, thanks for above link. Sorry, I was on vacation so I could not respond to your question, I'm glad that you figured out sw debounce. Personally I would go into hw and use something with Schmitt trigger. Often I use CD4093 which is a quad 2-input NAND gate with schmitt trigger. This gate + couple of resistors and condensators and you could simply move your problem from software to hardware. I'm building rfid reader on this gate (only) and it's quite fun :).
DeleteHi ,
ReplyDeleteyou are putting printk while interupt are disabled. printk can block. It's not a good practice.
// disable hard interrupts (remember them in flag 'flags')
local_irq_save(flags);
printk(KERN_NOTICE "Interrupt [%d] for device %s was triggered !.\n",
irq, (char *) dev_id);
// restore hard interrupts
local_irq_restore(flags);
Hi,
DeleteFirst of all, I want to thank you for good comment. You're absolutely true about printk and any other function which would run on disabled interrupts, we should be careful doing that. I'll add your comment to source code.
In my example, I was triggering interrupt by noise, rather than "nice" input like clock etc. so, output on console was ugly. so that's why I've used printk in disabled interrupt block code.
Thanks for sharing this. How can I use the interrupt(s) it in my own (C-)application?
ReplyDeletePlease write some more details. On what platform, your application will run. Atmel ? - no problem. Regular PC/Raspberry PI -> I doubt, that using interrupts here (application) is a good thing. Please give some more info, some example etc. ... maybe you'll end with using signals, not interrupts, etc.
DeleteHi, Is it possible to do the same thing on Beaglebone black ?
ReplyDeleteHi, of course. Check this link: http://processors.wiki.ti.com/index.php/Linux_PSP_GPIO_Driver_Guide
DeleteYou just need to know how irq to gpio mapping looks like.
-- snippet --
In this case Bank-1[0..31] maps to Linux GPIO numbers 32..63, Bank-2[0..31] to Linux GPIO numbers 64..95 etc.
-- snippet --
Basically function gpio_to_irq( ); does all dirty work for you.