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( _EFM_DEVICE )
00024 #include "em_rtc.h"
00025 #elif defined( _EFR_DEVICE )
00026 #include "em_rtcc.h"
00027 #endif
00028
00029 #include "rtcdriver.h"
00030 #if defined( EMDRV_RTCDRV_SLEEPDRV_INTEGRATION )
00031 #include "sleep.h"
00032 #endif
00033
00035
00036 #if defined( EMDRV_RTCDRV_SLEEPDRV_INTEGRATION ) \
00037 && !defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG ) \
00038 && defined( _EFM_DEVICE )
00039
00040 #define EMODE_DYNAMIC
00041 #endif
00042
00043 #if defined( EMDRV_RTCDRV_SLEEPDRV_INTEGRATION ) \
00044 && defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG ) \
00045 && defined( _EFM_DEVICE )
00046
00047 #define EMODE_NEVER_ALLOW_EM3EM4
00048 #endif
00049
00050
00051
00052
00053 #if defined( _EFM_DEVICE )
00054
00055
00056 #define TIMEDIFF( a, b ) ((( (a)<<8) - ((b)<<8) ) >> 8 )
00057 #define RTC_COUNTERGET() RTC_CounterGet()
00058 #define RTC_ALL_INTS _RTC_IF_MASK
00059 #define RTC_OF_INT RTC_IF_OF
00060 #define RTC_COMP_INT RTC_IF_COMP0
00061 #define RTC_COUNTER_MASK (_RTC_CNT_MASK)
00062 #define RTC_MAX_VALUE (_RTC_CNT_MASK)
00063 #define RTC_INTDISABLE( x ) RTC_IntDisable( x )
00064 #define RTC_INTENABLE( x ) RTC_IntEnable( x )
00065 #define RTC_INTCLEAR( x ) RTC_IntClear( x )
00066 #define RTC_INTGET() RTC_IntGet()
00067 #define RTC_COUNTERRESET() RTC_CounterReset()
00068 #define RTC_COMPARESET( x ) RTC_CompareSet( 0, (x) & _RTC_COMP0_MASK )
00069 #define RTC_COMPAREGET() RTC_CompareGet( 0 )
00070 #define NVIC_CLEARPENDINGIRQ() NVIC_ClearPendingIRQ( RTC_IRQn )
00071 #define NVIC_DISABLEIRQ() NVIC_DisableIRQ( RTC_IRQn )
00072 #define NVIC_ENABLEIRQ() NVIC_EnableIRQ( RTC_IRQn )
00073
00074 #elif defined( _EFR_DEVICE )
00075 #define TIMEDIFF( a, b ) ((a) - (b))
00076 #define RTC_COUNTERGET() RTCC_CounterGet()
00077 #define RTC_ALL_INTS _RTCC_IF_MASK
00078 #define RTC_OF_INT RTCC_IF_OF
00079 #define RTC_COMP_INT RTCC_IF_CC1
00080 #define RTC_COUNTER_MASK (_RTCC_CNT_MASK)
00081 #define RTC_MAX_VALUE (_RTCC_CNT_MASK)
00082 #define RTC_INTDISABLE( x ) RTCC_IntDisable( x )
00083 #define RTC_INTENABLE( x ) RTCC_IntEnable( x )
00084 #define RTC_INTCLEAR( x ) RTCC_IntClear( x )
00085 #define RTC_INTGET() RTCC_IntGet()
00086 #define RTC_COUNTERRESET() RTCC->CNT = _RTCC_CNT_RESETVALUE
00087 #define RTC_COMPARESET( x ) RTCC_CapComSet( 1, x )
00088 #define RTC_COMPAREGET() RTCC_CapComGet( 1 )
00089 #define NVIC_CLEARPENDINGIRQ() NVIC_ClearPendingIRQ( RTCC_IRQn )
00090 #define NVIC_DISABLEIRQ() NVIC_DisableIRQ( RTCC_IRQn )
00091 #define NVIC_ENABLEIRQ() NVIC_EnableIRQ( RTCC_IRQn )
00092 #endif
00093
00094
00095 #define MAX_RTC_TICK_CNT (RTC_MAX_VALUE+1UL)
00096 #define RTC_CLOSE_TO_MAX_VALUE (RTC_MAX_VALUE-100UL)
00097
00098 #if defined(_EFM32_GECKO_FAMILY)
00099
00100 #define RTC_DIVIDER ( cmuClkDiv_2 )
00101 #else
00102
00103 #define RTC_DIVIDER ( cmuClkDiv_8 )
00104 #endif
00105 #define RTC_CLOCK ( 32768U )
00106 #define MSEC_TO_TICKS_DIVIDER ( 1000U * RTC_DIVIDER )
00107 #define MSEC_TO_TICKS_ROUNDING_FACTOR ( MSEC_TO_TICKS_DIVIDER / 2 )
00108 #define MSEC_TO_TICKS( ms ) ( ( ( (uint64_t)ms * RTC_CLOCK ) \
00109 + MSEC_TO_TICKS_ROUNDING_FACTOR ) \
00110 / MSEC_TO_TICKS_DIVIDER )
00111
00112 #define TICKS_TO_MSEC_ROUNDING_FACTOR ( RTC_CLOCK / 2 )
00113 #define TICKS_TO_MSEC( ticks ) ( ( ( (uint64_t)ticks \
00114 * RTC_DIVIDER * 1000U ) \
00115 + TICKS_TO_MSEC_ROUNDING_FACTOR ) \
00116 / RTC_CLOCK )
00117
00118 #define TICKS_TO_SEC_ROUNDING_FACTOR ( RTC_CLOCK / 2 )
00119 #define TICKS_TO_SEC( ticks ) ( ( ( (uint64_t)ticks \
00120 * RTC_DIVIDER ) \
00121 + TICKS_TO_SEC_ROUNDING_FACTOR ) \
00122 / RTC_CLOCK )
00123 #define TICK_TIME_USEC ( 1000000 * RTC_DIVIDER / RTC_CLOCK )
00124
00125 typedef struct Timer
00126 {
00127 uint64_t remaining;
00128 uint64_t ticks;
00129 int periodicCompensationUsec;
00130 unsigned int periodicDriftUsec;
00131 RTCDRV_Callback_t callback;
00132 bool running;
00133 bool doCallback;
00134 bool allocated;
00135 RTCDRV_TimerType_t timerType;
00136 void *user;
00137 } Timer_t;
00138
00139 static Timer_t timer[ EMDRV_RTCDRV_NUM_TIMERS ];
00140 static uint32_t lastStart;
00141 static volatile uint32_t startTimerNestingLevel;
00142 static bool inTimerIRQ;
00143 static bool rtcRunning;
00144 static bool rtcdrvIsInitialized = false;
00145 #if defined( EMODE_DYNAMIC )
00146 static bool sleepBlocked;
00147 #endif
00148
00149 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00150 static uint32_t wallClockTime;
00151 static uint32_t wallClockInitTime;
00152 #endif
00153
00154 #if defined( _EFM_DEVICE )
00155 static const RTC_Init_TypeDef initRTC =
00156 {
00157 true,
00158 false,
00159 false
00160 };
00161
00162 #elif defined( _EFR_DEVICE )
00163 static RTCC_Init_TypeDef initRTCC =
00164 {
00165 true,
00166 rtccCntModeNormal,
00167 false,
00168 false,
00169 rtccCntPresc_8,
00170 rtccCntTickPresc,
00171 false,
00172 false,
00173 false
00174 };
00175
00176 static RTC_CCChConf_TypeDef initRTCCCompareChannel =
00177 {
00178 rtccCapComChModeCompare,
00179 rtccCompMatchOutActionNone,
00180 rtccPRSCh0,
00181 rtccInEdgeNone,
00182 rtccCompBaseCnt,
00183 0
00184 };
00185 #endif
00186
00187 static void checkAllTimers( uint32_t timeElapsed );
00188 static void delayTicks( uint32_t ticks );
00189 static void executeTimerCallbacks( void );
00190 static void rescheduleRtc( uint32_t rtcCnt );
00191
00193
00194
00208 Ecode_t RTCDRV_AllocateTimer( RTCDRV_TimerID_t *id )
00209 {
00210 int i = 0;
00211 int retVal = 0;
00212
00213 INT_Disable();
00214
00215 while ( ( timer[ i ].allocated ) && ( i < EMDRV_RTCDRV_NUM_TIMERS ) ) {
00216 i++;
00217 }
00218
00219
00220 if ( i == EMDRV_RTCDRV_NUM_TIMERS ) {
00221 retVal = ECODE_EMDRV_RTCDRV_ALL_TIMERS_USED;
00222 } else {
00223
00224 if ( id != NULL ) {
00225 timer[ i ].allocated = true;
00226 *id = i;
00227 retVal = ECODE_EMDRV_RTCDRV_OK;
00228 } else {
00229 retVal = ECODE_EMDRV_RTCDRV_PARAM_ERROR;
00230 }
00231 }
00232 INT_Enable();
00233
00234 return retVal;
00235 }
00236
00237
00246 Ecode_t RTCDRV_Delay( uint32_t ms )
00247 {
00248 uint64_t totalTicks;
00249
00250 totalTicks = MSEC_TO_TICKS( ms );
00251
00252 while ( totalTicks > RTC_CLOSE_TO_MAX_VALUE ) {
00253 delayTicks( RTC_CLOSE_TO_MAX_VALUE );
00254 totalTicks -= RTC_CLOSE_TO_MAX_VALUE;
00255 }
00256 delayTicks( totalTicks );
00257
00258 return ECODE_EMDRV_RTCDRV_OK;
00259 }
00260
00261
00274 Ecode_t RTCDRV_FreeTimer( RTCDRV_TimerID_t id )
00275 {
00276
00277 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00278 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00279 }
00280
00281 INT_Disable();
00282
00283 timer[ id ].running = false;
00284 timer[ id ].allocated = false;
00285
00286 INT_Enable();
00287
00288 return ECODE_EMDRV_RTCDRV_OK;
00289 }
00290
00291
00302 Ecode_t RTCDRV_Init( void )
00303 {
00304 if ( rtcdrvIsInitialized == true ) {
00305 return ECODE_EMDRV_RTCDRV_OK;
00306 }
00307 rtcdrvIsInitialized = true;
00308
00309
00310 CMU_ClockEnable( cmuClock_CORELE, true );
00311
00312
00313 CMU_ClockSelectSet( cmuClock_LFA, cmuSelect_LFXO );
00314
00315 #if defined( _EFM_DEVICE )
00316
00317 CMU_ClockDivSet( cmuClock_RTC, RTC_DIVIDER );
00318
00319
00320 CMU_ClockEnable( cmuClock_RTC, true );
00321
00322
00323 RTC_Init( &initRTC );
00324
00325 #elif defined( _EFR_DEVICE )
00326
00327 initRTCC.cntPresc = (RTCC_CntPresc_TypeDef)CMU_DivToLog2( RTC_DIVIDER );
00328
00329
00330 CMU_ClockEnable( cmuClock_RTCC, true );
00331
00332
00333 RTCC_Init( &initRTCC );
00334
00335
00336 RTCC_CapComChannelConfig( 1, &initRTCCCompareChannel );
00337 #endif
00338
00339
00340 RTC_INTDISABLE( RTC_ALL_INTS );
00341 RTC_INTCLEAR( RTC_ALL_INTS );
00342
00343 RTC_COUNTERRESET();
00344
00345
00346 NVIC_CLEARPENDINGIRQ();
00347 NVIC_ENABLEIRQ();
00348
00349 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00350
00351 RTC_INTENABLE( RTC_OF_INT );
00352 #endif
00353
00354
00355 memset( timer, 0, sizeof( timer ) );
00356 inTimerIRQ = false;
00357 rtcRunning = false;
00358 startTimerNestingLevel = 0;
00359 #if defined( EMODE_DYNAMIC )
00360 sleepBlocked = false;
00361 #endif
00362
00363 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00364 wallClockTime = 0;
00365 wallClockInitTime = 0;
00366
00367 #if defined( EMODE_NEVER_ALLOW_EM3EM4 )
00368
00369 SLEEP_SleepBlockBegin( sleepEM3 );
00370 #endif
00371
00372 #endif
00373
00374 return ECODE_EMDRV_RTCDRV_OK;
00375 }
00376
00377
00390 Ecode_t RTCDRV_DeInit( void )
00391 {
00392
00393 NVIC_DISABLEIRQ();
00394 RTC_INTDISABLE( RTC_ALL_INTS );
00395 RTC_INTCLEAR( RTC_ALL_INTS );
00396 NVIC_CLEARPENDINGIRQ();
00397
00398
00399 #if defined( _EFM_DEVICE )
00400 RTC_Enable( false );
00401 CMU_ClockEnable( cmuClock_RTC, false );
00402 #elif defined( _EFR_DEVICE )
00403 RTCC_Enable( false );
00404 CMU_ClockEnable( cmuClock_RTCC, false );
00405 #endif
00406
00407 #if defined( EMODE_NEVER_ALLOW_EM3EM4 )
00408
00409 SLEEP_SleepBlockEnd( sleepEM3 );
00410 #endif
00411
00412 #if defined( EMODE_DYNAMIC )
00413
00414 if ( sleepBlocked ) {
00415 SLEEP_SleepBlockEnd( sleepEM3 );
00416 }
00417 #endif
00418
00419
00420 rtcdrvIsInitialized = false;
00421
00422 return ECODE_EMDRV_RTCDRV_OK;
00423 }
00424
00425
00441 Ecode_t RTCDRV_IsRunning( RTCDRV_TimerID_t id, bool *isRunning )
00442 {
00443
00444 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00445 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00446 }
00447
00448
00449 if ( isRunning == NULL ) {
00450 return ECODE_EMDRV_RTCDRV_PARAM_ERROR;
00451 }
00452
00453 INT_Disable();
00454
00455 if ( ! timer[ id ].allocated ) {
00456 INT_Enable();
00457 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00458 }
00459 *isRunning = timer[ id ].running;
00460 INT_Enable();
00461
00462 return ECODE_EMDRV_RTCDRV_OK;
00463 }
00464
00465
00486 Ecode_t RTCDRV_StartTimer( RTCDRV_TimerID_t id,
00487 RTCDRV_TimerType_t type,
00488 uint32_t timeout,
00489 RTCDRV_Callback_t callback,
00490 void *user )
00491 {
00492 uint32_t timeElapsed, cnt, compVal, loopCnt = 0;
00493 uint32_t timeToNextTimerCompletion;
00494
00495
00496 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00497 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00498 }
00499
00500 INT_Disable();
00501 if ( ! timer[ id ].allocated ) {
00502 INT_Enable();
00503 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00504 }
00505
00506 if ( timeout == 0 ) {
00507 if ( callback != NULL ) {
00508 callback( id, user );
00509 }
00510 INT_Enable();
00511 return ECODE_EMDRV_RTCDRV_OK;
00512 }
00513
00514 cnt = RTC_COUNTERGET();
00515
00516 timer[ id ].callback = callback;
00517 timer[ id ].ticks = MSEC_TO_TICKS( timeout );
00518 if (rtcdrvTimerTypePeriodic == type) {
00519
00520 timer[ id ].periodicCompensationUsec = 1000 * timeout -
00521 (timer[ id ].ticks * TICK_TIME_USEC);
00522 timer[ id ].periodicDriftUsec = TICK_TIME_USEC/2;
00523 }
00524
00525 timer[ id ].remaining = timer[ id ].ticks + 1;
00526 timer[ id ].running = true;
00527 timer[ id ].timerType = type;
00528 timer[ id ].user = user;
00529
00530 if ( inTimerIRQ == true ) {
00531
00532 INT_Enable();
00533 return ECODE_EMDRV_RTCDRV_OK;
00534 }
00535
00536
00537 if ( startTimerNestingLevel < UINT32_MAX ) {
00538 startTimerNestingLevel++;
00539 }
00540
00541 if ( rtcRunning == false ) {
00542
00543 #if defined( _EFM_DEVICE )
00544 lastStart = ( cnt ) & RTC_COUNTER_MASK;
00545 #elif defined( _EFR_DEVICE )
00546 lastStart = cnt;
00547 #endif
00548
00549 RTC_INTCLEAR( RTC_COMP_INT );
00550
00551 compVal = EFM32_MIN( timer[ id ].remaining, RTC_CLOSE_TO_MAX_VALUE );
00552 RTC_COMPARESET( cnt + compVal );
00553
00554
00555 RTC_INTENABLE( RTC_COMP_INT );
00556
00557 #if defined( EMODE_DYNAMIC )
00558
00559 if ( sleepBlocked == false ) {
00560 sleepBlocked = true;
00561 SLEEP_SleepBlockBegin( sleepEM3 );
00562 }
00563 #endif
00564
00565 rtcRunning = true;
00566
00567 } else {
00568
00569
00570
00571
00572
00573 if ( startTimerNestingLevel == 1 ) {
00574
00575 timer[ id ].running = false;
00576
00577 do {
00578
00579 RTC_INTDISABLE( RTC_COMP_INT );
00580
00581 timeElapsed = TIMEDIFF( cnt, lastStart );
00582 #if defined( _EFM_DEVICE )
00583
00584
00585 if ( timeElapsed == RTC_MAX_VALUE ) {
00586 timeElapsed = 0;
00587 }
00588 #endif
00589
00590
00591 checkAllTimers( timeElapsed );
00592
00593
00594 executeTimerCallbacks();
00595
00596
00597 if ( loopCnt == 0 ) {
00598 timer[ id ].running = true;
00599 }
00600 loopCnt++;
00601
00602
00603 rescheduleRtc( cnt );
00604
00605 cnt = RTC_COUNTERGET();
00606 timeElapsed = TIMEDIFF( cnt, lastStart );
00607 timeToNextTimerCompletion = TIMEDIFF( RTC_COMPAREGET(), lastStart );
00608
00609
00610
00611
00612 }
00613 while ( rtcRunning && (timeElapsed > timeToNextTimerCompletion));
00614 }
00615 }
00616
00617 if ( startTimerNestingLevel > 0 ) {
00618 startTimerNestingLevel--;
00619 }
00620
00621 INT_Enable();
00622 return ECODE_EMDRV_RTCDRV_OK;
00623 }
00624
00625
00636 Ecode_t RTCDRV_StopTimer( RTCDRV_TimerID_t id )
00637 {
00638
00639 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00640 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00641 }
00642
00643 INT_Disable();
00644 if ( ! timer[ id ].allocated ) {
00645 INT_Enable();
00646 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00647 }
00648
00649 timer[ id ].running = false;
00650 INT_Enable();
00651
00652 return ECODE_EMDRV_RTCDRV_OK;
00653 }
00654
00655
00671 Ecode_t RTCDRV_TimeRemaining( RTCDRV_TimerID_t id, uint32_t *timeRemaining )
00672 {
00673 uint64_t tmp;
00674 uint32_t timeLeft, currentCnt, lastRtcStart;
00675
00676
00677 if ( id >= EMDRV_RTCDRV_NUM_TIMERS ) {
00678 return ECODE_EMDRV_RTCDRV_ILLEGAL_TIMER_ID;
00679 }
00680
00681
00682 if ( timeRemaining == NULL ) {
00683 return ECODE_EMDRV_RTCDRV_PARAM_ERROR;
00684 }
00685
00686 INT_Disable();
00687
00688 if ( ! timer[ id ].allocated ) {
00689 INT_Enable();
00690 return ECODE_EMDRV_RTCDRV_TIMER_NOT_ALLOCATED;
00691 }
00692
00693
00694 if ( ! timer[ id ].running ) {
00695 INT_Enable();
00696 return ECODE_EMDRV_RTCDRV_TIMER_NOT_RUNNING;
00697 }
00698
00699 timeLeft = timer[ id ].remaining;
00700 currentCnt = RTC_COUNTERGET();
00701 lastRtcStart = lastStart;
00702 INT_Enable();
00703
00704
00705 currentCnt = TIMEDIFF( currentCnt, lastRtcStart );
00706
00707 if ( currentCnt > timeLeft ) {
00708 timeLeft = 0;
00709 } else {
00710 timeLeft -= currentCnt;
00711 }
00712
00713 tmp = TICKS_TO_MSEC( timeLeft );
00714 *timeRemaining = tmp;
00715
00716 return ECODE_EMDRV_RTCDRV_OK;
00717 }
00718
00719 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00720
00727 uint32_t RTCDRV_GetWallClock( void )
00728 {
00729 uint64_t tmp;
00730 uint32_t ticks, wallClock, wallClockStartPoint;
00731
00732 INT_Disable();
00733 ticks = RTC_COUNTERGET();
00734 wallClock = wallClockTime;
00735 wallClockStartPoint = wallClockInitTime;
00736 INT_Enable();
00737
00738 tmp = ticks - wallClockStartPoint;
00739 return wallClock + (uint32_t)TICKS_TO_SEC( tmp );
00740 }
00741 #endif
00742
00743 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00744
00753 Ecode_t RTCDRV_SetWallClock( uint32_t secs )
00754 {
00755 INT_Disable();
00756 wallClockTime = secs;
00757 wallClockInitTime = RTC_COUNTERGET();
00758 INT_Enable();
00759
00760 return ECODE_EMDRV_RTCDRV_OK;
00761 }
00762 #endif
00763
00765
00766 #if defined( _EFM_DEVICE )
00767 void RTC_IRQHandler(void)
00768 #elif defined( _EFR_DEVICE )
00769 void RTCC_IRQHandler(void)
00770 #endif
00771 {
00772 uint32_t flags, timeElapsed, cnt, timeToNextTimerCompletion;
00773
00774 INT_Disable();
00775
00776
00777
00778
00779 flags = RTC_INTGET();
00780
00781 if ( flags & RTC_COMP_INT ) {
00782
00783
00784
00785
00786
00787
00788 inTimerIRQ = true;
00789
00790 cnt = RTC_COUNTERGET();
00791
00792
00793 do {
00794
00795 RTC_INTDISABLE( RTC_COMP_INT );
00796
00797 timeElapsed = TIMEDIFF( cnt, lastStart );
00798
00799
00800 checkAllTimers( timeElapsed );
00801
00802
00803 executeTimerCallbacks();
00804
00805
00806 rescheduleRtc( cnt );
00807
00808 cnt = RTC_COUNTERGET();
00809 timeElapsed = TIMEDIFF( cnt, lastStart );
00810 timeToNextTimerCompletion = TIMEDIFF( RTC_COMPAREGET(), lastStart );
00811
00812
00813
00814 }
00815 while ( rtcRunning && (timeElapsed > timeToNextTimerCompletion));
00816 inTimerIRQ = false;
00817 }
00818
00819 #if defined( EMDRV_RTCDRV_WALLCLOCK_CONFIG )
00820 if ( flags & RTC_OF_INT ) {
00821 uint64_t ticks;
00822
00823 RTC_INTCLEAR( RTC_OF_INT );
00824
00825 ticks = MAX_RTC_TICK_CNT - wallClockInitTime;
00826 wallClockInitTime = 0;
00827 wallClockTime += TICKS_TO_SEC( ticks );
00828 }
00829 #endif
00830
00831 INT_Enable();
00832 }
00833
00834 static void checkAllTimers( uint32_t timeElapsed )
00835 {
00836 int i;
00837 #if defined( EMODE_DYNAMIC )
00838 int numOfTimersRunning = 0;
00839 #endif
00840
00841
00842
00843
00844
00845 for ( i = 0; i < EMDRV_RTCDRV_NUM_TIMERS; i++ ) {
00846 timer[ i ].doCallback = false;
00847 if ( timer[ i ].running == true ) {
00848 #if defined( EMODE_DYNAMIC )
00849 numOfTimersRunning++;
00850 #endif
00851 if ( timer[ i ].remaining > timeElapsed ) {
00852 timer[ i ].remaining -= timeElapsed;
00853 } else {
00854 if ( timer[ i ].timerType == rtcdrvTimerTypeOneshot ) {
00855 timer[ i ].running = false;
00856 #if defined( EMODE_DYNAMIC )
00857 numOfTimersRunning--;
00858 #endif
00859 } else {
00860
00861 timer[ i ].remaining = timer[ i ].ticks - timeElapsed +
00862 timer[ i ].remaining;
00863 if ( timer[ i ].periodicCompensationUsec > 0 ) {
00864 timer[ i ].periodicDriftUsec += timer[i].periodicCompensationUsec;
00865 if (timer[ i ].periodicDriftUsec >= TICK_TIME_USEC) {
00866
00867
00868 timer[ i ].remaining += 1;
00869 timer[ i ].periodicDriftUsec -= TICK_TIME_USEC;
00870 }
00871 }
00872 else {
00873 timer[ i ].periodicDriftUsec -= timer[i].periodicCompensationUsec;
00874 if (timer[ i ].periodicDriftUsec >= TICK_TIME_USEC) {
00875
00876
00877 timer[ i ].remaining -= 1;
00878 timer[ i ].periodicDriftUsec -= TICK_TIME_USEC;
00879 }
00880 }
00881 }
00882 if ( timer[ i ].callback != NULL ) {
00883 timer[ i ].doCallback = true;
00884 }
00885 }
00886 }
00887 }
00888
00889 #if defined( EMODE_DYNAMIC )
00890
00891 if ( ( numOfTimersRunning == 0 ) && ( sleepBlocked == true ) ) {
00892 sleepBlocked = false;
00893 SLEEP_SleepBlockEnd( sleepEM3 );
00894 }
00895 #endif
00896 }
00897
00898 static void delayTicks( uint32_t ticks )
00899 {
00900 uint32_t startTime;
00901 volatile uint32_t now;
00902
00903 if ( ticks ) {
00904 startTime = RTC_COUNTERGET();
00905 do {
00906 now = RTC_COUNTERGET();
00907 } while ( TIMEDIFF( now, startTime ) < ticks );
00908 }
00909 }
00910
00911 static void executeTimerCallbacks( void )
00912 {
00913 int i;
00914
00915 for ( i = 0; i < EMDRV_RTCDRV_NUM_TIMERS; i++ ) {
00916 if ( timer[ i ].doCallback ) {
00917 timer[ i ].callback( i, timer[ i ].user );
00918 }
00919 }
00920 }
00921
00922 static void rescheduleRtc( uint32_t rtcCnt )
00923 {
00924 int i;
00925 uint64_t min = UINT64_MAX;
00926
00927
00928 for ( i = 0; i < EMDRV_RTCDRV_NUM_TIMERS; i++ ) {
00929 if ( ( timer[ i ].running == true )
00930 && ( timer[ i ].remaining < min ) ) {
00931 min = timer[ i ].remaining;
00932 }
00933 }
00934
00935 rtcRunning = false;
00936 if ( min != UINT64_MAX ) {
00937 min = EFM32_MIN( min, RTC_CLOSE_TO_MAX_VALUE );
00938 #if defined( _EFM_DEVICE )
00939 if ( inTimerIRQ == false ) {
00940 lastStart = ( rtcCnt ) & RTC_COUNTER_MASK;
00941 } else
00942 #endif
00943 {
00944 lastStart = rtcCnt;
00945 }
00946 RTC_INTCLEAR( RTC_COMP_INT );
00947
00948 RTC_COMPARESET( rtcCnt + min );
00949
00950 #if defined( EMODE_DYNAMIC )
00951
00952 if ( sleepBlocked == false ) {
00953 sleepBlocked = true;
00954 SLEEP_SleepBlockBegin( sleepEM3 );
00955 }
00956 #endif
00957
00958 rtcRunning = true;
00959
00960
00961 RTC_INTENABLE( RTC_COMP_INT );
00962 }
00963 }
00965
00966