drivers/device/MicoTimer.c

Fri, 13 Aug 2010 10:49:23 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Fri, 13 Aug 2010 10:49:23 +0100
changeset 0
396b0bd970d3
permissions
-rw-r--r--

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