MakingThings
  • 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.