- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# timer_isr.c

    00001 /*********************************************************************************
    00002
    00003  Copyright 2006-2008 MakingThings
    00004
    00005  Licensed under the Apache License,
    00006  Version 2.0 (the "License"); you may not use this file except in compliance
    00007  with the License. You may obtain a copy of the License at
    00008
    00009  http://www.apache.org/licenses/LICENSE-2.0
    00010
    00011  Unless required by applicable law or agreed to in writing, software distributed
    00012  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    00013  CONDITIONS OF ANY KIND, either express or implied. See the License for
    00014  the specific language governing permissions and limitations under the License.
    00015
    00016 *********************************************************************************/
    00017
    00018 /*
    00019   BASIC INTERRUPT DRIVEN DRIVER FOR MAKE BOARD.
    00020 */
    00021
    00022 /* Scheduler includes. */
    00023
    00024 #include "FreeRTOS.h"
    00025
    00026 #include "types.h"
    00027
    00028 #include "timer.h"
    00029 #include "timer_internal.h"
    00030
    00031 #include "io.h"
    00032
    00033 #include "AT91SAM7X256.h"
    00034
    00035 extern struct Timer_ Timer;
    00036
    00037 // At the moment, the Timer ISR or callbacks, very importantly, can't call any OS stuff since
    00038 // the IRQ might happen any old where
    00039
    00040 void Timer_Isr( void ) __attribute__ ((interrupt("IRQ")));
    00041 //void Timer_Isr( void ) __attribute__ ((interrupt(naked)));
    00042
    00043 void Timer_Isr( void )
    00044 {
    00045   /* This ISR can cause a context switch.  Therefore a call to the
    00046   portENTER_SWITCHING_ISR() macro is made.  This must come BEFORE any
    00047   stack variable declarations. */
    00048   // portENTER_SWITCHING_ISR();
    00049
    00050   int status = AT91C_BASE_TC0->TC_SR;
    00051   if ( status & AT91C_TC_CPCS )
    00052   {
    00053     Timer.servicing = true;
    00054
    00055     int jitter;
    00056     Timer.count++;
    00057     jitter = AT91C_BASE_TC0->TC_CV;
    00058
    00059     Timer.jitterTotal += jitter;
    00060     if ( jitter > Timer.jitterMax )
    00061       Timer.jitterMax = jitter;
    00062     if ( jitter > Timer.jitterMaxAllDay )
    00063       Timer.jitterMaxAllDay = jitter;
    00064
    00065     // Run through once to make the callback calls
    00066     TimerEntry* te = Timer.first;
    00067     Timer.next = NULL;
    00068     Timer.previous = NULL;
    00069     Timer.nextTime = -1;
    00070     while ( te != NULL )
    00071     {
    00072       Timer.next = te->next;
    00073       te->timeCurrent -= AT91C_BASE_TC0->TC_RC + AT91C_BASE_TC0->TC_CV;
    00074       if ( te->timeCurrent <= 0 )
    00075       {
    00076         if ( te->repeat )
    00077         {
    00078           te->timeCurrent += te->timeInitial;
    00079         }
    00080         else
    00081         {
    00082           // remove it if necessary (do this first!)
    00083           if ( Timer.previous == NULL )
    00084             Timer.first = Timer.next;
    00085           else
    00086             Timer.previous->next = Timer.next;
    00087         }
    00088
    00089         if ( te->callback != NULL )
    00090         {
    00091           // in this callback, the callee is free to add and remove any members of this list
    00092           // which might effect the first, next and previous pointers
    00093           // so don't assume any of those local variables are good anymore
    00094           (*te->callback)( te->id );
    00095         }
    00096
    00097         // Assuming we're still on the list (if we were removed, then re-added, we'd be on the beggining of
    00098         // the list with this task already performed) see whether our time is the next to run
    00099         if ( ( Timer.previous == NULL && Timer.first == te ) ||
    00100              ( Timer.previous != NULL && Timer.previous->next == te ) )
    00101         {
    00102           if ( Timer.nextTime == -1 || te->timeCurrent < Timer.nextTime )
    00103             Timer.nextTime = te->timeCurrent;
    00104         }
    00105       }
    00106       else
    00107       {
    00108         Timer.previous = te;
    00109       }
    00110
    00111       te = Timer.next;
    00112     }
    00113
    00114     if ( Timer.first != NULL )
    00115     {
    00116       // Add in whatever we're at now
    00117       Timer.nextTime += AT91C_BASE_TC0->TC_CV;
    00118       // Make sure it's not too big
    00119       if ( Timer.nextTime > 0xFFFF )
    00120         Timer.nextTime = 0xFFFF;
    00121       AT91C_BASE_TC0->TC_RC = Timer.nextTime;
    00122     }
    00123     else
    00124     {
    00125       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
    00126       Timer.running = false;
    00127     }
    00128
    00129     jitter = AT91C_BASE_TC0->TC_CV;
    00130
    00131     Timer.servicing = false;
    00132   }
    00133
    00134   /* Clear AIC to complete ISR processing */
    00135   AT91C_BASE_AIC->AIC_EOICR = 0;
    00136
    00137   /* Do a task switch if needed */
    00138   // portEXIT_SWITCHING_ISR( false );
    00139 }
    00140

The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.