ustimer.c
Go to the documentation of this file.00001
00016 #include <stdbool.h>
00017 #include "em_device.h"
00018 #include "em_common.h"
00019 #include "em_cmu.h"
00020 #include "em_emu.h"
00021 #include "em_int.h"
00022 #include "em_timer.h"
00023
00024 #include "ustimer.h"
00025
00028 #ifndef USTIMER_TIMER
00029 #define USTIMER_TIMER USTIMER_TIMER0
00030 #endif
00031
00032 #if ( USTIMER_TIMER == USTIMER_TIMER0 ) && ( TIMER_COUNT >= 1 )
00033 #define TIMER TIMER0
00034 #define TIMER_CLK cmuClock_TIMER0
00035 #define TIMER_IRQ TIMER0_IRQn
00036 #define TIMER_IRQHandler TIMER0_IRQHandler
00037
00038 #elif ( USTIMER_TIMER == USTIMER_TIMER1 ) && ( TIMER_COUNT >= 2 )
00039 #define TIMER TIMER1
00040 #define TIMER_CLK cmuClock_TIMER1
00041 #define TIMER_IRQ TIMER1_IRQn
00042 #define TIMER_IRQHandler TIMER1_IRQHandler
00043
00044 #elif ( USTIMER_TIMER == USTIMER_TIMER2 ) && ( TIMER_COUNT >= 3 )
00045 #define TIMER TIMER2
00046 #define TIMER_CLK cmuClock_TIMER2
00047 #define TIMER_IRQ TIMER2_IRQn
00048 #define TIMER_IRQHandler TIMER2_IRQHandler
00049
00050 #elif ( USTIMER_TIMER == USTIMER_TIMER3 ) && ( TIMER_COUNT == 4 )
00051 #define TIMER TIMER3
00052 #define TIMER_CLK cmuClock_TIMER3
00053 #define TIMER_IRQ TIMER3_IRQn
00054 #define TIMER_IRQHandler TIMER3_IRQHandler
00055
00056 #else
00057 #error "Illegal USTIMER TIMER selection"
00058 #endif
00059
00060 static uint32_t freq;
00061 static uint32_t minTicks;
00062 static volatile bool timeElapsed = false;
00063
00064 static void DelayTicksEM1( uint16_t ticks );
00065 static void DelayTicksPolled( uint16_t ticks );
00066
00069
00081 Ecode_t USTIMER_Init( void )
00082 {
00083 TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
00084 TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
00085 uint32_t coreClockScale;
00086
00087 timerCCInit.mode = timerCCModeCompare;
00088 CMU_ClockEnable( TIMER_CLK, true );
00089 TIMER_TopSet( TIMER, 0xFFFF );
00090 TIMER_InitCC( TIMER, 0, &timerCCInit );
00091
00092
00093 timerInit.prescale = (TIMER_Prescale_TypeDef)_TIMER_CTRL_PRESC_DIV1;
00094 do
00095 {
00096 TIMER_Init( TIMER, &timerInit );
00097
00098 freq = CMU_ClockFreqGet( cmuClock_HFPER );
00099 freq /= 1 << timerInit.prescale;
00100 timerInit.prescale++;
00101 }
00102 while ( ( timerInit.prescale <= _TIMER_CTRL_PRESC_DIV1024 )
00103 && ( freq > 2000000 ) );
00104
00105
00106
00107
00108
00109
00110 coreClockScale = ( 4 * 48000000 ) / CMU_ClockFreqGet( cmuClock_CORE );
00111 minTicks = ( ( (uint64_t)freq * coreClockScale ) + 500000 ) / 1000000;
00112 timeElapsed = false;
00113
00114 TIMER_IntDisable( TIMER, TIMER_IEN_CC0 );
00115 NVIC_ClearPendingIRQ( TIMER_IRQ );
00116 NVIC_EnableIRQ( TIMER_IRQ );
00117
00118 return ECODE_EMDRV_USTIMER_OK;
00119 }
00120
00121
00132 Ecode_t USTIMER_DeInit( void )
00133 {
00134 NVIC_DisableIRQ( TIMER_IRQ );
00135 TIMER_IntDisable( TIMER, TIMER_IEN_CC0 );
00136
00137 TIMER_IntClear( TIMER, TIMER_IFC_CC0 );
00138 NVIC_ClearPendingIRQ( TIMER_IRQ );
00139
00140 TIMER_Enable( TIMER, false );
00141 CMU_ClockEnable( TIMER_CLK, false );
00142
00143 return ECODE_EMDRV_USTIMER_OK;
00144 }
00145
00146
00163 Ecode_t USTIMER_Delay( uint32_t usec )
00164 {
00165 uint64_t totalTicks;
00166
00167 totalTicks = ( ( (uint64_t)freq * usec ) + 500000 ) / 1000000;
00168
00169
00170
00171 while ( totalTicks > 65000 )
00172 {
00173 DelayTicksEM1( 65000 );
00174 totalTicks -= 65000;
00175 }
00176 DelayTicksEM1( (uint16_t)totalTicks );
00177
00178 return ECODE_EMDRV_USTIMER_OK;
00179 }
00180
00181
00198 Ecode_t USTIMER_DelayIntSafe( uint32_t usec )
00199 {
00200 uint64_t totalTicks;
00201
00202 totalTicks = ( ( (uint64_t)freq * usec ) + 500000 ) / 1000000;
00203
00204
00205
00206 while ( totalTicks > 65000 )
00207 {
00208 DelayTicksPolled( 65000 );
00209 totalTicks -= 65000;
00210 }
00211 DelayTicksPolled( (uint16_t)totalTicks );
00212
00213 return ECODE_EMDRV_USTIMER_OK;
00214 }
00215
00216
00219 void TIMER_IRQHandler( void )
00220 {
00221 uint32_t flags;
00222
00223 flags = TIMER_IntGet( TIMER );
00224
00225 if ( flags & TIMER_IF_CC0 )
00226 {
00227 TIMER_IntClear( TIMER, TIMER_IFC_CC0 );
00228 timeElapsed = true;
00229 }
00230 }
00231
00232 static void DelayTicksPolled( uint16_t ticks )
00233 {
00234 uint16_t startTime;
00235 volatile uint16_t now;
00236
00237 if ( ticks )
00238 {
00239 startTime = TIMER_CounterGet( TIMER );
00240 do
00241 {
00242 now = TIMER_CounterGet( TIMER );
00243 } while ( (uint16_t)( now - startTime ) < ticks );
00244 }
00245 }
00246
00247 static void DelayTicksEM1( uint16_t ticks )
00248 {
00249 if ( ticks )
00250 {
00251
00252
00253 INT_Disable();
00254
00255
00256 TIMER_CompareSet( TIMER, 0,
00257 TIMER_CounterGet( TIMER ) + EFM32_MAX( minTicks, ticks ) );
00258 TIMER_IntClear( TIMER, TIMER_IFC_CC0 );
00259 TIMER_IntEnable( TIMER, TIMER_IEN_CC0 );
00260
00261 INT_Enable();
00262
00263 while ( ! timeElapsed )
00264 {
00265 EMU_EnterEM1();
00266 }
00267 timeElapsed = false;
00268
00269 TIMER_IntDisable( TIMER, TIMER_IEN_CC0 );
00270 }
00271 }
00272
00275
00315