nutinit.c

Go to the documentation of this file.
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: nutinit.c,v $
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 struct __iobuf {
00149     int     iob_fd;
00150     uint16_t iob_mode;
00151     uint8_t iob_flags;
00152     int     iob_unget;
00153 };
00154 #endif
00155 
00160 
00161 #ifndef NUT_THREAD_MAINSTACK
00162 #define NUT_THREAD_MAINSTACK    1024
00163 #endif
00164 
00165 #ifndef NUT_THREAD_IDLESTACK
00166 /* arm-elf-gcc optimized code used 160 bytes. */
00167 #define NUT_THREAD_IDLESTACK    256
00168 #endif
00169 
00170 #ifdef __CROSSWORKS4ARM__
00171 extern void *__unused_start__;
00172 /*
00173  * Michael, Why does Crossworks needs this one. Is memory configurable
00174  * with the Configurator?
00175  */
00176 extern void *__External_SRAM_segment_end__;
00177 
00178 #define HEAP_START  &__unused_start__
00179 #define HEAP_SIZE  ((uintptr_t)(&__External_SRAM_segment_end__ - 1) - (uintptr_t)(HEAP_START) - 256)
00180 #else   /* GCC */
00181 
00184 #define NUTMEM_END (uintptr_t)(NUTMEM_START + NUTMEM_SIZE - 1U)
00185 extern void *__heap_start;
00186 
00187 #define HEAP_START  &__heap_start
00188 #define HEAP_SIZE  ((uintptr_t) (NUTMEM_END - 256 - (uintptr_t) (&__heap_start)))
00189 #endif
00190 
00191 #if !defined(__arm__) && !defined(__cplusplus)
00192 extern void NutAppMain(void *arg) __attribute__ ((noreturn));
00193 #else
00194 extern void main(void *);
00195 #endif
00196 
00197 
00198 #if defined(OLIMEX_LPCE2294)
00199 /*
00200  * InitHW for OLIMEX LPC-E2294
00201  */
00202 static void InitHW (void)
00203 {
00204   PINSEL0  = 0;
00205   PINSEL1  = 0;
00206 
00207   BCFG2    = 0x03501;
00208   PINSEL2 |= 0x00804000;
00209 } /* InitHW */
00210 
00211 #endif /* OLIMEX_LPCE2294 */
00212 
00213 
00214 
00222 THREAD(NutIdle, arg)
00223 {
00224 #if defined(MCU_GBA) || defined(MCU_LPC2XXX)
00225     InitIrqHandler();
00226 #endif
00227     /* Initialize system timers. */
00228     NutTimerInit();
00229 
00230     /* Read OS configuration from non-volatile memory. We can't do this
00231     ** earlier, because the low level driver may be interrupt driven. */
00232     NutLoadConfig();
00233 
00234     /* Create the main application thread. Watch this carefully when
00235     ** changing compilers and compiler versions. Some handle main()
00236     ** in a special way, like setting the stack pointer and other
00237     ** weird stuff that may break this code. */
00238     NutThreadCreate("main", main, 0, 
00239         (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00240 
00241     /* Enter an idle loop at the lowest priority. This will run when
00242     ** all other threads are waiting for an event. */
00243     NutThreadSetPriority(254);
00244     for (;;) {
00245         /* Check if other threads became ready to run. */
00246         NutThreadYield();
00247         /* Remove terminated threads. */
00248         NutThreadDestroy();
00249         /* We could do some power management. */
00250     }
00251 }
00252 
00260 void NutInit(void)
00261 {
00262     /* Do some basic hardware initialization first. Frankly, these
00263     ** are all hacks and could be done in a more general way. */
00264 #if defined(OLIMEX_LPCE2294)
00265     InitHW();
00266 #elif defined(MCU_AT91)
00267     McuInit();
00268 #endif
00269 #if defined(MCU_AT91SAM7X) || defined (MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE)
00270     {
00271         uint32_t freq = NutGetCpuClock();
00272         /* Set Flash Waite state. */
00273         outr(MC_FMR, ((((freq + freq / 2) / 1000000UL) & 0xFF) << 16) | MC_FWS_2R3W);
00274     }
00275 #endif
00276 #ifdef EARLY_STDIO_DEV
00277     /* We may optionally initialize stdout as early as possible.
00278     ** Be aware, that no heap is available and no threads are 
00279     ** running. We need a very basic driver here, which won't
00280     ** use interrupts or call malloc, NutEventXxx, NutSleep etc. */
00281     {
00282         extern NUTDEVICE EARLY_STDIO_DEV;
00283         static struct __iobuf early_stdout;
00284         /* Initialize the output device. */
00285         EARLY_STDIO_DEV.dev_init(&EARLY_STDIO_DEV);
00286         /* Assign a static iobuf. */
00287         stdout = &early_stdout;
00288         /* Open the device. */
00289         stdout->iob_fd = (int)EARLY_STDIO_DEV.dev_open(&EARLY_STDIO_DEV, "", 0, 0);
00290         /* Set the mode. No idea if this is required. */
00291         stdout->iob_mode = _O_WRONLY | _O_CREAT | _O_TRUNC;
00292         /* A first trial. */
00293         puts("\nStarting Nut/OS");
00294     }
00295 #endif
00296     /* Initialize our heap memory. */
00297     NutHeapAdd(HEAP_START, HEAP_SIZE);
00298 
00299     /* Create idle thread. Note, that the first call to NutThreadCreate 
00300     ** will never return. */
00301     NutThreadCreate("idle", NutIdle, 0, 
00302         (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00303 }
00304 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/