Fri, 13 Aug 2010 10:49:23 +0100
Initial import, Timer v3.0
| philpem@0 | 1 | /**************************************************************************** |
| philpem@0 | 2 | ** |
| philpem@0 | 3 | ** Name: MicoTimer.c |
| philpem@0 | 4 | ** |
| philpem@0 | 5 | ** Description: |
| philpem@0 | 6 | ** Implements functions for manipulating LatticeMico32 Timer |
| philpem@0 | 7 | ** |
| philpem@0 | 8 | ** $Revision: $ |
| philpem@0 | 9 | ** |
| philpem@0 | 10 | ** Disclaimer: |
| philpem@0 | 11 | ** |
| philpem@0 | 12 | ** This source code is intended as a design reference which |
| philpem@0 | 13 | ** illustrates how these types of functions can be implemented. It |
| philpem@0 | 14 | ** is the user's responsibility to verify their design for |
| philpem@0 | 15 | ** consistency and functionality through the use of formal |
| philpem@0 | 16 | ** verification methods. Lattice Semiconductor provides no warranty |
| philpem@0 | 17 | ** regarding the use or functionality of this code. |
| philpem@0 | 18 | ** |
| philpem@0 | 19 | ** -------------------------------------------------------------------- |
| philpem@0 | 20 | ** |
| philpem@0 | 21 | ** Lattice Semiconductor Corporation |
| philpem@0 | 22 | ** 5555 NE Moore Court |
| philpem@0 | 23 | ** Hillsboro, OR 97214 |
| philpem@0 | 24 | ** U.S.A |
| philpem@0 | 25 | ** |
| philpem@0 | 26 | ** TEL: 1-800-Lattice (USA and Canada) |
| philpem@0 | 27 | ** (503)268-8001 (other locations) |
| philpem@0 | 28 | ** |
| philpem@0 | 29 | ** web: http://www.latticesemi.com |
| philpem@0 | 30 | ** email: techsupport@latticesemi.com |
| philpem@0 | 31 | ** |
| philpem@0 | 32 | ** -------------------------------------------------------------------------- |
| philpem@0 | 33 | ** |
| philpem@0 | 34 | ** Change History (Latest changes on top) |
| philpem@0 | 35 | ** |
| philpem@0 | 36 | ** Ver Date Description |
| philpem@0 | 37 | ** -------------------------------------------------------------------------- |
| philpem@0 | 38 | ** |
| philpem@0 | 39 | ** 3.0 Mar-25-2008 Added Header |
| philpem@0 | 40 | ** |
| philpem@0 | 41 | **--------------------------------------------------------------------------- |
| philpem@0 | 42 | *****************************************************************************/ |
| philpem@0 | 43 | |
| philpem@0 | 44 | |
| philpem@0 | 45 | #include "MicoTimer.h" |
| philpem@0 | 46 | #include "MicoTimerService.h" |
| philpem@0 | 47 | #include "MicoMacros.h" |
| philpem@0 | 48 | #include "MicoInterrupts.h" |
| philpem@0 | 49 | |
| philpem@0 | 50 | |
| philpem@0 | 51 | |
| philpem@0 | 52 | /************************************************************************** |
| philpem@0 | 53 | * driver-debug functions * |
| philpem@0 | 54 | **************************************************************************/ |
| philpem@0 | 55 | #if _MICO_TIMER_DRIVER_DEBUG_ENABLED_ |
| philpem@0 | 56 | static void MicoTimerDumpCtx(MicoTimerCtx_t *pCtx) |
| philpem@0 | 57 | { |
| philpem@0 | 58 | printf("\n Base : 0x%x", pCtx->base); |
| philpem@0 | 59 | printf("\n IntrLevel: 0x%x", pCtx->intrLevel); |
| philpem@0 | 60 | printf("\n Context : 0x%x", pCtx->userCtx); |
| philpem@0 | 61 | printf("\n Callback : 0x%x", pCtx->callback); |
| philpem@0 | 62 | return; |
| philpem@0 | 63 | } |
| philpem@0 | 64 | |
| philpem@0 | 65 | |
| philpem@0 | 66 | void MicoTimerDumpRegs(MicoTimerCtx_t *pCtx) |
| philpem@0 | 67 | { |
| philpem@0 | 68 | MicoTimer_t *pTimer = (MicoTimer_t *)pCtx->base; |
| philpem@0 | 69 | printf("\n isr-status : 0x%x", pTimer->Status); |
| philpem@0 | 70 | printf("\n isr-control : 0x%x", pTimer->Control); |
| philpem@0 | 71 | printf("\n isr-period : 0x%x", pTimer->Period); |
| philpem@0 | 72 | printf("\n isr-snapshot: 0x%x\n", pTimer->Snapshot); |
| philpem@0 | 73 | } |
| philpem@0 | 74 | #endif |
| philpem@0 | 75 | |
| philpem@0 | 76 | |
| philpem@0 | 77 | /****************************************************************************** |
| philpem@0 | 78 | * Timer interrupt-handler * |
| philpem@0 | 79 | ******************************************************************************/ |
| philpem@0 | 80 | static void MicoTimerISR(unsigned int intrLevel, void *pContext) |
| philpem@0 | 81 | { |
| philpem@0 | 82 | /* |
| philpem@0 | 83 | * flow: |
| philpem@0 | 84 | * - clear the timeout-bit |
| philpem@0 | 85 | * - invoke user-registered callback |
| philpem@0 | 86 | */ |
| philpem@0 | 87 | MicoTimerCtx_t *ctx = (MicoTimerCtx_t *)pContext; |
| philpem@0 | 88 | volatile MicoTimer_t *pTimer = (MicoTimer_t *)ctx->base; |
| philpem@0 | 89 | |
| philpem@0 | 90 | /* acknowledge the interrupt */ |
| philpem@0 | 91 | pTimer->Status = 0; |
| philpem@0 | 92 | |
| philpem@0 | 93 | /* call the isr */ |
| philpem@0 | 94 | if(ctx->callback != 0) |
| philpem@0 | 95 | ((TimerCallback_t)ctx->callback)(ctx->userCtx); |
| philpem@0 | 96 | |
| philpem@0 | 97 | return; |
| philpem@0 | 98 | } |
| philpem@0 | 99 | |
| philpem@0 | 100 | |
| philpem@0 | 101 | /****************************************************************************** |
| philpem@0 | 102 | * Initializes a timer * |
| philpem@0 | 103 | *----------------------------------------------------------------------------* |
| philpem@0 | 104 | * Inputs: * |
| philpem@0 | 105 | * unsigned int IntNum: Interrupt-level * |
| philpem@0 | 106 | * Outputs: * |
| philpem@0 | 107 | * Return values: * |
| philpem@0 | 108 | * MICO_STATUS_E_INVALID_PARAM * |
| philpem@0 | 109 | * MICO_STATUS_OK * |
| philpem@0 | 110 | ******************************************************************************/ |
| philpem@0 | 111 | void MicoTimerInit( MicoTimerCtx_t *ctx ) |
| philpem@0 | 112 | { |
| philpem@0 | 113 | /* stop the timer (if it was running) */ |
| philpem@0 | 114 | MicoTimerStop(ctx); |
| philpem@0 | 115 | |
| philpem@0 | 116 | /* |
| philpem@0 | 117 | * Enable interrupts without registering an isr: |
| philpem@0 | 118 | * this way, any spurious timer interrupt that might have |
| philpem@0 | 119 | * existed prior to this init being called, will cause the |
| philpem@0 | 120 | * Mico Interrupt-framework to acknowlede the CPU's interrupt-pending. |
| philpem@0 | 121 | */ |
| philpem@0 | 122 | MicoEnableInterrupt(ctx->intrLevel); |
| philpem@0 | 123 | |
| philpem@0 | 124 | /* register this timer for lookup service */ |
| philpem@0 | 125 | ctx->lookupReg.name = ctx->name; |
| philpem@0 | 126 | ctx->lookupReg.deviceType = "TimerDevice"; |
| philpem@0 | 127 | ctx->lookupReg.priv = ctx; |
| philpem@0 | 128 | MicoRegisterDevice( &(ctx->lookupReg) ); |
| philpem@0 | 129 | |
| philpem@0 | 130 | /* all done */ |
| philpem@0 | 131 | return; |
| philpem@0 | 132 | } |
| philpem@0 | 133 | |
| philpem@0 | 134 | |
| philpem@0 | 135 | /****************************************************************************** |
| philpem@0 | 136 | * Starts a Mico32 timer * |
| philpem@0 | 137 | *----------------------------------------------------------------------------* |
| philpem@0 | 138 | * Inputs: * |
| philpem@0 | 139 | * MicoTimerCtx_t *ctx: pointer to valid ctx * |
| philpem@0 | 140 | * * |
| philpem@0 | 141 | * TimerCallback_t callback: User-provided callback function, called * |
| philpem@0 | 142 | * in interrupt-context. * |
| philpem@0 | 143 | * * |
| philpem@0 | 144 | * void *priv: user-provided data that will be called in the callback * |
| philpem@0 | 145 | * * |
| philpem@0 | 146 | * unsigned int timercount: ticks to load counter with * |
| philpem@0 | 147 | * * |
| philpem@0 | 148 | * int periodic: if 1, the timer is programmed to auto-load, else * |
| philpem@0 | 149 | * timer is programmed not to reload on reaching terminal value * |
| philpem@0 | 150 | * * |
| philpem@0 | 151 | * Note: user MUST supply a valid ctx. * |
| philpem@0 | 152 | * user MUST make sure timerCount is non-zero * |
| philpem@0 | 153 | ******************************************************************************/ |
| philpem@0 | 154 | mico_status |
| philpem@0 | 155 | MicoTimerStart( MicoTimerCtx_t *ctx, TimerCallback_t callback, void *priv, unsigned int timerCount, int periodic ) |
| philpem@0 | 156 | { |
| philpem@0 | 157 | volatile MicoTimer_t *pTimer; |
| philpem@0 | 158 | unsigned int regValue; |
| philpem@0 | 159 | |
| philpem@0 | 160 | if( (ctx == 0) || (timerCount == 0) ) |
| philpem@0 | 161 | return(MICO_STATUS_E_INVALID_PARAM); |
| philpem@0 | 162 | |
| philpem@0 | 163 | /* flow: |
| philpem@0 | 164 | * - stop the timer, |
| philpem@0 | 165 | * - load new timerCount, |
| philpem@0 | 166 | * - configure the timer, taking into account the periodicity |
| philpem@0 | 167 | * - register the isr (user MUST provide an isr) |
| philpem@0 | 168 | * - start the timer. |
| philpem@0 | 169 | */ |
| philpem@0 | 170 | pTimer = (MicoTimer_t *)(ctx->base); |
| philpem@0 | 171 | regValue = (MICO32_TIMER_CONTROL_START_BIT_MASK|MICO32_TIMER_CONTROL_INT_BIT_MASK); |
| philpem@0 | 172 | ctx->callback = (void *)callback; |
| philpem@0 | 173 | ctx->userCtx = priv; |
| philpem@0 | 174 | |
| philpem@0 | 175 | MicoRegisterISR(ctx->intrLevel, ctx, MicoTimerISR); |
| philpem@0 | 176 | |
| philpem@0 | 177 | if(periodic != 0) |
| philpem@0 | 178 | regValue |= MICO32_TIMER_CONTROL_CONT_BIT_MASK; |
| philpem@0 | 179 | |
| philpem@0 | 180 | |
| philpem@0 | 181 | pTimer->Control = MICO32_TIMER_CONTROL_STOP_BIT_MASK; |
| philpem@0 | 182 | pTimer->Period = timerCount; |
| philpem@0 | 183 | pTimer->Control = regValue; |
| philpem@0 | 184 | |
| philpem@0 | 185 | |
| philpem@0 | 186 | return(MICO_STATUS_OK); |
| philpem@0 | 187 | } |
| philpem@0 | 188 | |
| philpem@0 | 189 | |
| philpem@0 | 190 | /****************************************************************************** |
| philpem@0 | 191 | * * |
| philpem@0 | 192 | * Stops a Mico32 timer * |
| philpem@0 | 193 | * * |
| philpem@0 | 194 | *----------------------------------------------------------------------------* |
| philpem@0 | 195 | * * |
| philpem@0 | 196 | * Note: user MUST supply a valid ctx. * |
| philpem@0 | 197 | * * |
| philpem@0 | 198 | ******************************************************************************/ |
| philpem@0 | 199 | mico_status |
| philpem@0 | 200 | MicoTimerStop(MicoTimerCtx_t *ctx) |
| philpem@0 | 201 | { |
| philpem@0 | 202 | volatile MicoTimer_t *pTimer; |
| philpem@0 | 203 | if(ctx == 0) |
| philpem@0 | 204 | return(MICO_STATUS_E_INVALID_PARAM); |
| philpem@0 | 205 | |
| philpem@0 | 206 | |
| philpem@0 | 207 | /* stop the timer first and ack any pending interrupts */ |
| philpem@0 | 208 | pTimer = (MicoTimer_t *)(ctx->base); |
| philpem@0 | 209 | pTimer->Control = MICO32_TIMER_CONTROL_STOP_BIT_MASK; |
| philpem@0 | 210 | pTimer->Status = 0; |
| philpem@0 | 211 | |
| philpem@0 | 212 | /* all done */ |
| philpem@0 | 213 | return(MICO_STATUS_OK); |
| philpem@0 | 214 | } |
| philpem@0 | 215 | |
| philpem@0 | 216 | |
| philpem@0 | 217 | /****************************************************************************** |
| philpem@0 | 218 | * reads timer-snapshot * |
| philpem@0 | 219 | *----------------------------------------------------------------------------* |
| philpem@0 | 220 | * Note: user MUST supply a valid ctx. * |
| philpem@0 | 221 | ******************************************************************************/ |
| philpem@0 | 222 | unsigned int MicoTimerSnapshot( MicoTimerCtx_t *ctx) |
| philpem@0 | 223 | { |
| philpem@0 | 224 | volatile MicoTimer_t *pTimer; |
| philpem@0 | 225 | if(ctx == 0){ |
| philpem@0 | 226 | return(0); |
| philpem@0 | 227 | } |
| philpem@0 | 228 | pTimer = (MicoTimer_t *)(ctx->base); |
| philpem@0 | 229 | return(pTimer->Snapshot); |
| philpem@0 | 230 | } |
| philpem@0 | 231 |