I3CPAC+Exercise+6



=Øvelse 6= //Lav en driver som kan implementere en blokerende læsning fra én GPIO. Driveren skal benytte en ISR til at vække ”read” metoden når der sket et event på en given GPIO. Du skal kun implementere det for et enkelt GPIO input.//

Vigtige funktioner
Vigtige metoder at fremhæve er:

code format="c" /* get interrupt line attached to GPIO port # */ unsigned int gpio_to_irq(unsigned int gpio);

/* sleep until woken up and condition is true */ wait_event_interruptible(queue, condition)

/* wake up queue subscriber */ void wake_up_interruptible(wait_queue_head_t *queue);

code

Implementer Interrupt request
Efter initialiseringen af portenes læseretning implementeres vores interrupt request i vores init rutine.

code format="c" // Get IRQ Line irq_line = gpio_to_irq(gpio[0].num); printk("irq line is: %i", irq_line);

// Request IRQ if (request_irq(irq_line, isr_func, IRQF_TRIGGER_RISING, "this_is_a_label", NULL) != 0) printk("Error requesting IRQ"); code

IRQF_TRIGGER_RISING er defineret i interrupt.h biblioteket.

Implementer Interrupt Free
Vores IRQ Line frigives i exit rutinen

code format="c" // Free IRQ free_irq(irq_line, NULL); code

Implementer Interrupt Service Routine
Vores ISR funktion er implementeret over init-funktionen, og udskriver en besked med printk samt sørger for at vække vores read-funktion.

code format="c" irqreturn_t isr_func(int irq,           void *dev_id, struct pt_regs *)

{   printk(”IRQ event!!!\n); flag = 1; wake_up_interruptible(wait_queue); return IRQ_HANDLED; } code

=Implementer Read= I read skal vi vente indtil data er klar, altså at interrupt-rutinen er blevet kaldt. Dermed bliver det en blocking read funktion. wait_event_interruptible venter indtil flaget er sat og vækker derefter read fra den "dybe søvn". Følgende linjer tilføjes til den allerede implementerede read-funktion:

code format="c" // ...   wait_event_interruptible(wait_queue, flag == 1); flag = 0; // ... code

En oversigt over registrerede interrupts kan findes i /proc/interrupts/.