MakingThings
  • Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

fasttimer_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 #include "types.h"
00026 #include "fasttimer.h"
00027 #include "fasttimer_internal.h"
00028 #include "AT91SAM7X256.h"
00029 
00030 void DisableFIQFromThumb( void )
00031 {
00032   asm volatile ( "STMDB SP!, {R0}" );   /* Push R0.                 */
00033   asm volatile ( "MRS   R0, CPSR" );    /* Get CPSR.                */
00034   asm volatile ( "ORR   R0, R0, #0x40" ); /* Disable FIQ.           */
00035   asm volatile ( "MSR   CPSR, R0" );    /* Write back modified value.       */
00036   asm volatile ( "LDMIA SP!, {R0}" );   /* Pop R0.                  */
00037   asm volatile ( "BX    R14" );       /* Return back to thumb.          */
00038 }
00039     
00040 void EnableFIQFromThumb( void )
00041 {
00042   asm volatile ( "STMDB SP!, {R0}" );   /* Push R0.                 */  
00043   asm volatile ( "MRS   R0, CPSR" );    /* Get CPSR.                */  
00044   asm volatile ( "BIC   R0, R0, #0x40" ); /* Enable FIQ.              */  
00045   asm volatile ( "MSR   CPSR, R0" );    /* Write back modified value.       */  
00046   asm volatile ( "LDMIA SP!, {R0}" );   /* Pop R0.                  */
00047   asm volatile ( "BX    R14" );       /* Return back to thumb.          */
00048 }
00049 
00050 extern struct FastTimer_ FastTimer;
00051 
00052 // At the moment, the FastTimer ISR or callbacks, very importantly, can't call any OS stuff since
00053 // the IRQ might happen any old where
00054 
00055 void FastTimer_Isr( void ) __attribute__ ((naked));
00056 
00057 // Made non-local for debugging
00058 FastTimerEntry* te;
00059 int jitter;
00060 int timeReference;
00061 
00062 void FastTimer_Isr( void )
00063 {
00064   portENTER_FIQ( );
00065   int status = AT91C_BASE_TC2->TC_SR;
00066   if ( status & AT91C_TC_CPCS )
00067   {
00068     FastTimer.servicing = true;
00069 
00070     //AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS;
00071 
00072     // make sure there's not another IRQ while we're processing
00073     timeReference = AT91C_BASE_TC2->TC_RC;
00074     AT91C_BASE_TC2->TC_RC = 0xFF00;
00075 
00076 #ifdef FASTIRQ_MONITOR_IO
00077     Io_SetTrue( FASTIRQ_MONITOR_IO );
00078 #endif
00079 
00080 #ifdef FASTIRQ_STATS
00081     int startCount = AT91C_BASE_TC2->TC_CV;
00082 
00083     // moved outside for debugging
00084     //int jitter;
00085     jitter = AT91C_BASE_TC2->TC_CV;
00086 
00087     if ( ++FastTimer.count == 1000 )
00088     {
00089       // need to not do division here... takes too long
00090       //FastTimer.jitterTotal = FastTimer.jitterTotal / FastTimer.count;
00091       FastTimer.jitterTotal = 0;
00092       FastTimer.jitterMax = 0;
00093       // need to not do division here... takes too long
00094       // FastTimer.durationTotal = FastTimer.durationTotal / FastTimer.count;
00095       FastTimer.durationTotal = 0;
00096       FastTimer.durationMax = 0;
00097       FastTimer.count = 1;
00098     }
00099     
00100     FastTimer.jitterTotal += jitter;
00101         
00102     if ( jitter > FastTimer.jitterMax )
00103       FastTimer.jitterMax = jitter;
00104     if ( jitter > FastTimer.jitterMaxAllDay )
00105       FastTimer.jitterMaxAllDay = jitter;
00106 
00107 #endif
00108 
00109     //FastTimerEntry* te = FastTimer.first;
00110     // Use this during debuggin
00111     te = FastTimer.first;
00112 
00113     FastTimer.next = NULL;
00114     FastTimer.previous = NULL;
00115     FastTimer.nextTime = 0xFF00;
00116     int removed = false;
00117     // timeReference = AT91C_BASE_TC2->TC_CV;
00118 
00119     while ( te != NULL )
00120     {
00121       FastTimer.next = te->next;
00122       te->timeCurrent -= ( timeReference + AT91C_BASE_TC2->TC_CV );
00123       if ( te->timeCurrent <= FASTTIMER_MINCOUNT )
00124       {
00125         // Watch out for gross errors
00126         //if ( te->timeCurrent < -FASTTIMER_MINCOUNT)
00127         //  te->timeCurrent = -FASTTIMER_MINCOUNT;
00128 
00129         if ( te->repeat )
00130         {
00131           te->timeCurrent += te->timeInitial;
00132         }
00133         else
00134         {
00135           // remove it if necessary (do this first!)
00136           if ( FastTimer.previous == NULL )
00137             FastTimer.first = FastTimer.next;
00138           else
00139             FastTimer.previous->next = FastTimer.next;  
00140           removed = true;
00141         }
00142 
00143         if ( te->callback != NULL )
00144         {
00145           // in this callback, the callee is free to add and remove any members of this list
00146           // which might effect the first, next and previous pointers
00147           // so don't assume any of those local variables are good anymore
00148           (*te->callback)( te->id );
00149         }
00150       }
00151       
00152       // note that this has to be better than this ultimately - since
00153       // the callback routine can remove the entry without letting us know
00154       // at all.
00155       if ( !removed )
00156       {
00157         if ( FastTimer.nextTime == -1 || te->timeCurrent < FastTimer.nextTime )
00158         {
00159           FastTimer.nextTime = te->timeCurrent;
00160         }
00161         FastTimer.previous = te;
00162       }
00163 
00164       te = FastTimer.next;
00165     }
00166 
00167     if ( FastTimer.first != NULL )
00168     {
00169       // Make sure it's not too big
00170       if ( FastTimer.nextTime > 0xFF00 )
00171         FastTimer.nextTime = 0xFF00;
00172       // Make sure it's not too small
00173       if ( FastTimer.nextTime < (int)AT91C_BASE_TC2->TC_CV + 20 )
00174         FastTimer.nextTime = AT91C_BASE_TC2->TC_CV + 20;
00175       AT91C_BASE_TC2->TC_RC = FastTimer.nextTime;
00176     }
00177     else
00178     {
00179       AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS;
00180       FastTimer.running = false;
00181     }
00182 
00183 #ifdef FASTIRQ_STATS    
00184     int duration = AT91C_BASE_TC2->TC_CV - startCount;
00185     FastTimer.durationTotal += duration;  
00186     if ( duration > FastTimer.durationMax )
00187       FastTimer.durationMax = duration;
00188     if ( duration > FastTimer.durationMaxAllDay )
00189       FastTimer.durationMaxAllDay = duration;
00190 #endif
00191 
00192 #ifdef FASTIRQ_MONITOR_IO    
00193     Io_SetFalse( FASTIRQ_MONITOR_IO );
00194 #endif
00195 
00196     // AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
00197     FastTimer.servicing = false;
00198   }
00199   portEXIT_FIQ( );
00200 }
00201 

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.