ostimer.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 #include <cfg/os.h>
00105 #include <sys/atom.h>
00106 #include <dev/irqreg.h>
00107 #include <arch/timer.h>
00108
00118 #ifndef NUT_TICK_NFREQ
00119 #ifdef NUT_CPU_FREQ
00120 #define NUT_TICK_NFREQ 1000L
00121 #else
00122 #define NUT_TICK_NFREQ 1024L
00123 #endif
00124 #endif
00125
00126 #ifdef NUT_CPU_FREQ
00127 #ifndef NUT_TIMER_CRYSTAL
00128 #define NUT_TIMER_CRYSTAL NUT_CPU_FREQ
00129 #endif
00130 #ifndef NUT_TIMER_PRESCALE
00131 #define NUT_TIMER_PRESCALE 128
00132 #endif
00133 #else
00134 #ifndef NUT_TIMER_CRYSTAL
00135 #define NUT_TIMER_CRYSTAL 32768L
00136 #endif
00137 #ifndef NUT_TIMER_PRESCALE
00138 #define NUT_TIMER_PRESCALE 1
00139 #endif
00140 #endif
00141
00142
00143 #define OCR_VALUE (((2 * NUT_TIMER_CRYSTAL / (NUT_TIMER_PRESCALE * NUT_TICK_NFREQ) + 1) / 2) - 1)
00144
00145
00146 #define NUT_TICK_FREQ ((2 * NUT_TIMER_CRYSTAL / (OCR_VALUE + 1) / NUT_TIMER_PRESCALE + 1) / 2)
00147
00148
00149 #ifdef NUT_CPU_FREQ
00150 #if defined(MCU_AT90CAN128)
00151 #define TCCR_FLAGS (_BV(CS20) | _BV(CS22) | _BV(WGM21))
00152 #elif defined(MCU_ATMEGA2560)
00153 #define TCCR_FLAGS (_BV(WGM21))
00154 #define TCCR2B_FLAGS (_BV(CS20) | _BV(CS22))
00155 #elif defined(MCU_ATMEGA2561)
00156 #define TCCR_FLAGS (_BV(WGM21))
00157 #define TCCR2B_FLAGS (_BV(CS20) | _BV(CS22))
00158 #elif defined(MCU_ATMEGA103)
00159 #define TCCR_FLAGS (_BV(CS00) | _BV(CS02) | _BV(CTC0))
00160 #else
00161 #define TCCR_FLAGS (_BV(CS00) | _BV(CS02) | _BV(WGM01))
00162 #endif
00163 #else
00164 #if defined(MCU_ATMEGA103)
00165 #define TCCR_FLAGS (_BV(CS00) | _BV(CTC0))
00166 #define TCCR_AFLAGS _BV(CS01)
00167 #define ASSR_BIT AS0
00168 #define ASSR_BUSY (_BV(TCN0UB) | _BV(OCR0UB) | _BV(TCR0UB))
00169 #elif defined(MCU_ATMEGA128)
00170 #define TCCR_FLAGS (_BV(CS00) | _BV(WGM01))
00171 #define TCCR_AFLAGS _BV(CS01)
00172 #define ASSR_BIT AS0
00173 #define ASSR_BUSY (_BV(TCN0UB) | _BV(OCR0UB) | _BV(TCR0UB))
00174 #else
00175 #error Define NUT_CPU_FREQ to compile for this CPU.
00176 #endif
00177 #endif
00178
00179 #if defined(MCU_AT90CAN128) || defined(MCU_ATMEGA2560) || defined(MCU_ATMEGA2561)
00180 #define TCCRx TCCR2A
00181 #define TCNTx TCNT2
00182 #define OCRx OCR2A
00183 #define TIFR_OCFx _BV(OCF2A)
00184 #define TIFR_TOVx _BV(TOV2)
00185 #define sig_TIMER sig_OUTPUT_COMPARE2
00186 #else
00187 #define TCCRx TCCR0
00188 #define TCNTx TCNT0
00189 #define OCRx OCR0
00190 #define TIFR_OCFx _BV(OCF0)
00191 #define TIFR_TOVx _BV(TOV0)
00192 #define sig_TIMER sig_OUTPUT_COMPARE0
00193 #endif
00194
00195 static uint32_t cpu_clock;
00196
00202 #ifndef NUT_CPU_FREQ
00203 static uint32_t CountCpuLoops(void)
00204 {
00205 #ifdef __GNUC__
00206 uint32_t rc = 1;
00207
00208 __asm__ __volatile__("firstovf: \n\t"
00209 "in %D0,%1 \n\t"
00210 "andi %D0,%2 \n\t"
00211 "breq firstovf \n\t"
00212 "out %1,%D0 \n\n"
00213
00214 "nextovf: \n\t"
00215 "sec \n\t"
00216 "adc %A0,__zero_reg__ \n\t"
00217 "adc %B0,__zero_reg__ \n\t"
00218 "adc %C0,__zero_reg__ \n\t"
00219 "in %D0,%1 \n\t"
00220 "andi %D0,%2 \n\t"
00221 "breq nextovf \n\t"
00222 "clr %D0 "
00223 :"=d"(rc)
00224 :"I"(_SFR_IO_ADDR(TIFR))
00225 , "I"(TIFR_TOVx)
00226 , "0"(rc)
00227 );
00228 return rc;
00229 #elif defined(__IMAGECRAFT__)
00230 uint32_t rc;
00231
00232 asm("CLR R0");
00233 asm("CLR R16");
00234 asm("CLR R17");
00235 asm("CLR R18");
00236 asm("firstovf:");
00237 asm("IN R19, 0x36");
00238 asm("ANDI R19,1");
00239 asm("BREQ firstovf");
00240 asm("OUT 0x36, R19");
00241
00242 asm("nextovf:");
00243 asm("SEC");
00244 asm("ADC R16, R0");
00245 asm("ADC R17, R0");
00246 asm("ADC R18, R0");
00247 asm("IN R19, 0x36");
00248 asm("ANDI R19, 1");
00249 asm("BREQ nextovf");
00250 asm("CLR R19");
00251 asm("STD Y+0, R16");
00252 asm("STD Y+1, R17");
00253 asm("STD Y+2, R18");
00254 asm("STD Y+3, R19");
00255
00256 return rc;
00257 #endif
00258 }
00259 #endif
00260
00270 #ifndef NUT_CPU_FREQ
00271 static uint32_t NutComputeCpuClock(void)
00272 {
00273 uint32_t rc;
00274
00275
00276 NutDisableTimerIrq();
00277
00278
00279 sbi(ASSR, ASSR_BIT);
00280
00281
00282 outb(TCNTx, 0);
00283
00284
00285 outb(TCCRx, TCCR_AFLAGS);
00286
00287
00288 while ((inb(ASSR) & ASSR_BUSY) != 0);
00289
00290
00291 outb(TIFR, TIFR_TOVx);
00292
00293 NutEnterCritical();
00294 rc = CountCpuLoops();
00295 NutExitCritical();
00296
00297 return rc << 7;
00298 }
00299 #endif
00300
00309 void NutRegisterTimer(void (*handler) (void *))
00310 {
00311 #ifdef NUT_CPU_FREQ
00312 cpu_clock = NUT_CPU_FREQ;
00313 #else
00314 cpu_clock = NutComputeCpuClock();
00315 #endif
00316
00317
00318 NutDisableTimerIrq();
00319
00320 #ifndef NUT_CPU_FREQ
00321
00322 sbi(ASSR, ASSR_BIT);
00323 #endif
00324
00325
00326 outb(TCNTx, 0);
00327
00328
00329 outb(TCCRx, TCCR_FLAGS);
00330 #ifdef TCCR2B_FLAGS
00331 outb(TCCR2B, TCCR2B_FLAGS);
00332 #endif
00333
00334
00335 outb(OCRx, OCR_VALUE);
00336
00337 #ifndef NUT_CPU_FREQ
00338
00339 while ((inb(ASSR) & ASSR_BUSY) != 0);
00340 #endif
00341
00342
00343 outb(TIFR, TIFR_OCFx);
00344
00345
00346 NutRegisterIrqHandler(&sig_TIMER, handler, 0);
00347 }
00348
00354 uint32_t NutArchClockGet(int idx)
00355 {
00356 return cpu_clock;
00357 }
00358
00364 uint32_t NutGetTickClock(void)
00365 {
00366 return NUT_TICK_FREQ;
00367 }
00368
00372 uint32_t NutTimerMillisToTicks(uint32_t ms)
00373 {
00374 uint32_t x;
00375
00376 x = ms * NutGetTickClock() / 1000UL;
00377 if (x == 0) {
00378 x = 1;
00379 }
00380
00381 return (x);
00382 }
00383