Example of a Handler

Top  Previous  Next

The following is an example of a low-level interrupt handler for a hypothetical device attached to interrupt 6. This handler needs to write to a device-specific register at 0x03fe00004 to acknowledge the interrupt and disable the device. Writing to 0x03fe00000 allows the device to generate interrupts when ready.

 

Note that the return from k_event_set goes directly to the next interrupt handler.

 

.title "interrupt 6 handler"

.text

 

INT_CLEAR .set 0x03EF0004 ; write 0 to acknowledge

 

.def _interrupt6

 

;------------------------------------------;

; on entry: a11 = kernel pointer           ;

; a2 = &event                              ;

; b11 = address of next icb                ;

; Interrupts are ENABLED                   ;

; on exit: b11 = address of next handler   ;

; a2 = arg for next handler                ;

; free regs:a0, a1, a3, a4, b0, b1, b3, b4 ;

;------------------------------------------;

 

_interrupt6: ldw  *+a11[-1], b1  ; pointer to k_event_set

             mv    a2,       a4  ; argument for i_event_set

             ldw  *+b11[1],  b3  ; return address (next handler)

             ldw  *+b11[2],  a2  ; next argument

             ldw  *+b11[0],  b11 ; next handler ICB

             b     b1            ; call k_event_set (&return)

             ldw  *a4,       b0  ; contents of event word

             mvkl INT_CLEAR, a0

             mvkh INT_CLEAR, a0  ; address INT_CLEAR

             zero a1

             stw  a1,       *a0  ; acknowledge interrupt

 

;-----------------------------;

; NOTE: i_event_set corrupts: ;

; b0, a1, a4, b4 ;

;-----------------------------;

 

This handler could be attached and used as follows:

 

extern void interrupt6(void);   // the interrupt handler

static struct c6xint_ICB ICB6;

static event Event6 = EVENT_NO; // initialised event

extern cregister unsigned int IER;

 

#define DEV_ENABLE *(volatile int *)0x03EF0004

 

...

 

ICB6.Handler = interrupt6;

ICB6.Arg     = &Event6;

 

c6xint_attach_handler(6, &ICB6);

 

IER |= (1<<6); // enable interrupt 6

 

for (;;) {

   Event6 = EVENT_NO;

   DEV_ENABLE = 1;              // enable the device

   event_wait(&Event6);

   // the interrupt has occurred – deal with it

   ...

}