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.