1.1 diff -r 000000000000 -r 396b0bd970d3 drivers/service/MicoTimerService.c 1.2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 +++ b/drivers/service/MicoTimerService.c Fri Aug 13 10:49:23 2010 +0100 1.4 @@ -0,0 +1,248 @@ 1.5 +/**************************************************************************** 1.6 +** 1.7 +** Name: MicoTimerService.c 1.8 +** 1.9 +** Description: 1.10 +** Implements timer service functionality: 1.11 +** -- registering a timer as a system timer (64-bit) 1.12 +** and retrieving the system tick 1.13 +** 1.14 +** -- registering a timer as a "lookup-able" device 1.15 +** (user does not have to work with these functions) 1.16 +** 1.17 +** $Revision: $ 1.18 +** 1.19 +** Disclaimer: 1.20 +** 1.21 +** This source code is intended as a design reference which 1.22 +** illustrates how these types of functions can be implemented. It 1.23 +** is the user's responsibility to verify their design for 1.24 +** consistency and functionality through the use of formal 1.25 +** verification methods. Lattice Semiconductor provides no warranty 1.26 +** regarding the use or functionality of this code. 1.27 +** 1.28 +** -------------------------------------------------------------------- 1.29 +** 1.30 +** Lattice Semiconductor Corporation 1.31 +** 5555 NE Moore Court 1.32 +** Hillsboro, OR 97214 1.33 +** U.S.A 1.34 +** 1.35 +** TEL: 1-800-Lattice (USA and Canada) 1.36 +** (503)268-8001 (other locations) 1.37 +** 1.38 +** web: http://www.latticesemi.com 1.39 +** email: techsupport@latticesemi.com 1.40 +** 1.41 +** -------------------------------------------------------------------------- 1.42 +** 1.43 +** Change History (Latest changes on top) 1.44 +** 1.45 +** Ver Date Description 1.46 +** -------------------------------------------------------------------------- 1.47 +** 1.48 +** 3.0 Mar-25-2008 Added Header 1.49 +** 1.50 +**--------------------------------------------------------------------------- 1.51 +*****************************************************************************/ 1.52 + 1.53 +#include "MicoTimerService.h" 1.54 +#include "MicoUtils.h" 1.55 +#include "MicoMacros.h" 1.56 +#include "MicoInterrupts.h" 1.57 +#include "LookupServices.h" 1.58 + 1.59 + 1.60 +#ifdef __cplusplus 1.61 +extern "C" 1.62 +{ 1.63 +#endif /* __cplusplus */ 1.64 + 1.65 + 1.66 +/****************************************************************************** 1.67 + * Type-definitions and manifest constants and structures * 1.68 + ******************************************************************************/ 1.69 +typedef struct st_ActivityListEntry{ 1.70 + void *ctx; 1.71 + MicoSysTimerActivity_t activity; 1.72 +}ActivityListEntry_t; 1.73 + 1.74 + 1.75 +/****************************************************************************** 1.76 + * data memebers * 1.77 + ******************************************************************************/ 1.78 +static ActivityListEntry_t s_SysTimerActivity = {0,0}; 1.79 +static MicoTimerCtx_t *s_MicoSystemTimer = 0; 1.80 +static unsigned long long int s_MicoCPUTicks; 1.81 +static unsigned int s_MicoSysTicks; 1.82 + 1.83 +#ifdef __cplusplus 1.84 +} 1.85 +#endif /* __cplusplus */ 1.86 + 1.87 +/****************************************************************************** 1.88 + * debug routines * 1.89 + ******************************************************************************/ 1.90 +#ifdef _MICO_TIMER_SERVICES_DEBUG_ENABLED_ 1.91 + 1.92 +void DumpMicoTimerServicesActivityList() 1.93 +{ 1.94 + /* ToDo */ 1.95 +} 1.96 + 1.97 + 1.98 +void DumpMicoTimerServicesRegisteredTimers() 1.99 +{ 1.100 + /* ToDo */ 1.101 +} 1.102 + 1.103 +#endif 1.104 + 1.105 + 1.106 +/****************************************************************************** 1.107 + * system-timer ISR * 1.108 + ******************************************************************************/ 1.109 +static void MicoTimerServicesSysTimerISR(void *pContext) 1.110 +{ 1.111 + MicoSysTimerActivity_t activity; 1.112 + 1.113 + /* increment CPU ticks */ 1.114 + s_MicoCPUTicks += s_MicoSysTicks; 1.115 + 1.116 + /* if there's an activity registered for system-tick, invoke it */ 1.117 + if(s_SysTimerActivity.activity != 0){ 1.118 + activity = s_SysTimerActivity.activity; 1.119 + activity(s_SysTimerActivity.ctx); 1.120 + }; 1.121 + 1.122 + return; 1.123 +} 1.124 + 1.125 + 1.126 + 1.127 +/****************************************************************************** 1.128 + * Initializes TimerServices * 1.129 + ******************************************************************************/ 1.130 +static void MicoTimerServicesInit() 1.131 +{ 1.132 + static int s_Initialized = 0; 1.133 + if(s_Initialized == 0) { 1.134 + s_Initialized = 1; 1.135 + s_SysTimerActivity.activity = 0; 1.136 + s_MicoSystemTimer = 0; 1.137 + s_MicoCPUTicks = 0; 1.138 + } 1.139 +} 1.140 + 1.141 + 1.142 +/****************************************************************************** 1.143 + * registers a system-timer if one isn't already registered.. * 1.144 + ******************************************************************************/ 1.145 +MicoTimerCtx_t* RegisterSystemTimer(MicoTimerCtx_t *pTimer, unsigned int TicksInMS) 1.146 +{ 1.147 + MicoTimerServicesInit(); 1.148 + 1.149 + /* 1.150 + * If there's a system-timer registered, don't modify it but simply 1.151 + * return its context information 1.152 + */ 1.153 + if(s_MicoSystemTimer != 0) 1.154 + return(s_MicoSystemTimer); 1.155 + 1.156 + /* 1.157 + * there's none, so register this one as the system-timer 1.158 + */ 1.159 + if(pTimer != 0){ 1.160 + s_MicoSystemTimer = pTimer; 1.161 + if(TicksInMS == 0) 1.162 + TicksInMS = 1; 1.163 + s_MicoSysTicks = (TicksInMS * (MICO32_CPU_CLOCK_MHZ/1000)); 1.164 + MicoTimerStart( s_MicoSystemTimer, 1.165 + MicoTimerServicesSysTimerISR, 1.166 + 0, 1.167 + s_MicoSysTicks-1, 1.168 + 1); 1.169 + } 1.170 + 1.171 + return(s_MicoSystemTimer); 1.172 +} 1.173 + 1.174 + 1.175 + 1.176 +/****************************************************************************** 1.177 + * get cpu-ticks * 1.178 + ******************************************************************************/ 1.179 +void MicoGetCPUTicks(unsigned long long int *ticks) 1.180 +{ 1.181 + /* 1.182 + * We need to get a finer resolution than the system-tick and also 1.183 + * account for a possible roll-over just after we read the snaphot. 1.184 + * We're definitely not going to be exact on the dot but we'll be 1.185 + * pretty darn close; higher the clock-speed, less the error (in 1.186 + * seconds). 1.187 + */ 1.188 + unsigned long long int cpuTicks = 0; 1.189 + unsigned int intrMask; 1.190 + unsigned int snapshot; 1.191 + 1.192 + if(s_MicoSystemTimer != 0) { 1.193 + 1.194 + /* disable interrupts and read the gross resolution tick-count */ 1.195 + intrMask = MicoDisableInterrupts(); 1.196 + cpuTicks = s_MicoCPUTicks; 1.197 + 1.198 + 1.199 + /* read the snapshot to get a finer tuning */ 1.200 + snapshot = MicoTimerSnapshot(s_MicoSystemTimer); 1.201 + 1.202 + 1.203 + /* 1.204 + * Since the timer is an external peripheral over a bus, there may be 1.205 + * contention and we may not get the right reading. So allow another 1.206 + * interrupt if it happened, to make our tick-reading as accurate 1.207 + * as possible. 1.208 + */ 1.209 + MicoEnableInterrupt(s_MicoSystemTimer->intrLevel); 1.210 + 1.211 + 1.212 + /* we're done; decide what our reading should be */ 1.213 + MicoDisableInterrupts(); 1.214 + if(cpuTicks == s_MicoCPUTicks) 1.215 + cpuTicks += (s_MicoSysTicks - snapshot -1); 1.216 + else 1.217 + cpuTicks = s_MicoCPUTicks; 1.218 + 1.219 + 1.220 + /* restore interrupts */ 1.221 + MicoEnableInterrupts(intrMask); 1.222 + } 1.223 + 1.224 + if(ticks != 0) 1.225 + *ticks = cpuTicks; 1.226 + 1.227 + return; 1.228 +} 1.229 + 1.230 + 1.231 +/****************************************************************************** 1.232 + * Registers a periodic-activity (system-timer ticks) * 1.233 + *----------------------------------------------------------------------------* 1.234 + * System-timer must exist for this to function correctly. * 1.235 + ******************************************************************************/ 1.236 +void MicoRegisterActivity(MicoSysTimerActivity_t activity, void *ctx) 1.237 +{ 1.238 + MicoTimerServicesInit(); 1.239 + 1.240 + if(s_MicoSystemTimer == 0) 1.241 + return; 1.242 + 1.243 + MicoDisableInterrupt(s_MicoSystemTimer->intrLevel); 1.244 + 1.245 + s_SysTimerActivity.ctx = ctx; 1.246 + s_SysTimerActivity.activity = activity; 1.247 + 1.248 + MicoEnableInterrupt(s_MicoSystemTimer->intrLevel); 1.249 + 1.250 + return; 1.251 +} 1.252 +