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