Nut/OS  4.10.3
API Reference
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$
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 #include <dev/board.h>
00145 
00146 #ifdef EARLY_STDIO_DEV
00147 #include <sys/device.h>
00148 #include <stdio.h>
00149 #include <fcntl.h>
00150 #include <dev/debug.h>
00151 struct __iobuf {
00152     int     iob_fd;
00153     uint16_t iob_mode;
00154     uint8_t iob_flags;
00155     int     iob_unget;
00156 };
00157 #endif
00158 
00163 
00164 #ifndef NUT_THREAD_MAINSTACK
00165 #define NUT_THREAD_MAINSTACK    1024
00166 #endif
00167 
00168 #ifndef NUT_THREAD_IDLESTACK
00169 /* arm-elf-gcc optimized code used 160 bytes. */
00170 #define NUT_THREAD_IDLESTACK    256
00171 #endif
00172 
00173 #ifdef __CROSSWORKS_ARM
00174 
00175 /*
00176  * A CrossWorks MemoryMap file will be used. Here the memory
00177  * between __heap_start__ and __External_RAM_segment_end__
00178  * can be used for NutOS.
00179  */
00180 extern void *__heap_start__;
00181 extern void *__RAM_END_segment_end__;
00182 
00183 #define HEAP_START  &__heap_start__
00184 #define HEAP_SIZE  ((uintptr_t)(&__RAM_END_segment_end__ - 1) - (uintptr_t)(HEAP_START) - 256)
00185 
00186 #else   /* GCC */
00187 
00191 #define NUTMEM_END (uintptr_t)(NUTMEM_START + NUTMEM_SIZE - 1U)
00192 extern void *__heap_start;
00193 
00194 #define HEAP_START  &__heap_start
00195 #define HEAP_SIZE  ((uintptr_t) (NUTMEM_END - 256 - (uintptr_t) (&__heap_start)))
00196 #endif
00197 
00198 #if !defined(__arm__) && !defined(__cplusplus)
00199 extern void NutAppMain(void *arg) __attribute__ ((noreturn));
00200 #else
00201 extern void main(void *);
00202 #endif
00203 
00204 
00205 #if defined(OLIMEX_LPCE2294)
00206 /*
00207  * InitHW for OLIMEX LPC-E2294
00208  */
00209 static void InitHW (void)
00210 {
00211   PINSEL0  = 0;
00212   PINSEL1  = 0;
00213 
00214   BCFG2    = 0x03501;
00215   PINSEL2 |= 0x00804000;
00216 } /* InitHW */
00217 
00218 #endif /* OLIMEX_LPCE2294 */
00219 
00220 
00221 
00229 THREAD(NutIdle, arg)
00230 {
00231 #if defined(MCU_GBA) || defined(MCU_LPC2XXX)
00232     InitIrqHandler();
00233 #endif
00234 #ifdef NUT_INIT_IDLE
00235     NutIdleInit();
00236 #endif
00237     /* Initialize system timers. */
00238     NutTimerInit();
00239 
00240     /* Read OS configuration from non-volatile memory. We can't do this
00241     ** earlier, because the low level driver may be interrupt driven. */
00242     NutLoadConfig();
00243 
00244 #ifdef NUT_INIT_MAIN
00245     NutMainInit();
00246 #endif
00247 
00248     /* Create the main application thread. Watch this carefully when
00249     ** changing compilers and compiler versions. Some handle main()
00250     ** in a special way, like setting the stack pointer and other
00251     ** weird stuff that may break this code. */
00252     NutThreadCreate("main", main, 0, 
00253         (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00254 
00255     /* Enter an idle loop at the lowest priority. This will run when
00256     ** all other threads are waiting for an event. */
00257     NutThreadSetPriority(254);
00258     for (;;) {
00259         /* Check if other threads became ready to run. */
00260         NutThreadYield();
00261         /* Remove terminated threads. */
00262         NutThreadDestroy();
00263         /* We could do some power management. */
00264     }
00265 }
00266 
00274 void NutInit(void)
00275 {
00276     /* Do some basic hardware initialization first. Frankly, these
00277     ** are all hacks and could be done in a more general way. */
00278 #if defined(OLIMEX_LPCE2294)
00279     InitHW();
00280 #elif defined(MCU_AT91)
00281     McuInit();
00282 #endif
00283 #if defined(MCU_AT91SAM7X) || defined (MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE)
00284     {
00285         uint32_t freq = NutGetCpuClock();
00286         /* Set Flash Waite state. */
00287         outr(MC_FMR, ((((freq + freq / 2) / 1000000UL) & 0xFF) << 16) | MC_FWS_2R3W);
00288     }
00289 #endif
00290 #ifdef EARLY_STDIO_DEV
00291     /* We may optionally initialize stdout as early as possible.
00292     ** Be aware, that no heap is available and no threads are 
00293     ** running. We need a very basic driver here, which won't
00294     ** use interrupts or call malloc, NutEventXxx, NutSleep etc. */
00295     {
00296         extern NUTDEVICE EARLY_STDIO_DEV;
00297         static struct __iobuf early_stdout;
00298         /* Initialize the output device. */
00299         EARLY_STDIO_DEV.dev_init(&EARLY_STDIO_DEV);
00300         /* Assign a static iobuf. */
00301         stdout = &early_stdout;
00302         /* Open the device. */
00303         stdout->iob_fd = (int)EARLY_STDIO_DEV.dev_open(&EARLY_STDIO_DEV, "", 0, 0);
00304         /* Set the mode. No idea if this is required. */
00305         stdout->iob_mode = _O_WRONLY | _O_CREAT | _O_TRUNC;
00306         /* A first trial. */
00307         puts("\nStarting Nut/OS");
00308     }
00309 #endif
00310 #ifdef NUT_INIT_BOARD
00311     NutBoardInit();
00312 #endif
00313     /* Initialize our heap memory. */
00314     NutHeapAdd(HEAP_START, HEAP_SIZE & ~3);
00315 
00316     /* Create idle thread. Note, that the first call to NutThreadCreate 
00317     ** will never return. */
00318     NutThreadCreate("idle", NutIdle, 0, 
00319         (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00320 }
00321