00001
00016 #include <string.h>
00017
00018 #include "em_device.h"
00019 #include "em_cmu.h"
00020 #include "em_common.h"
00021 #include "em_int.h"
00022
00023 #if defined( RTCC_PRESENT ) && ( RTCC_COUNT == 1 )
00024 #define RTCDRV_USE_RTCC
00025 #else
00026 #define RTCDRV_USE_RTC
00027 #endif
00028
00029 #if defined( RTCDRV_USE_RTCC )
00030 #include "em_rtcc.h"
00031 #else
00032 #include "em_rtc.h"
00033 #endif
00034
00035 #include "rtcdriver.h"
00036 #if defined( EMDRV_RTCDRV_SLEEPDRV_INTEGRATION )
00037 #include "sleep.h"
00038 #endif
00039
00041
00042 #if defined( EMDRV_RTCDRV_SLEEPDRV_INTEGRATION ) \
00043 && !defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG ) \
00044 && defined( RTCDRV_USE_RTC )
00045
00046 #define EMODE_DYNAMIC
00047 #endif
00048
00049 #if defined( EMDRV_RTCDRV_SLEEPDRV_INTEGRATION ) \
00050 && defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG ) \
00051 && defined( RTCDRV_USE_RTC )
00052
00053 #define EMODE_NEVER_ALLOW_EM3EM4
00054 #endif
00055
00056
00057
00058
00059 #if defined( RTCDRV_USE_RTCC )
00060 #define TIMEDIFF( a, b ) ((a) - (b))
00061 #define RTC_COUNTERGET() RTCC_CounterGet()
00062 #define RTC_COUNTER_BITS 32
00063 #define RTC_ALL_INTS _RTCC_IF_MASK
00064 #define RTC_OF_INT RTCC_IF_OF
00065 #define RTC_COMP_INT RTCC_IF_CC1
00066 #define RTC_COUNTER_MASK (_RTCC_CNT_MASK)
00067 #define RTC_MAX_VALUE (_RTCC_CNT_MASK)
00068 #define RTC_INTDISABLE( x ) RTCC_IntDisable( x )
00069 #define RTC_INTENABLE( x ) RTCC_IntEnable( x )
00070 #define RTC_INTCLEAR( x ) RTCC_IntClear( x )
00071 #define RTC_INTGET() RTCC_IntGet()
00072 #define RTC_COUNTERRESET() RTCC->CNT = _RTCC_CNT_RESETVALUE
00073 #define RTC_COMPARESET( x ) RTCC_ChannelCCVSet( 1, x )
00074 #define RTC_COMPAREGET() RTCC_ChannelCCVGet( 1 )
00075 #define NVIC_CLEARPENDINGIRQ() NVIC_ClearPendingIRQ( RTCC_IRQn )
00076 #define NVIC_DISABLEIRQ() NVIC_DisableIRQ( RTCC_IRQn )
00077 #define NVIC_ENABLEIRQ() NVIC_EnableIRQ( RTCC_IRQn )
00078
00079 #else
00080
00081
00082 #define TIMEDIFF( a, b ) ((( (a)<<8) - ((b)<<8) ) >> 8 )
00083 #define RTC_COUNTERGET() RTC_CounterGet()
00084 #define RTC_COUNTER_BITS 24
00085 #define RTC_ALL_INTS _RTC_IF_MASK
00086 #define RTC_OF_INT RTC_IF_OF
00087 #define RTC_COMP_INT RTC_IF_COMP0
00088 #define RTC_COUNTER_MASK (_RTC_CNT_MASK)
00089 #define RTC_MAX_VALUE (_RTC_CNT_MASK)
00090 #define RTC_INTDISABLE( x ) RTC_IntDisable( x )
00091 #define RTC_INTENABLE( x ) RTC_IntEnable( x )
00092 #define RTC_INTCLEAR( x ) RTC_IntClear( x )
00093 #define RTC_INTGET() RTC_IntGet()
00094 #define RTC_COUNTERRESET() RTC_CounterReset()
00095 #define RTC_COMPARESET( x ) RTC_CompareSet( 0, (x) & _RTC_COMP0_MASK )
00096 #define RTC_COMPAREGET() RTC_CompareGet( 0 )
00097 #define NVIC_CLEARPENDINGIRQ() NVIC_ClearPendingIRQ( RTC_IRQn )
00098 #define NVIC_DISABLEIRQ() NVIC_DisableIRQ( RTC_IRQn )
00099 #define NVIC_ENABLEIRQ() NVIC_EnableIRQ( RTC_IRQn )
00100 #endif
00101
00102
00103 #define MAX_RTC_TICK_CNT (RTC_MAX_VALUE+1UL)
00104 #define RTC_CLOSE_TO_MAX_VALUE (RTC_MAX_VALUE-100UL)
00105
00106 #if defined(_EFM32_GECKO_FAMILY)
00107
00108 #define RTC_DIVIDER ( cmuClkDiv_2 )
00109 #else
00110
00111 #define RTC_DIVIDER ( cmuClkDiv_8 )
00112 #endif
00113
00114 #define RTC_CLOCK ( 32768U )
00115 #define MSEC_TO_TICKS_DIVIDER ( 1000U * RTC_DIVIDER )
00116 #define MSEC_TO_TICKS_ROUNDING_FACTOR ( MSEC_TO_TICKS_DIVIDER / 2 )
00117 #define MSEC_TO_TICKS( ms ) ( ( ( (uint64_t)(ms) * RTC_CLOCK ) \
00118 + MSEC_TO_TICKS_ROUNDING_FACTOR ) \
00119 / MSEC_TO_TICKS_DIVIDER )
00120
00121 #define TICKS_TO_MSEC_ROUNDING_FACTOR ( RTC_CLOCK / 2 )
00122 #define TICKS_TO_MSEC( ticks ) ( ( ( (uint64_t)(ticks) \
00123 * RTC_DIVIDER * 1000U ) \
00124 + TICKS_TO_MSEC_ROUNDING_FACTOR ) \
00125 / RTC_CLOCK )
00126
00127 #define TICKS_TO_SEC_ROUNDING_FACTOR ( RTC_CLOCK / 2 )
00128 #define TICKS_TO_SEC( ticks ) ( ( ( (uint64_t)(ticks) \
00129 * RTC_DIVIDER ) \
00130 + TICKS_TO_SEC_ROUNDING_FACTOR ) \
00131 / RTC_CLOCK )
00132 #define TICK_TIME_USEC ( 1000000 * RTC_DIVIDER / RTC_CLOCK )
00133
00134 typedef struct Timer
00135 {
00136 uint64_t remaining;
00137 uint64_t ticks;
00138 int periodicCompensationUsec;
00139 unsigned int periodicDriftUsec;
00140 RTCDRV_Callback_t callback;
00141 bool running;
00142 bool doCallback;
00143 bool allocated;
00144 RTCDRV_TimerType_t timerType;
00145 void *user;
00146 } Timer_t;
00147
00148 static Timer_t timer[ EMDRV_RTCDRV_NUM_TIMERS ];
00149 static uint32_t lastStart;
00150 static volatile uint32_t startTimerNestingLevel;
00151 static bool inTimerIRQ;
00152 static bool rtcRunning;
00153 static bool rtcdrvIsInitialized = false;
00154 #if defined( EMODE_DYNAMIC )
00155 static bool sleepBlocked;
00156 #endif
00157
00158 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00159 static volatile uint32_t wallClockOverflowCnt;
00160 static uint32_t wallClockTimeBase;
00161 #endif
00162
00163 #if defined( RTCDRV_USE_RTC )
00164 static const RTC_Init_TypeDef initRTC =
00165 {
00166 true,
00167 false,
00168 false
00169 };
00170
00171 #elif defined( RTCDRV_USE_RTCC )
00172 static RTCC_Init_TypeDef initRTCC =
00173 {
00174 true,
00175 false,
00176 false,
00177 false,
00178 rtccCntPresc_8,
00179 rtccCntTickPresc,
00180 false,
00181 false,
00182 rtccCntModeNormal,
00183 false
00184 };
00185
00186 static RTCC_CCChConf_TypeDef initRTCCCompareChannel =
00187 {
00188 rtccCapComChModeCompare,
00189 rtccCompMatchOutActionPulse,
00190 rtccPRSCh0,
00191 rtccInEdgeNone,
00192 rtccCompBaseCnt,
00193 0,
00194 rtccDayCompareModeMonth
00195 };
00196 #endif
00197
00198 static void checkAllTimers( uint32_t timeElapsed );
00199 static void delayTicks( uint32_t ticks );
00200 static void executeTimerCallbacks( void );
00201 static void rescheduleRtc( uint32_t rtcCnt );
00202
00204
00205
00219 Ecode_t RTCDRV_AllocateTimer( RTCDRV_TimerID_t *id )
00220 {
00221 int i = 0;
00222 int retVal = 0;
00223
00224 INT_Disable();
00225
00226 while ( ( i < EMDRV_RTCDRV_NUM_TIMERS ) && ( timer[ i ].allocated ) ) {
00227 i++;
00228 }
00229
00230
00231 if ( i == EMDRV_RTCDRV_NUM_TIMERS ) {
00232 retVal = ECODE_EMDRV_RTCDRV_ALL_TIMERS_USED;
00233 } else {
00234
00235 if ( id != NULL ) {
00236 timer[ i ].allocated = true;
00237 *id = i;
00238 retVal = ECODE_EMDRV_RTCDRV_OK;
00239 } else {
00240 retVal = ECODE_EMDRV_RTCDRV_PARAM_ERROR;
00241 }
00242 }
00243 INT_Enable();
00244
00245 return retVal;
00246 }
00247
00248
00257 Ecode_t RTCDRV_Delay( uint32_t ms )
00258 {
00259 uint64_t totalTicks;
00260
00261 totalTicks = MSEC_TO_TICKS( ms );
00262
00263 while ( totalTicks > RTC_CLOSE_TO_MAX_VALUE ) {
00264 delayTicks( RTC_CLOSE_TO_MAX_VALUE );
00265 totalTicks -= RTC_CLOSE_TO_MAX_VALUE;
00266 }
00267 delayTicks( totalTicks );
00268
00269 return ECODE_EMDRV_RTCDRV_OK;
00270 }
00271
00272
00285 Ecode_t RTCDRV_FreeTimer( RTCDRV_TimerID_t id )
00286 {
00287
00288 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00289 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00290 }
00291
00292 INT_Disable();
00293
00294 timer[ id ].running = false;
00295 timer[ id ].allocated = false;
00296
00297 INT_Enable();
00298
00299 return ECODE_EMDRV_RTCDRV_OK;
00300 }
00301
00302
00313 Ecode_t RTCDRV_Init( void )
00314 {
00315 if ( rtcdrvIsInitialized == true ) {
00316 return ECODE_EMDRV_RTCDRV_OK;
00317 }
00318 rtcdrvIsInitialized = true;
00319
00320
00321 CMU_ClockEnable( cmuClock_CORELE, true );
00322
00323 #if defined( CMU_LFECLKEN0_RTCC )
00324
00325 CMU_ClockSelectSet( cmuClock_LFE, cmuSelect_LFXO );
00326 #else
00327
00328 CMU_ClockSelectSet( cmuClock_LFA, cmuSelect_LFXO );
00329 #endif
00330
00331 #if defined( RTCDRV_USE_RTC )
00332
00333 CMU_ClockDivSet( cmuClock_RTC, RTC_DIVIDER );
00334
00335
00336 CMU_ClockEnable( cmuClock_RTC, true );
00337
00338
00339 RTC_Init( &initRTC );
00340
00341 #elif defined( RTCDRV_USE_RTCC )
00342
00343 initRTCC.presc = (RTCC_CntPresc_TypeDef)CMU_DivToLog2( RTC_DIVIDER );
00344
00345
00346 CMU_ClockEnable( cmuClock_RTCC, true );
00347
00348
00349 RTCC_Init( &initRTCC );
00350
00351
00352 RTCC_ChannelInit( 1, &initRTCCCompareChannel );
00353 #endif
00354
00355
00356 RTC_INTDISABLE( RTC_ALL_INTS );
00357 RTC_INTCLEAR( RTC_ALL_INTS );
00358
00359 RTC_COUNTERRESET();
00360
00361
00362 NVIC_CLEARPENDINGIRQ();
00363 NVIC_ENABLEIRQ();
00364
00365 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00366
00367 RTC_INTENABLE( RTC_OF_INT );
00368 #endif
00369
00370
00371 memset( timer, 0, sizeof( timer ) );
00372 inTimerIRQ = false;
00373 rtcRunning = false;
00374 startTimerNestingLevel = 0;
00375 #if defined( EMODE_DYNAMIC )
00376 sleepBlocked = false;
00377 #endif
00378
00379 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00380 wallClockOverflowCnt = 0;
00381 wallClockTimeBase = 0;
00382
00383 #if defined( EMODE_NEVER_ALLOW_EM3EM4 )
00384
00385 SLEEP_SleepBlockBegin( sleepEM3 );
00386 #endif
00387
00388 #endif
00389
00390 return ECODE_EMDRV_RTCDRV_OK;
00391 }
00392
00393
00406 Ecode_t RTCDRV_DeInit( void )
00407 {
00408
00409 NVIC_DISABLEIRQ();
00410 RTC_INTDISABLE( RTC_ALL_INTS );
00411 RTC_INTCLEAR( RTC_ALL_INTS );
00412 NVIC_CLEARPENDINGIRQ();
00413
00414
00415 #if defined( RTCDRV_USE_RTC )
00416 RTC_Enable( false );
00417 CMU_ClockEnable( cmuClock_RTC, false );
00418 #elif defined( RTCDRV_USE_RTCC )
00419 RTCC_Enable( false );
00420 CMU_ClockEnable( cmuClock_RTCC, false );
00421 #endif
00422
00423 #if defined( EMODE_NEVER_ALLOW_EM3EM4 )
00424
00425 SLEEP_SleepBlockEnd( sleepEM3 );
00426 #endif
00427
00428 #if defined( EMODE_DYNAMIC )
00429
00430 if ( sleepBlocked ) {
00431 SLEEP_SleepBlockEnd( sleepEM3 );
00432 }
00433 #endif
00434
00435
00436 rtcdrvIsInitialized = false;
00437
00438 return ECODE_EMDRV_RTCDRV_OK;
00439 }
00440
00441
00457 Ecode_t RTCDRV_IsRunning( RTCDRV_TimerID_t id, bool *isRunning )
00458 {
00459
00460 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00461 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00462 }
00463
00464
00465 if ( isRunning == NULL ) {
00466 return ECODE_EMDRV_RTCDRV_PARAM_ERROR;
00467 }
00468
00469 INT_Disable();
00470
00471 if ( ! timer[ id ].allocated ) {
00472 INT_Enable();
00473 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00474 }
00475 *isRunning = timer[ id ].running;
00476 INT_Enable();
00477
00478 return ECODE_EMDRV_RTCDRV_OK;
00479 }
00480
00481
00502 Ecode_t RTCDRV_StartTimer( RTCDRV_TimerID_t id,
00503 RTCDRV_TimerType_t type,
00504 uint32_t timeout,
00505 RTCDRV_Callback_t callback,
00506 void *user )
00507 {
00508 uint32_t timeElapsed, cnt, compVal, loopCnt = 0;
00509 uint32_t timeToNextTimerCompletion;
00510
00511
00512 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00513 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00514 }
00515
00516 INT_Disable();
00517 if ( ! timer[ id ].allocated ) {
00518 INT_Enable();
00519 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00520 }
00521
00522 if ( timeout == 0 ) {
00523 if ( callback != NULL ) {
00524 callback( id, user );
00525 }
00526 INT_Enable();
00527 return ECODE_EMDRV_RTCDRV_OK;
00528 }
00529
00530 cnt = RTC_COUNTERGET();
00531
00532 timer[ id ].callback = callback;
00533 timer[ id ].ticks = MSEC_TO_TICKS( timeout );
00534 if (rtcdrvTimerTypePeriodic == type) {
00535
00536 timer[ id ].periodicCompensationUsec = 1000 * timeout -
00537 (timer[ id ].ticks * TICK_TIME_USEC);
00538 timer[ id ].periodicDriftUsec = TICK_TIME_USEC/2;
00539 }
00540
00541 timer[ id ].remaining = timer[ id ].ticks + 1;
00542 timer[ id ].running = true;
00543 timer[ id ].timerType = type;
00544 timer[ id ].user = user;
00545
00546 if ( inTimerIRQ == true ) {
00547
00548 INT_Enable();
00549 return ECODE_EMDRV_RTCDRV_OK;
00550 }
00551
00552
00553 if ( startTimerNestingLevel < UINT32_MAX ) {
00554 startTimerNestingLevel++;
00555 }
00556
00557 if ( rtcRunning == false ) {
00558
00559 #if defined( RTCDRV_USE_RTC )
00560 lastStart = ( cnt ) & RTC_COUNTER_MASK;
00561 #elif defined( RTCDRV_USE_RTCC )
00562 lastStart = cnt;
00563 #endif
00564
00565 RTC_INTCLEAR( RTC_COMP_INT );
00566
00567 compVal = EFM32_MIN( timer[ id ].remaining, RTC_CLOSE_TO_MAX_VALUE );
00568 RTC_COMPARESET( cnt + compVal );
00569
00570
00571 RTC_INTENABLE( RTC_COMP_INT );
00572
00573 #if defined( EMODE_DYNAMIC )
00574
00575 if ( sleepBlocked == false ) {
00576 sleepBlocked = true;
00577 SLEEP_SleepBlockBegin( sleepEM3 );
00578 }
00579 #endif
00580
00581 rtcRunning = true;
00582
00583 } else {
00584
00585
00586
00587
00588
00589 if ( startTimerNestingLevel == 1 ) {
00590
00591 timer[ id ].running = false;
00592
00593 do {
00594
00595 RTC_INTDISABLE( RTC_COMP_INT );
00596
00597 timeElapsed = TIMEDIFF( cnt, lastStart );
00598 #if defined( RTCDRV_USE_RTC )
00599
00600
00601 if ( timeElapsed == RTC_MAX_VALUE ) {
00602 timeElapsed = 0;
00603 }
00604 #endif
00605
00606
00607 checkAllTimers( timeElapsed );
00608
00609
00610 executeTimerCallbacks();
00611
00612
00613 if ( loopCnt == 0 ) {
00614 timer[ id ].running = true;
00615 }
00616 loopCnt++;
00617
00618
00619 rescheduleRtc( cnt );
00620
00621 cnt = RTC_COUNTERGET();
00622 timeElapsed = TIMEDIFF( cnt, lastStart );
00623 timeToNextTimerCompletion = TIMEDIFF( RTC_COMPAREGET(), lastStart );
00624
00625
00626
00627
00628 }
00629 while ( rtcRunning && (timeElapsed > timeToNextTimerCompletion));
00630 }
00631 }
00632
00633 if ( startTimerNestingLevel > 0 ) {
00634 startTimerNestingLevel--;
00635 }
00636
00637 INT_Enable();
00638 return ECODE_EMDRV_RTCDRV_OK;
00639 }
00640
00641
00652 Ecode_t RTCDRV_StopTimer( RTCDRV_TimerID_t id )
00653 {
00654
00655 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00656 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00657 }
00658
00659 INT_Disable();
00660 if ( ! timer[ id ].allocated ) {
00661 INT_Enable();
00662 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00663 }
00664
00665 timer[ id ].running = false;
00666 INT_Enable();
00667
00668 return ECODE_EMDRV_RTCDRV_OK;
00669 }
00670
00671
00687 Ecode_t RTCDRV_TimeRemaining( RTCDRV_TimerID_t id, uint32_t *timeRemaining )
00688 {
00689 uint64_t tmp;
00690 uint32_t timeLeft, currentCnt, lastRtcStart;
00691
00692
00693 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00694 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00695 }
00696
00697
00698 if ( timeRemaining == NULL ) {
00699 return ECODE_EMDRV_RTCDRV_PARAM_ERROR;
00700 }
00701
00702 INT_Disable();
00703
00704 if ( ! timer[ id ].allocated ) {
00705 INT_Enable();
00706 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00707 }
00708
00709
00710 if ( ! timer[ id ].running ) {
00711 INT_Enable();
00712 return ECODE_EMDRV_RTCDRV_TIMER_NOT_RUNNING;
00713 }
00714
00715 timeLeft = timer[ id ].remaining;
00716 currentCnt = RTC_COUNTERGET();
00717 lastRtcStart = lastStart;
00718 INT_Enable();
00719
00720
00721 currentCnt = TIMEDIFF( currentCnt, lastRtcStart );
00722
00723 if ( currentCnt > timeLeft ) {
00724 timeLeft = 0;
00725 } else {
00726 timeLeft -= currentCnt;
00727 }
00728
00729 tmp = TICKS_TO_MSEC( timeLeft );
00730 *timeRemaining = tmp;
00731
00732 return ECODE_EMDRV_RTCDRV_OK;
00733 }
00734
00735 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00736
00743 uint32_t RTCDRV_GetWallClock( void )
00744 {
00745 return wallClockTimeBase
00746 + (uint32_t)TICKS_TO_SEC( RTCDRV_GetWallClockTicks32() );
00747 }
00748 #endif
00749
00750 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00751
00759 uint32_t RTCDRV_GetWallClockTicks32( void )
00760 {
00761 uint32_t overflows, ticks;
00762
00763
00764 do
00765 {
00766 overflows = wallClockOverflowCnt;
00767 ticks = RTC_COUNTERGET();
00768 } while ( overflows != wallClockOverflowCnt );
00769
00770 #if ( RTC_COUNTER_BITS < 32 )
00771 return ( overflows << RTC_COUNTER_BITS ) + ticks;
00772 #else
00773 return ticks;
00774 #endif
00775 }
00776 #endif
00777
00778 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00779
00786 uint64_t RTCDRV_GetWallClockTicks64( void )
00787 {
00788 uint64_t overflows, ticks;
00789
00790
00791 do
00792 {
00793 overflows = wallClockOverflowCnt;
00794 ticks = RTC_COUNTERGET();
00795 } while ( overflows != wallClockOverflowCnt );
00796
00797 return ( overflows << RTC_COUNTER_BITS ) + ticks;
00798 }
00799 #endif
00800
00801 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00802
00811 Ecode_t RTCDRV_SetWallClock( uint32_t secs )
00812 {
00813 wallClockTimeBase = secs - TICKS_TO_SEC( RTCDRV_GetWallClockTicks32() );
00814 return ECODE_EMDRV_RTCDRV_OK;
00815 }
00816 #endif
00817
00818 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00819
00828 uint64_t RTCDRV_MsecsToTicks( uint32_t ms )
00829 {
00830 return MSEC_TO_TICKS( ms );
00831 }
00832 #endif
00833
00834 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00835
00844 uint64_t RTCDRV_SecsToTicks( uint32_t secs )
00845 {
00846 return MSEC_TO_TICKS( 1000 * secs );
00847 }
00848 #endif
00849
00850 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00851
00860 uint32_t RTCDRV_TicksToMsec( uint64_t ticks )
00861 {
00862 return TICKS_TO_MSEC( ticks );
00863 }
00864 #endif
00865
00866 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00867
00876 uint32_t RTCDRV_TicksToSec( uint64_t ticks )
00877 {
00878 return TICKS_TO_MSEC( ticks ) / 1000;
00879 }
00880 #endif
00881
00883
00884 #if defined( RTCDRV_USE_RTC )
00885 void RTC_IRQHandler(void)
00886 #elif defined( RTCDRV_USE_RTCC )
00887 void RTCC_IRQHandler(void)
00888 #endif
00889 {
00890 uint32_t flags, timeElapsed, cnt, timeToNextTimerCompletion;
00891
00892 INT_Disable();
00893
00894
00895
00896
00897 flags = RTC_INTGET();
00898
00899 if ( flags & RTC_COMP_INT ) {
00900
00901
00902
00903
00904
00905
00906 inTimerIRQ = true;
00907
00908 cnt = RTC_COUNTERGET();
00909
00910
00911 do {
00912
00913 RTC_INTDISABLE( RTC_COMP_INT );
00914
00915 timeElapsed = TIMEDIFF( cnt, lastStart );
00916
00917
00918 checkAllTimers( timeElapsed );
00919
00920
00921 executeTimerCallbacks();
00922
00923
00924 rescheduleRtc( cnt );
00925
00926 cnt = RTC_COUNTERGET();
00927 timeElapsed = TIMEDIFF( cnt, lastStart );
00928 timeToNextTimerCompletion = TIMEDIFF( RTC_COMPAREGET(), lastStart );
00929
00930
00931
00932 }
00933 while ( rtcRunning && (timeElapsed > timeToNextTimerCompletion));
00934 inTimerIRQ = false;
00935 }
00936
00937 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00938 if ( flags & RTC_OF_INT )
00939 {
00940 RTC_INTCLEAR( RTC_OF_INT );
00941 wallClockOverflowCnt++;
00942 }
00943 #endif
00944
00945 INT_Enable();
00946 }
00947
00948 static void checkAllTimers( uint32_t timeElapsed )
00949 {
00950 int i;
00951 #if defined( EMODE_DYNAMIC )
00952 int numOfTimersRunning = 0;
00953 #endif
00954
00955
00956
00957
00958
00959 for ( i = 0; i < EMDRV_RTCDRV_NUM_TIMERS; i++ ) {
00960 timer[ i ].doCallback = false;
00961 if ( timer[ i ].running == true ) {
00962 #if defined( EMODE_DYNAMIC )
00963 numOfTimersRunning++;
00964 #endif
00965 if ( timer[ i ].remaining > timeElapsed ) {
00966 timer[ i ].remaining -= timeElapsed;
00967 } else {
00968 if ( timer[ i ].timerType == rtcdrvTimerTypeOneshot ) {
00969 timer[ i ].running = false;
00970 #if defined( EMODE_DYNAMIC )
00971 numOfTimersRunning--;
00972 #endif
00973 } else {
00974
00975 timer[ i ].remaining = timer[ i ].ticks - timeElapsed +
00976 timer[ i ].remaining;
00977 if ( timer[ i ].periodicCompensationUsec > 0 ) {
00978 timer[ i ].periodicDriftUsec += timer[i].periodicCompensationUsec;
00979 if (timer[ i ].periodicDriftUsec >= TICK_TIME_USEC) {
00980
00981
00982 timer[ i ].remaining += 1;
00983 timer[ i ].periodicDriftUsec -= TICK_TIME_USEC;
00984 }
00985 }
00986 else {
00987 timer[ i ].periodicDriftUsec -= timer[i].periodicCompensationUsec;
00988 if (timer[ i ].periodicDriftUsec >= TICK_TIME_USEC) {
00989
00990
00991 timer[ i ].remaining -= 1;
00992 timer[ i ].periodicDriftUsec -= TICK_TIME_USEC;
00993 }
00994 }
00995 }
00996 if ( timer[ i ].callback != NULL ) {
00997 timer[ i ].doCallback = true;
00998 }
00999 }
01000 }
01001 }
01002
01003 #if defined( EMODE_DYNAMIC )
01004
01005 if ( ( numOfTimersRunning == 0 ) && ( sleepBlocked == true ) ) {
01006 sleepBlocked = false;
01007 SLEEP_SleepBlockEnd( sleepEM3 );
01008 }
01009 #endif
01010 }
01011
01012 static void delayTicks( uint32_t ticks )
01013 {
01014 uint32_t startTime;
01015 volatile uint32_t now;
01016
01017 if ( ticks ) {
01018 startTime = RTC_COUNTERGET();
01019 do {
01020 now = RTC_COUNTERGET();
01021 } while ( TIMEDIFF( now, startTime ) < ticks );
01022 }
01023 }
01024
01025 static void executeTimerCallbacks( void )
01026 {
01027 int i;
01028
01029 for ( i = 0; i < EMDRV_RTCDRV_NUM_TIMERS; i++ ) {
01030 if ( timer[ i ].doCallback ) {
01031 timer[ i ].callback( i, timer[ i ].user );
01032 }
01033 }
01034 }
01035
01036 static void rescheduleRtc( uint32_t rtcCnt )
01037 {
01038 int i;
01039 uint64_t min = UINT64_MAX;
01040
01041
01042 for ( i = 0; i < EMDRV_RTCDRV_NUM_TIMERS; i++ ) {
01043 if ( ( timer[ i ].running == true )
01044 && ( timer[ i ].remaining < min ) ) {
01045 min = timer[ i ].remaining;
01046 }
01047 }
01048
01049 rtcRunning = false;
01050 if ( min != UINT64_MAX ) {
01051 min = EFM32_MIN( min, RTC_CLOSE_TO_MAX_VALUE );
01052 #if defined( RTCDRV_USE_RTC )
01053 if ( inTimerIRQ == false ) {
01054 lastStart = ( rtcCnt ) & RTC_COUNTER_MASK;
01055 } else
01056 #endif
01057 {
01058 lastStart = rtcCnt;
01059 }
01060 RTC_INTCLEAR( RTC_COMP_INT );
01061
01062 RTC_COMPARESET( rtcCnt + min );
01063
01064 #if defined( EMODE_DYNAMIC )
01065
01066 if ( sleepBlocked == false ) {
01067 sleepBlocked = true;
01068 SLEEP_SleepBlockBegin( sleepEM3 );
01069 }
01070 #endif
01071
01072 rtcRunning = true;
01073
01074
01075 RTC_INTENABLE( RTC_COMP_INT );
01076 }
01077 }
01079
01080