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