Thank you Edwin,

I will test your solution and say you what happens.

Have a nice day.

Maxime


--- In [email protected], Edwin van den Oetelaar <[EMAIL PROTECTED]> 
wrote:
>
> maxime_coquelin schreef:
> > Hi everybody,
> >
> > For my project, I need to use the PA0 pin as an interrupt to handle
> > the \int pin of the pcf8574 chip (which is a I2C-8-bit controller). I
> > have used the work done by calzo(Foxdoc.pdf on lugman.net, thank's to
> > him).
> > I succeed in building the module and  the IRQ is well requested. To do
> > that, I have to invert the \int pin of the pcf8574.
> >
> > The problem I have is that the interrupt is handeld on the high state
> > (and not on the front), so, when a logic state change on the pcf8574,
> > the PA0 pin goes to high, and it generates thousand of interrupts,
> > whereas I need only one.
> >
> > Here is the code made by Calzo :
> >
> > #include <linux/interrupt.h>
> > #include <linux/module.h>
> > #include <asm/io.h> //provide access to GPIO port and other
> > MODULE_LICENSE("DUAL GPL/BSD");
> > MODULE_VERSION("0.1");
> > #define IRQ_PA_MASK 0x01 //interrupt sul pulsante
> > static DEFINE_SPINLOCK(gpio_lock_irq);
> >
> > /***** FUNZIONE DI INTERRUPT ******
> > * In questa funzione viene disabilitata temporaneamente la
> > * possibilità di ricevere altri interrupt fino a che non è
> > * soddisfatta la funzione seguente
> > * ********************************/
> > static irqreturn_t
> > irqPA_interrupt(int irq, void *dev_id, struct pt_regs *regs)
> > {
> > *R_IRQ_MASK1_CLR = 0;
> > *R_PORT_PA_DATA = 0; //fondamentale!
> > printk(KERN_ALERT "calzo - irq servito\n");
> > return IRQ_HANDLED;
> > }
> > /****************************************
> > * INITIALIZATION & CLEANUP functions
> > ****************************************/
> > /// Funzione di inizializzazione del modulo
> > int irqPA_init_module(void) {
> > if (request_irq(PA_IRQ_NBR, irqPA_interrupt,
> > SA_INTERRUPT,"calzo gpio PA interrupt", NULL))
> > {
> > printk(KERN_CRIT "err: PA irq for gpio (calzo)\n");
> > return -ERESTART;
> > }
> > //setto su quale pin vi è línterrupt valido
> > *R_IRQ_MASK1_SET = IRQ_PA_MASK;
> > return 0;
> > }
> > ///Funzione di scaricamento del modulo
> > void irqPA_cleanup_module(void) {
> > spin_lock_irq(&gpio_lock_irq);
> > *R_IRQ_MASK1_SET = 0;
> > *R_IRQ_MASK1_CLR = 0;
> > free_irq(PA_IRQ_NBR, NULL);
> > spin_unlock_irq(&gpio_lock_irq);
> > }
> > /***************************************
> > * INIT & EXIT
> > ***************************************/
> > module_init(irqPA_init_module);
> > module_exit(irqPA_cleanup_module);
> >
> > Do you understand my problem? And do you see how to disable the irq
> > once one is received?
> >
> > Thank's in advance.
> >
> > Maxime Coquelin
> >
> >   
> I see your problem.
> What I can tell it works like this :
> 1) you get an interrupt, you set flag and disable further interrupts 
> from this pin
> 2) you read the contents of your pc8574 which clears the interrupt
(from 
> tasklet)
> 3) you reset flag and enable interrupts again (from tasklet)
> note: you can not lose events this way from your i2c device if you 
> enable interrupts again directly after the
> read from the device. The device will keep on interrupting you again 
> until you do a i2c read or write.
> 
> Just my opinion, you should also talk to john Crispin, he knows about 
> this stuff.
> check out page 274 of Linux Device Drivers 3rd edition and the functions
> local_irq_save(unsigned long flags);
> local_irq_restore(unsigned long flags);
> You might want to split this in a top and bottom half (page 275)
using a 
> tasklet.
> 
> Good luck,
> Edwin van den Oetelaar
>


Reply via email to