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.