Fri, 13 Aug 2010 10:49:23 +0100
Initial import, Timer v3.0
1 /****************************************************************************
2 **
3 ** Name: MicoTimerService.c
4 **
5 ** Description:
6 ** Implements timer service functionality:
7 ** -- registering a timer as a system timer (64-bit)
8 ** and retrieving the system tick
9 **
10 ** -- registering a timer as a "lookup-able" device
11 ** (user does not have to work with these functions)
12 **
13 ** $Revision: $
14 **
15 ** Disclaimer:
16 **
17 ** This source code is intended as a design reference which
18 ** illustrates how these types of functions can be implemented. It
19 ** is the user's responsibility to verify their design for
20 ** consistency and functionality through the use of formal
21 ** verification methods. Lattice Semiconductor provides no warranty
22 ** regarding the use or functionality of this code.
23 **
24 ** --------------------------------------------------------------------
25 **
26 ** Lattice Semiconductor Corporation
27 ** 5555 NE Moore Court
28 ** Hillsboro, OR 97214
29 ** U.S.A
30 **
31 ** TEL: 1-800-Lattice (USA and Canada)
32 ** (503)268-8001 (other locations)
33 **
34 ** web: http://www.latticesemi.com
35 ** email: techsupport@latticesemi.com
36 **
37 ** --------------------------------------------------------------------------
38 **
39 ** Change History (Latest changes on top)
40 **
41 ** Ver Date Description
42 ** --------------------------------------------------------------------------
43 **
44 ** 3.0 Mar-25-2008 Added Header
45 **
46 **---------------------------------------------------------------------------
47 *****************************************************************************/
49 #include "MicoTimerService.h"
50 #include "MicoUtils.h"
51 #include "MicoMacros.h"
52 #include "MicoInterrupts.h"
53 #include "LookupServices.h"
56 #ifdef __cplusplus
57 extern "C"
58 {
59 #endif /* __cplusplus */
62 /******************************************************************************
63 * Type-definitions and manifest constants and structures *
64 ******************************************************************************/
65 typedef struct st_ActivityListEntry{
66 void *ctx;
67 MicoSysTimerActivity_t activity;
68 }ActivityListEntry_t;
71 /******************************************************************************
72 * data memebers *
73 ******************************************************************************/
74 static ActivityListEntry_t s_SysTimerActivity = {0,0};
75 static MicoTimerCtx_t *s_MicoSystemTimer = 0;
76 static unsigned long long int s_MicoCPUTicks;
77 static unsigned int s_MicoSysTicks;
79 #ifdef __cplusplus
80 }
81 #endif /* __cplusplus */
83 /******************************************************************************
84 * debug routines *
85 ******************************************************************************/
86 #ifdef _MICO_TIMER_SERVICES_DEBUG_ENABLED_
88 void DumpMicoTimerServicesActivityList()
89 {
90 /* ToDo */
91 }
94 void DumpMicoTimerServicesRegisteredTimers()
95 {
96 /* ToDo */
97 }
99 #endif
102 /******************************************************************************
103 * system-timer ISR *
104 ******************************************************************************/
105 static void MicoTimerServicesSysTimerISR(void *pContext)
106 {
107 MicoSysTimerActivity_t activity;
109 /* increment CPU ticks */
110 s_MicoCPUTicks += s_MicoSysTicks;
112 /* if there's an activity registered for system-tick, invoke it */
113 if(s_SysTimerActivity.activity != 0){
114 activity = s_SysTimerActivity.activity;
115 activity(s_SysTimerActivity.ctx);
116 };
118 return;
119 }
123 /******************************************************************************
124 * Initializes TimerServices *
125 ******************************************************************************/
126 static void MicoTimerServicesInit()
127 {
128 static int s_Initialized = 0;
129 if(s_Initialized == 0) {
130 s_Initialized = 1;
131 s_SysTimerActivity.activity = 0;
132 s_MicoSystemTimer = 0;
133 s_MicoCPUTicks = 0;
134 }
135 }
138 /******************************************************************************
139 * registers a system-timer if one isn't already registered.. *
140 ******************************************************************************/
141 MicoTimerCtx_t* RegisterSystemTimer(MicoTimerCtx_t *pTimer, unsigned int TicksInMS)
142 {
143 MicoTimerServicesInit();
145 /*
146 * If there's a system-timer registered, don't modify it but simply
147 * return its context information
148 */
149 if(s_MicoSystemTimer != 0)
150 return(s_MicoSystemTimer);
152 /*
153 * there's none, so register this one as the system-timer
154 */
155 if(pTimer != 0){
156 s_MicoSystemTimer = pTimer;
157 if(TicksInMS == 0)
158 TicksInMS = 1;
159 s_MicoSysTicks = (TicksInMS * (MICO32_CPU_CLOCK_MHZ/1000));
160 MicoTimerStart( s_MicoSystemTimer,
161 MicoTimerServicesSysTimerISR,
162 0,
163 s_MicoSysTicks-1,
164 1);
165 }
167 return(s_MicoSystemTimer);
168 }
172 /******************************************************************************
173 * get cpu-ticks *
174 ******************************************************************************/
175 void MicoGetCPUTicks(unsigned long long int *ticks)
176 {
177 /*
178 * We need to get a finer resolution than the system-tick and also
179 * account for a possible roll-over just after we read the snaphot.
180 * We're definitely not going to be exact on the dot but we'll be
181 * pretty darn close; higher the clock-speed, less the error (in
182 * seconds).
183 */
184 unsigned long long int cpuTicks = 0;
185 unsigned int intrMask;
186 unsigned int snapshot;
188 if(s_MicoSystemTimer != 0) {
190 /* disable interrupts and read the gross resolution tick-count */
191 intrMask = MicoDisableInterrupts();
192 cpuTicks = s_MicoCPUTicks;
195 /* read the snapshot to get a finer tuning */
196 snapshot = MicoTimerSnapshot(s_MicoSystemTimer);
199 /*
200 * Since the timer is an external peripheral over a bus, there may be
201 * contention and we may not get the right reading. So allow another
202 * interrupt if it happened, to make our tick-reading as accurate
203 * as possible.
204 */
205 MicoEnableInterrupt(s_MicoSystemTimer->intrLevel);
208 /* we're done; decide what our reading should be */
209 MicoDisableInterrupts();
210 if(cpuTicks == s_MicoCPUTicks)
211 cpuTicks += (s_MicoSysTicks - snapshot -1);
212 else
213 cpuTicks = s_MicoCPUTicks;
216 /* restore interrupts */
217 MicoEnableInterrupts(intrMask);
218 }
220 if(ticks != 0)
221 *ticks = cpuTicks;
223 return;
224 }
227 /******************************************************************************
228 * Registers a periodic-activity (system-timer ticks) *
229 *----------------------------------------------------------------------------*
230 * System-timer must exist for this to function correctly. *
231 ******************************************************************************/
232 void MicoRegisterActivity(MicoSysTimerActivity_t activity, void *ctx)
233 {
234 MicoTimerServicesInit();
236 if(s_MicoSystemTimer == 0)
237 return;
239 MicoDisableInterrupt(s_MicoSystemTimer->intrLevel);
241 s_SysTimerActivity.ctx = ctx;
242 s_SysTimerActivity.activity = activity;
244 MicoEnableInterrupt(s_MicoSystemTimer->intrLevel);
246 return;
247 }