drivers/service/MicoTimerService.c

changeset 0
396b0bd970d3
     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 +