Nut/OS  4.10.3
API Reference
ih_nmi.c
Go to the documentation of this file.
00001 
00036 /*
00037  * $Log: ih_nmi.c,v $
00038  *
00039  */
00040 
00041 #include <arch/avr32.h>
00042 #include <dev/irqreg.h>
00043 #include <dev/gpio.h>
00044 
00045 #include <arch/avr32/gpio.h>
00046 #include <arch/avr32/ihndlr.h>
00047 
00048 #include <avr32/io.h>
00049 
00050 static int InterruptNMICtl(int cmd, void *param);
00051 
00052 IRQ_HANDLER sig_INTERRUPTNMI = {
00053 #ifdef NUT_PERFMON
00054     0,                          /* Interrupt counter, ir_count. */
00055 #endif
00056     NULL,                       /* Passed argument, ir_arg. */
00057     NULL,                       /* Handler subroutine, ir_handler. */
00058     InterruptNMICtl             /* Interrupt control, ir_ctl. */
00059 };
00060 
00064 SIGNAL(InterruptNMIEntry)
00065 {
00066     /*
00067      * We can't use our IRQ_ENTRY() macro here, because this is special, it comes
00068      * directly from the exception handler.
00069      * There is also no automatic saving of registers. But both GM and EM are
00070      * set, so we don't need to worry about preempted interrupts.
00071      */
00072     __asm__ __volatile__("pushm r0-r12, lr");
00073 
00074 #ifdef NUT_PERFMON
00075     sig_INTERRUPTNMI.ir_count++;
00076 #endif
00077     if (sig_INTERRUPTNMI.ir_handler) {
00078         (sig_INTERRUPTNMI.ir_handler) (sig_INTERRUPTNMI.ir_arg);
00079     }
00080 
00081     /* Clear interrupt */
00082     AVR32_EIC.icr = AVR32_EIC_ICR_NMI_MASK;
00083     AVR32_EIC.isr;
00084 
00085     __asm__ __volatile__("popm r0-r12,lr");
00086 }
00087 
00101 static int InterruptNMICtl(int cmd, void *param)
00102 {
00103     int rc = 0;
00104     unsigned int *ival = (unsigned int *) param;
00105     int_fast8_t enabled = AVR32_EIC.imr & AVR32_EIC_IMR_NMI_MASK;
00106 
00107     /*  Disable interrupt. */
00108     if (enabled) {
00109         AVR32_EIC.idr = AVR32_EIC_IDR_NMI_MASK;
00110         AVR32_EIC.imr;
00111     }
00112 
00113     switch (cmd) {
00114     case NUT_IRQCTL_INIT:
00115         /* Setup Peripheral mux for interrupt line */
00116         gpio_enable_module_pin(AVR32_EIC_EXTINT_8_PIN, AVR32_EIC_EXTINT_8_FUNCTION);
00117 
00118         /* Initialize to edge triggered with defined priority. */
00119         AVR32_EIC.mode &= ~AVR32_EIC_MODE_NMI_MASK;
00120 
00121         /* Clear interrupt */
00122         AVR32_EIC.icr = AVR32_EIC_ICR_NMI_MASK;
00123         break;
00124     case NUT_IRQCTL_STATUS:
00125         if (enabled) {
00126             *ival |= 1;
00127         } else {
00128             *ival &= ~1;
00129         }
00130         break;
00131     case NUT_IRQCTL_ENABLE:
00132         enabled = 1;
00133         break;
00134     case NUT_IRQCTL_DISABLE:
00135         enabled = 0;
00136         break;
00137     case NUT_IRQCTL_GETMODE:
00138         {
00139             if (AVR32_EIC.mode & AVR32_EIC_MODE_NMI_MASK) {
00140                 if (AVR32_EIC.level & AVR32_EIC_LEVEL_NMI_MASK)
00141                     *ival = NUT_IRQMODE_HIGHLEVEL;
00142                 else
00143                     *ival = NUT_IRQMODE_LOWLEVEL;
00144             } else {
00145                 if (AVR32_EIC.edge & AVR32_EIC_EDGE_NMI_MASK)
00146                     *ival = NUT_IRQMODE_RISINGEDGE;
00147                 else
00148                     *ival = NUT_IRQMODE_FALLINGEDGE;
00149             }
00150         }
00151         break;
00152     case NUT_IRQCTL_SETMODE:
00153         if (*ival == NUT_IRQMODE_LOWLEVEL) {
00154             AVR32_EIC.mode |= AVR32_EIC_MODE_NMI_MASK;
00155             AVR32_EIC.level &= ~AVR32_EIC_LEVEL_NMI_MASK;
00156         } else if (*ival == NUT_IRQMODE_HIGHLEVEL) {
00157             AVR32_EIC.mode |= AVR32_EIC_MODE_NMI_MASK;
00158             AVR32_EIC.level |= ~AVR32_EIC_LEVEL_NMI_MASK;
00159         } else if (*ival == NUT_IRQMODE_FALLINGEDGE) {
00160             AVR32_EIC.mode &= ~AVR32_EIC_MODE_NMI_MASK;
00161             AVR32_EIC.edge &= ~AVR32_EIC_EDGE_NMI_MASK;
00162         } else if (*ival == NUT_IRQMODE_RISINGEDGE) {
00163             AVR32_EIC.mode &= ~AVR32_EIC_MODE_NMI_MASK;
00164             AVR32_EIC.edge |= ~AVR32_EIC_EDGE_NMI_MASK;
00165         } else {
00166             rc = -1;
00167         }
00168         break;
00169 #ifdef NUT_PERFMON
00170     case NUT_IRQCTL_GETCOUNT:
00171         *ival = (unsigned int) sig_INTERRUPTNMI.ir_count;
00172         sig_INTERRUPTNMI.ir_count = 0;
00173         break;
00174 #endif
00175     default:
00176         rc = -1;
00177         break;
00178     }
00179 
00180     /* Enable interrupt. */
00181     if (enabled) {
00182         AVR32_EIC.ier = AVR32_EIC_IER_NMI_MASK;
00183         AVR32_EIC.imr;
00184         AVR32_EIC.en |= AVR32_EIC_EN_NMI_MASK;
00185     }
00186     return rc;
00187 }