drivers/service/MicoTimerService.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

     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 }