Contiki 2.6

sys-interrupt.c

00001 #include <sys-interrupt.h>
00002 #include <interrupt-utils.h>
00003 #include <AT91SAM7S64.h>
00004 
00005 #define ATTR
00006 
00007 #ifndef NULL
00008 #define NULL 0
00009 #endif
00010 
00011 
00012 static SystemInterruptHandler *handlers = NULL;
00013 
00014 static void
00015 system_int_safe (void) __attribute__((noinline));
00016 
00017 static void
00018 system_int_safe (void) 
00019 {
00020   SystemInterruptHandler *h;
00021   h = handlers;
00022   while (h) {
00023     if (h->handler()) break;
00024     h = h->next;
00025   }
00026 }
00027   
00028 static void NACKEDFUNC ATTR
00029 system_int (void) /* System Interrupt Handler */ 
00030 {
00031   ISR_ENTRY();
00032   system_int_safe();
00033   *AT91C_AIC_EOICR = 0;                   /* End of Interrupt */
00034   ISR_EXIT();
00035 }
00036 
00037 static unsigned int enabled = 0; /* Number of times the system
00038                                     interrupt has been enabled */
00039 
00040 #define DIS_INT *AT91C_AIC_IDCR = (1 << AT91C_ID_SYS)
00041 #define EN_INT if (enabled > 0) *AT91C_AIC_IECR = (1 << AT91C_ID_SYS)
00042 
00043 void
00044 sys_interrupt_enable()
00045 {
00046   if (enabled++ == 0) {
00047     /* Level trigged at priority 5 */
00048     AT91C_AIC_SMR[AT91C_ID_SYS] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | 5;
00049     /* Interrupt vector */
00050     AT91C_AIC_SVR[AT91C_ID_SYS] = (unsigned long) system_int;
00051     /* Enable */
00052     EN_INT;
00053   }
00054 }
00055 
00056 
00057 void
00058 sys_interrupt_disable()
00059 {
00060   if (--enabled == 0) {
00061     DIS_INT;
00062   }
00063 }
00064 
00065 void
00066 sys_interrupt_append_handler(SystemInterruptHandler *handler)
00067 {
00068   SystemInterruptHandler **h = &handlers;
00069   while(*h) {
00070     h = &(*h)->next;
00071   }
00072   DIS_INT;
00073   *h = handler;
00074   handler->next = NULL;
00075   EN_INT;
00076 }
00077 
00078 void
00079 sys_interrupt_prepend_handler(SystemInterruptHandler *handler)
00080 {
00081   DIS_INT;
00082   handler->next = handlers;
00083   handlers = handler;
00084   EN_INT;
00085 }
00086 
00087 void
00088 sys_interrupt_remove_handler(SystemInterruptHandler *handler)
00089 {
00090   SystemInterruptHandler **h = &handlers;
00091   while(*h) {
00092     if (*h == handler) {
00093       DIS_INT;
00094       *h = handler->next;
00095       EN_INT;
00096       break;
00097     }
00098     h = &(*h)->next;
00099   }
00100 }