00001 /* 00002 * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 * 00032 */ 00033 00034 /* 00035 * $Log$ 00036 * Revision 1.21 2009/02/06 15:37:39 haraldkipp 00037 * Added stack space multiplier and addend. Adjusted stack space. 00038 * 00039 * Revision 1.20 2009/01/19 10:38:00 haraldkipp 00040 * Moved NutLoadConfig from NutInit to the idle thread. We can now use 00041 * standard drivers to read the configuration. 00042 * Added support for early stdout. 00043 * 00044 * Revision 1.19 2009/01/17 11:26:37 haraldkipp 00045 * Getting rid of two remaining BSD types in favor of stdint. 00046 * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'. 00047 * 00048 * Revision 1.18 2009/01/16 17:02:18 haraldkipp 00049 * No longer save any default OS configuration in non-volatile RAM. 00050 * All platforms will now call NutLoadConfig(). 00051 * 00052 * Revision 1.17 2008/08/11 06:59:14 haraldkipp 00053 * BSD types replaced by stdint types (feature request #1282721). 00054 * 00055 * Revision 1.16 2008/08/06 12:51:05 haraldkipp 00056 * Added support for Ethernut 5 (AT91SAM9XE reference design). 00057 * 00058 * Revision 1.15 2008/02/15 16:59:27 haraldkipp 00059 * Spport for AT91SAM7SE512 added. 00060 * 00061 * Revision 1.14 2007/10/04 20:08:00 olereinhardt 00062 * Support for SAM7S256 added 00063 * 00064 * Revision 1.13 2006/09/29 12:39:51 haraldkipp 00065 * Spurious interrupt handling on all supported AT91 devices. 00066 * 00067 * Revision 1.12 2006/07/26 11:17:16 haraldkipp 00068 * Defining AT91_PLL_MAINCK will automatically determine SAM7X clock by 00069 * reading PLL settings. 00070 * 00071 * Revision 1.11 2006/07/18 14:04:10 haraldkipp 00072 * Low level hardware initialization moved to crtat91sam7x256_rom.S. This 00073 * avoids the ugly jump from C code back into the runtime initialization. 00074 * Watchdog reset (tiger bell) removed from idle thread. 00075 * 00076 * Revision 1.10 2006/07/15 11:13:30 haraldkipp 00077 * CPU ran into the data pool of Sam7xLowLevelInit(). Temporarily 00078 * fixed by Andras Albert with an additional global label in the 00079 * startup code. Furthermore Andras changed the clock initialization. 00080 * The CPU is now running at 47.9232 MHz and the MAC starts working. 00081 * Great, TCP/IP is now running on the SAM7X. 00082 * 00083 * Revision 1.9 2006/07/10 14:27:03 haraldkipp 00084 * C++ will use main instead of NutAppMain. Contributed by Matthias Wilde. 00085 * 00086 * Revision 1.8 2006/07/05 07:57:52 haraldkipp 00087 * Daidai's support for AT91SAM7X added. Possibly taken from Atmel. 00088 * May require new coding from ground up in order to not conflict with 00089 * original copyright. 00090 * Nevertheless, many thanks to Daidai for providing his adaption. 00091 * 00092 * Revision 1.7 2006/06/28 17:22:34 haraldkipp 00093 * Make it compile for AT91SAM7X256. 00094 * 00095 * Revision 1.6 2006/03/02 19:43:11 haraldkipp 00096 * Added MCU specific hardware initialization routine. This should be done 00097 * later for all MCUs to avoid contaminating NutInit() with MCU specific 00098 * stuff. For the AT91 the spurious interrupt handler has been added, 00099 * which fixes SF 1440948. 00100 * 00101 * Revision 1.5 2006/02/23 15:34:00 haraldkipp 00102 * Support for Philips LPC2xxx Family and LPC-E2294 Board from Olimex added. 00103 * Many thanks to Michael Fischer for this port. 00104 * 00105 * Revision 1.4 2005/10/24 09:22:29 haraldkipp 00106 * Default idle and main thread stack sizes increased. 00107 * AT91 header file moved. 00108 * 00109 * Revision 1.3 2005/08/02 17:46:45 haraldkipp 00110 * Major API documentation update. 00111 * 00112 * Revision 1.2 2005/07/26 16:17:03 haraldkipp 00113 * Use default stack sizes for main and idle, if none had been defined. 00114 * 00115 * Revision 1.1 2005/05/27 17:16:40 drsung 00116 * Moved the file. 00117 * 00118 * Revision 1.4 2005/04/05 17:52:41 haraldkipp 00119 * Much better implementation of GBA interrupt registration. 00120 * 00121 * Revision 1.3 2004/11/08 18:58:59 haraldkipp 00122 * Configurable stack sizes 00123 * 00124 * Revision 1.2 2004/09/08 10:19:23 haraldkipp 00125 * Made it look more general 00126 * 00127 * Revision 1.1 2004/03/16 16:48:46 haraldkipp 00128 * Added Jan Dubiec's H8/300 port. 00129 * 00130 * 00131 */ 00132 00133 #include <cfg/arch.h> 00134 #include <cfg/memory.h> 00135 #include <cfg/os.h> 00136 #ifdef MCU_GBA 00137 #include <dev/irqreg.h> 00138 #elif defined(MCU_LPC2XXX) 00139 #include <arch/arm/lpc2xxx.h> 00140 #else 00141 #include <arch/arm/at91.h> 00142 #endif 00143 00144 #ifdef EARLY_STDIO_DEV 00145 #include <sys/device.h> 00146 #include <stdio.h> 00147 #include <fcntl.h> 00148 #include <dev/debug.h> 00149 struct __iobuf { 00150 int iob_fd; 00151 uint16_t iob_mode; 00152 uint8_t iob_flags; 00153 int iob_unget; 00154 }; 00155 #endif 00156 00161 00162 #ifndef NUT_THREAD_MAINSTACK 00163 #define NUT_THREAD_MAINSTACK 1024 00164 #endif 00165 00166 #ifndef NUT_THREAD_IDLESTACK 00167 /* arm-elf-gcc optimized code used 160 bytes. */ 00168 #define NUT_THREAD_IDLESTACK 256 00169 #endif 00170 00171 #ifdef __CROSSWORKS_ARM 00172 00173 /* 00174 * A CrossWorks MemoryMap file will be used. Here the memory 00175 * between __heap_start__ and __External_RAM_segment_end__ 00176 * can be used for NutOS. 00177 */ 00178 extern void *__heap_start__; 00179 extern void *__RAM_END_segment_end__; 00180 00181 #define HEAP_START &__heap_start__ 00182 #define HEAP_SIZE ((uintptr_t)(&__RAM_END_segment_end__ - 1) - (uintptr_t)(HEAP_START) - 256) 00183 00184 #else /* GCC */ 00185 00189 #define NUTMEM_END (uintptr_t)(NUTMEM_START + NUTMEM_SIZE - 1U) 00190 extern void *__heap_start; 00191 00192 #define HEAP_START &__heap_start 00193 #define HEAP_SIZE ((uintptr_t) (NUTMEM_END - 256 - (uintptr_t) (&__heap_start))) 00194 #endif 00195 00196 #if !defined(__arm__) && !defined(__cplusplus) 00197 extern void NutAppMain(void *arg) __attribute__ ((noreturn)); 00198 #else 00199 extern void main(void *); 00200 #endif 00201 00202 00203 #if defined(OLIMEX_LPCE2294) 00204 /* 00205 * InitHW for OLIMEX LPC-E2294 00206 */ 00207 static void InitHW (void) 00208 { 00209 PINSEL0 = 0; 00210 PINSEL1 = 0; 00211 00212 BCFG2 = 0x03501; 00213 PINSEL2 |= 0x00804000; 00214 } /* InitHW */ 00215 00216 #endif /* OLIMEX_LPCE2294 */ 00217 00218 00219 00227 THREAD(NutIdle, arg) 00228 { 00229 #if defined(MCU_GBA) || defined(MCU_LPC2XXX) 00230 InitIrqHandler(); 00231 #endif 00232 /* Initialize system timers. */ 00233 NutTimerInit(); 00234 00235 /* Read OS configuration from non-volatile memory. We can't do this 00236 ** earlier, because the low level driver may be interrupt driven. */ 00237 NutLoadConfig(); 00238 00239 /* Create the main application thread. Watch this carefully when 00240 ** changing compilers and compiler versions. Some handle main() 00241 ** in a special way, like setting the stack pointer and other 00242 ** weird stuff that may break this code. */ 00243 NutThreadCreate("main", main, 0, 00244 (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD); 00245 00246 /* Enter an idle loop at the lowest priority. This will run when 00247 ** all other threads are waiting for an event. */ 00248 NutThreadSetPriority(254); 00249 for (;;) { 00250 /* Check if other threads became ready to run. */ 00251 NutThreadYield(); 00252 /* Remove terminated threads. */ 00253 NutThreadDestroy(); 00254 /* We could do some power management. */ 00255 } 00256 } 00257 00265 void NutInit(void) 00266 { 00267 /* Do some basic hardware initialization first. Frankly, these 00268 ** are all hacks and could be done in a more general way. */ 00269 #if defined(OLIMEX_LPCE2294) 00270 InitHW(); 00271 #elif defined(MCU_AT91) 00272 McuInit(); 00273 #endif 00274 #if defined(MCU_AT91SAM7X) || defined (MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE) 00275 { 00276 uint32_t freq = NutGetCpuClock(); 00277 /* Set Flash Waite state. */ 00278 outr(MC_FMR, ((((freq + freq / 2) / 1000000UL) & 0xFF) << 16) | MC_FWS_2R3W); 00279 } 00280 #endif 00281 #ifdef EARLY_STDIO_DEV 00282 /* We may optionally initialize stdout as early as possible. 00283 ** Be aware, that no heap is available and no threads are 00284 ** running. We need a very basic driver here, which won't 00285 ** use interrupts or call malloc, NutEventXxx, NutSleep etc. */ 00286 { 00287 extern NUTDEVICE EARLY_STDIO_DEV; 00288 static struct __iobuf early_stdout; 00289 /* Initialize the output device. */ 00290 EARLY_STDIO_DEV.dev_init(&EARLY_STDIO_DEV); 00291 /* Assign a static iobuf. */ 00292 stdout = &early_stdout; 00293 /* Open the device. */ 00294 stdout->iob_fd = (int)EARLY_STDIO_DEV.dev_open(&EARLY_STDIO_DEV, "", 0, 0); 00295 /* Set the mode. No idea if this is required. */ 00296 stdout->iob_mode = _O_WRONLY | _O_CREAT | _O_TRUNC; 00297 /* A first trial. */ 00298 puts("\nStarting Nut/OS"); 00299 } 00300 #endif 00301 /* Initialize our heap memory. */ 00302 NutHeapAdd(HEAP_START, HEAP_SIZE & ~3); 00303 00304 /* Create idle thread. Note, that the first call to NutThreadCreate 00305 ** will never return. */ 00306 NutThreadCreate("idle", NutIdle, 0, 00307 (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD); 00308 } 00309