00001 /*************************************************************************** 00002 * system.c 00003 * (C) 2010 Ivan Meleca 00004 * Based on original code written by Ruben Meleca 00005 * www.milos.it 00006 00007 # This program is free software; you can redistribute it and/or modify 00008 # it under the terms of the GNU General Public License as published by 00009 # the Free Software Foundation; either version 2 of the License, or 00010 # (at your option) any later version. 00011 # 00012 # This program is distributed in the hope that it will be useful, 00013 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 # GNU General Public License for more details. 00016 # 00017 # You should have received a copy of the GNU General Public License 00018 # along with this program; if not, write to the Free Software 00019 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 00021 ***************************************************************************/ 00022 00023 #include "system.h" 00024 #include "dbgterm.h" 00025 #include "heap.h" 00026 #include "thread.h" 00027 #include "timer.h" 00028 #include "device.h" 00029 #include "rtc.h" 00030 00073 __BOOL __systemReset = __FALSE; 00074 __STATIC __APP_ENTRY* __systemAppEntry = __NULL; 00075 __STATIC __VOLATILE u32 __systemIrqCount; 00076 __STATIC __VOLATILE u32 __systemTickCount = 0; 00077 __STATIC __VOLATILE u32 __systemSecondsCount = 0; 00078 __STATIC __VOLATILE u32 __systemContextSwCount = 0; 00080 __STATIC __VOLATILE u32 __systemNestingISR = 0; 00081 __STATIC __PTHREAD __systemThreadPtr; 00082 __STATIC __VOLATILE u8 __systemContextSwRequest; 00102 __VOID __systemThread(__VOID) 00103 { 00104 u32 ticks = __systemTickCount; 00105 00106 /* Start thread for software timers */ 00107 #if __CONFIG_ENABLE_SWTIMERS 00108 __timerInit(__CONFIG_STACK_TIMTHREAD); 00109 #endif 00110 00111 /* Initialize the Debug Terminal, if enabled */ 00112 #if __CONFIG_DBGTERM_ENABLED 00113 __dbgInit(); 00114 #endif // __CONFIG_DBGTERM_ENABLED 00115 00116 if (__systemAppEntry) 00117 { 00118 (__systemAppEntry)(); 00119 } 00120 00121 for(;;) 00122 { 00123 00124 #if __CONFIG_ENABLE_WATCHDOG 00125 if (!__systemReset) 00126 { 00127 // __cpuResetWatchdog(); 00128 } 00129 #endif /* __CONFIG_ENABLE_WATCHDOG */ 00130 00131 #if __CONFIG_ENABLE_HEARTBEAT 00132 __cpuHeartBeat(); 00133 #endif /* __CONFIG_ENABLE_HEARTBEAT */ 00134 00135 /* Seconds counter */ 00136 if (__systemTickCount < ticks) 00137 { 00138 /* overflowed */ 00139 ticks = 0xFFFFFFFF - ticks; 00140 } 00141 00142 if (__systemTickCount - ticks > CPU_MS_TO_TICKS(1000)) 00143 { 00144 __systemSecondsCount += (__systemTickCount - ticks) / CPU_MS_TO_TICKS(1000); 00145 ticks = __systemTickCount; 00146 } 00147 00148 __threadSleep(__CONFIG_SYSTHREAD_SLEEP_TIME); 00149 } 00150 } 00151 00158 __STATIC __VOID __systemInitThread(__VOID) 00159 { 00160 00161 /* Create system thread */ 00162 __systemThreadPtr = __threadCreate( "system", /* name */ 00163 __systemThread, /* function */ 00164 __CONFIG_PRIO_SYSTHREAD, /* priority */ 00165 __CONFIG_STACK_SYSTHREAD, /* stack */ 00166 1, /* time to live */ 00167 __NULL); /* parameter */ 00168 00169 /* Call platform custom initialization before activating 00170 * the scheduler 00171 */ 00172 __cpuCustomCreateSystemThread(); 00173 } 00174 00186 __VOID __systemInit(__APP_ENTRY* entry) 00187 { 00188 /* Avoid interrupts we are not handling yet */ 00189 __systemStop(); 00190 00191 __systemAppEntry = entry; 00192 00193 /* Init CPU hardware */ 00194 __cpuInitHardware(); 00195 00196 /* MMU */ 00197 __cpuStartMMU(); 00198 00199 /* Init Interrupts */ 00200 __cpuInitInterrupts(); 00201 00202 /* Init Heap */ 00203 __heapInit(&__CPU_HEAP_BASE, (u32) &__CPU_HEAP_SIZE); 00204 00205 /* Init RTC */ 00206 #if __CONFIG_COMPILE_RTC 00207 __rtcInit(); 00208 #endif /* __CONFIG_COMPILE_RTC */ 00209 00210 /* Initialize Watchdog */ 00211 #if __CONFIG_ENABLE_WATCHDOG 00212 // __cpuStartWatchdog(); 00213 #endif /* __CONFIG_ENABLE_WATCHDOG */ 00214 00215 /* Create System Threads */ 00216 __systemInitThread(); 00217 00218 /* Init Scheduler timer after creating the first thread */ 00219 __cpuInitSchedulerTimer(); 00220 00221 __systemScheduleThreadChange(); 00222 00223 /* Enable interrupts */ 00224 __systemStart(); 00225 00226 /* If everything is OK, we should be running the OS by now. 00227 * This function will never return. __systemThread() will now enter execution under 00228 * the context of the OS. 00229 */ 00230 for (;;) 00231 { 00232 } 00233 } 00234 00242 __VOID __systemProcessTick(__VOID) 00243 { 00244 /* Software system ticks */ 00245 __systemTickCount++; 00246 __threadProcessTick(); 00247 } 00248 00254 __VOID __systemStop(__VOID) 00255 { 00256 if (!__systemIrqCount) 00257 { 00258 __cpuDisableInterrupts(); 00259 } 00260 __systemIrqCount++; 00261 } 00262 00268 __VOID __systemStart(__VOID) 00269 { 00270 if (__systemIrqCount && --__systemIrqCount) { 00271 return; 00272 } 00273 00274 /* enable interrupts */ 00275 __cpuEnableInterrupts(); 00276 } 00277 00278 00289 __VOID __systemEnableScheduler(__VOID) 00290 { 00291 __systemStop(); 00292 if (__systemContextSwCount) 00293 { 00294 __systemContextSwCount--; 00295 00296 /* Check for pending thread change request */ 00297 if (!__systemContextSwCount && __systemContextSwRequest) 00298 { 00299 __systemContextSwRequest = 0; 00300 00301 /* Check if there is a ready thread with higher priority 00302 * than the current one. 00303 */ 00304 if (__threadGetCurrent()) { 00305 if (__threadGetCurrent()->th_priority > __threadGetReady()->th_priority) 00306 { 00307 __threadAddToReadyList(__threadGetCurrent()); 00308 __threadSetCurrent(__NULL); 00309 __systemScheduleThreadChange(); 00310 } 00311 } 00312 } 00313 } 00314 __systemStart(); 00315 } 00316 00324 __VOID __systemDisableScheduler(__VOID) 00325 { 00326 __systemStop(); 00327 __systemContextSwCount++; 00328 if (__cpuThreadChangeScheduled()) 00329 __cpuClearPendingThreadChange(); 00330 __systemStart(); 00331 } 00332 00338 __VOID __systemScheduleThreadChange(__VOID) 00339 { 00340 if (!__systemContextSwCount) 00341 { 00342 __cpuScheduleThreadChange(); 00343 } else 00344 { 00345 __systemContextSwRequest = 1; 00346 } 00347 } 00348 00354 __VOID __systemEnterISR(__VOID) 00355 { 00356 __systemNestingISR++; 00357 } 00358 00365 __VOID __systemLeaveISR(__VOID) 00366 { 00367 __systemNestingISR--; 00368 } 00369 00376 u32 __systemGetTickCount(__VOID) 00377 { 00378 return __systemTickCount; 00379 } 00380 00386 u32 __systemGetSecondsCount(__VOID) 00387 { 00388 return __systemSecondsCount; 00389 } 00390 00396 u32 __systemGetIrqCount(__VOID) 00397 { 00398 return __systemIrqCount; 00399 } 00400 00406 __BOOL __systemSchedulerDisabled(__VOID) 00407 { 00408 if (__systemContextSwCount) return __TRUE; 00409 return __FALSE; 00410 } 00411