Nut/OS  4.10.3
API Reference
ih_rtc.c
Go to the documentation of this file.
00001 
00036 /*
00037  * $Log: ih_rtc.c,v $
00038   *
00039  */
00040 
00041 #include <arch/avr32.h>
00042 #include <arch/avr32/pm.h>
00043 #include <dev/irqreg.h>
00044 #include <avr32/io.h>
00045 
00046 #include <arch/avr32/ihndlr.h>
00047 
00048 #ifndef NUT_IRQPRI_RTC
00049 #define NUT_IRQPRI_RTC  AVR32_INTC_INT0
00050 #endif
00051 
00052 // Work around differences between ES and production chips.
00053 #ifndef AVR32_RTC_CTRL_CLKEN_MASK
00054 #define AVR32_RTC_CTRL_CLKEN_MASK AVR32_RTC_CTRL_EN_MASK
00055 #endif
00056 
00057 
00058 static int RealTimeCounterIrqCtl(int cmd, void *param);
00059 
00060 IRQ_HANDLER sig_RTC = {
00061 #ifdef NUT_PERFMON
00062     0,                          /* Interrupt counter, ir_count. */
00063 #endif
00064     NULL,                       /* Passed argument, ir_arg. */
00065     NULL,                       /* Handler subroutine, ir_handler. */
00066     RealTimeCounterIrqCtl       /* Interrupt control, ir_ctl. */
00067 };
00068 
00072 static SIGNAL(RealTimeCounterIrqEntry)
00073 {
00074     IRQ_ENTRY();
00075 #ifdef NUT_PERFMON
00076     sig_RTC.ir_count++;
00077 #endif
00078     if (sig_RTC.ir_handler) {
00079         (sig_RTC.ir_handler) (sig_RTC.ir_arg);
00080     }
00081     IRQ_EXIT();
00082 }
00083 
00097 static int RealTimeCounterIrqCtl(int cmd, void *param)
00098 {
00099     int rc = 0;
00100     unsigned int *ival = (unsigned int *) param;
00101     int_fast8_t enabled = AVR32_RTC.imr & AVR32_RTC_IMR_TOPI_MASK;
00102 
00103     /* Disable interrupt. */
00104     if (enabled) {
00105         AVR32_RTC.idr = AVR32_RTC_IDR_TOPI_MASK;
00106         AVR32_RTC.imr;
00107     }
00108 
00109     switch (cmd) {
00110     case NUT_IRQCTL_INIT:
00111         /* Enable 32k oscillator crystal */
00112         pm_enable_osc32_crystal(&AVR32_PM);
00113         pm_enable_clk32_no_wait(&AVR32_PM, AVR32_PM_OSCCTRL32_STARTUP_0_RCOSC);
00114 
00115         /* Wait until the rtc CTRL register is up-to-date */
00116         while ((AVR32_RTC.ctrl & AVR32_RTC_CTRL_BUSY_MASK));
00117 
00118         /* Set the new RTC configuration to 1ms */
00119         AVR32_RTC.ctrl = 1 << AVR32_RTC_CTRL_CLK32_OFFSET | 4 << AVR32_RTC_CTRL_PSEL_OFFSET | AVR32_RTC_CTRL_CLKEN_MASK;
00120 
00121         /* Wait until the rtc CTRL register is up-to-date */
00122         while ((AVR32_RTC.ctrl & AVR32_RTC_CTRL_BUSY_MASK));
00123 
00124         register_interrupt(RealTimeCounterIrqEntry, AVR32_RTC_IRQ, NUT_IRQPRI_RTC);
00125 
00126         break;
00127     case NUT_IRQCTL_STATUS:
00128         if (enabled) {
00129             *ival |= 1;
00130         } else {
00131             *ival &= ~1;
00132         }
00133         break;
00134     case NUT_IRQCTL_ENABLE:
00135         enabled = 1;
00136         break;
00137     case NUT_IRQCTL_DISABLE:
00138         enabled = 0;
00139         break;
00140 #ifdef NUT_PERFMON
00141     case NUT_IRQCTL_GETCOUNT:
00142         *ival = (unsigned int) sig_TC0.ir_count;
00143         sig_RTC.ir_count = 0;
00144         break;
00145 #endif
00146     default:
00147         rc = -1;
00148         break;
00149     }
00150 
00151     /* Enable interrupt. */
00152     if (enabled) {
00153         AVR32_RTC.ier = AVR32_RTC_IER_TOPI_MASK;
00154     }
00155     return rc;
00156 }