Go to the documentation of this file.00001 
00036 
00037 
00038 
00039 
00040 
00041 #include <cfg/os.h>
00042 #include <cfg/clock.h>
00043 #include <arch/avr32.h>
00044 #include <dev/irqreg.h>
00045 #include <sys/timer.h>
00046 
00047 #include <arch/avr32/ihndlr.h>
00048 
00049 #include <avr32/io.h>
00050 
00051 
00056 
00057 #ifndef NUT_TICK_FREQ
00058 #define NUT_TICK_FREQ   1000UL
00059 #endif
00060 
00061 IRQ_HANDLER sig_sysCompare = {
00062 #ifdef NUT_PERFMON
00063     0,                          
00064 #endif
00065     NULL,                       
00066     NULL,                       
00067     NULL                        
00068 };
00069 
00070 
00078 static u_int AVR32GetPllClock(int pll)
00079 {
00080     u_int rc;
00081     u_int osc = 0;
00082 
00083     if (AVR32_PM.PLL[pll].pllosc)
00084         osc = 0;
00085     else
00086         osc = OSC0_VAL;
00087 
00088     
00089 
00090 
00091 
00092     rc = osc;
00093 
00094     if (AVR32_PM.PLL[pll].pllen) {
00095         u_int divider = AVR32_PM.PLL[pll].plldiv;
00096         u_int multiplier = AVR32_PM.PLL[pll].pllmul;
00097 
00098         if (divider)
00099             rc *= (multiplier + 1) / divider;
00100         else
00101             rc *= 2 * (multiplier + 1);
00102 
00103         if (AVR32_PM.PLL[pll].pllopt)
00104             rc /= 2;
00105     }
00106     return rc;
00107 }
00108 
00114 static uint32_t Avr32GetProcessorClock(void)
00115 {
00116     u_int rc = 0;
00117     u_int mckr = AVR32_PM.mcctrl;
00118 
00119     
00120     switch (mckr & AVR32_PM_MCCTRL_MCSEL_MASK) {
00121     case AVR32_PM_MCCTRL_MCSEL_OSC0:
00122         
00123         rc = OSC0_VAL;
00124         break;
00125     case AVR32_PM_MCCTRL_MCSEL_SLOW:
00126         
00127         rc = AVR32_PM_RCOSC_FREQUENCY;
00128         break;
00129     case AVR32_PM_MCCTRL_MCSEL_PLL0:
00130         
00131         rc = AVR32GetPllClock(0);
00132         break;
00133     }
00134 
00135     
00136     if (AVR32_PM.cksel & AVR32_PM_CKSEL_CPUDIV_MASK) {
00137         int cpusel = (AVR32_PM.cksel & AVR32_PM_CKSEL_CPUSEL_MASK) >> AVR32_PM_CKSEL_CPUSEL_OFFSET;
00138         
00139         rc /= _BV(cpusel + 1);
00140     }
00141 
00142     return rc;
00143 }
00144 
00145 
00149 static SIGNAL(SystemCompareIrqEntry)
00150 {
00151     IRQ_ENTRY();
00152     uint32_t compare;
00153     compare = Get_system_register(AVR32_COMPARE);
00154     Set_system_register(AVR32_COMPARE, 0);
00155     if (sig_sysCompare.ir_handler) {
00156         (sig_sysCompare.ir_handler) (sig_sysCompare.ir_arg);
00157     }
00158 #if __AVR32_AP7000__ || __AT32AP7000__ || __AVR32_UC3A0512ES__ || __AVR32_UC3A1512ES__
00159     
00160 
00161     compare += NutGetCpuClock() / NUT_TICK_FREQ;
00162     if (!compare)               
00163         ++compare;
00164 #endif
00165     Set_system_register(AVR32_COMPARE, compare);
00166     IRQ_EXIT();
00167 }
00168 
00180 void NutRegisterTimer(void (*handler) (void *))
00181 {
00182     
00183     Set_system_register(AVR32_COMPARE, NutGetCpuClock() / NUT_TICK_FREQ + Get_system_register(AVR32_COUNT));
00184 
00185     sig_sysCompare.ir_handler = handler;
00186 
00187     register_interrupt(SystemCompareIrqEntry, AVR32_CORE_COMPARE_IRQ, AVR32_INTC_INT0);
00188 }
00189 
00199 uint32_t NutArchClockGet(int idx)
00200 {
00201     uint32_t rc = AVR32_PM_PBA_MAX_FREQ;
00202 
00203     if (idx == NUT_HWCLK_CPU || idx == NUT_HWCLK_PERIPHERAL_HSB) {
00204         rc = Avr32GetProcessorClock();
00205     } else if (idx == NUT_HWCLK_PERIPHERAL_A) {
00206         
00207         rc = Avr32GetProcessorClock();
00208 
00209         if (AVR32_PM.CKSEL.pbadiv) {
00210             rc /= _BV(AVR32_PM.CKSEL.pbasel + 1);
00211         }
00212     } else if (idx == NUT_HWCLK_PERIPHERAL_B) {
00213         
00214         rc = Avr32GetProcessorClock();
00215 
00216         if (AVR32_PM.CKSEL.pbbdiv) {
00217             rc /= _BV(AVR32_PM.CKSEL.pbbsel + 1);
00218         }
00219     } else if (idx == NUT_HWCLK_SLOW_CLOCK) {
00220         
00221 
00222 
00223 
00224 #if defined( __AVR32_AP7000__ )
00225         rc = 32768;             
00226 #else
00227         rc = AVR32_PM_RCOSC_FREQUENCY;
00228 #endif
00229     }
00230 
00231     return rc;
00232 }
00233 
00234 
00240 uint32_t NutGetTickClock(void)
00241 {
00242     return NUT_TICK_FREQ;
00243 }
00244 
00248 uint32_t NutTimerMillisToTicks(uint32_t ms)
00249 {
00250 #if (NUT_TICK_FREQ % 1000)
00251     if (ms >= 0x3E8000UL)
00252         return (ms / 1000UL) * NUT_TICK_FREQ;
00253     return (ms * NUT_TICK_FREQ + 999UL) / 1000UL;
00254 #else
00255     return ms * (NUT_TICK_FREQ / 1000UL);
00256 #endif
00257 }
00258