nutinit.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2006 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.17  2009/02/06 15:37:40  haraldkipp
00037  * Added stack space multiplier and addend. Adjusted stack space.
00038  *
00039  * Revision 1.16  2009/01/16 17:02:19  haraldkipp
00040  * No longer save any default OS configuration in non-volatile RAM.
00041  * All platforms will now call NutLoadConfig().
00042  *
00043  * Revision 1.15  2008/08/27 06:40:41  thornen
00044  * Added MMnet03..04 and MMnet102..104 CPLD initialization.
00045  *
00046  * Revision 1.14  2008/08/26 17:36:45  haraldkipp
00047  * Revoked changes 2008/08/26 by thornen.
00048  *
00049  * Revision 1.12  2008/08/11 11:51:19  thiagocorrea
00050  * Preliminary Atmega2560 compile options, but not yet supported.
00051  * It builds, but doesn't seam to run properly at this time.
00052  *
00053  * Revision 1.11  2008/08/11 06:59:39  haraldkipp
00054  * BSD types replaced by stdint types (feature request #1282721).
00055  *
00056  * Revision 1.10  2007/06/14 07:24:38  freckle
00057  * Disable ADC and buskeeper during idle thread sleep, if IDLE_THREAD_ADC_OFF and IDLE_THREAD_BUSKEEPER_OFF are defined
00058  *
00059  * Revision 1.9  2006/10/07 00:24:14  hwmaier
00060  * Include of sys/heap.h added.
00061  *
00062  * Revision 1.8  2006/09/29 12:39:23  haraldkipp
00063  * Added support for ATmega2561.
00064  *
00065  * Revision 1.7  2006/07/04 03:38:56  hwmaier
00066  * Changed binary constants to hex constants in XNUT board
00067  * initialization code.
00068  *
00069  * Revision 1.6  2006/05/15 11:46:49  haraldkipp
00070  * Added heartbeat port bit, which is regularly toggled by the idle thread.
00071  * Helps to develop on boards with external watchdog hardware that can't be
00072  * disabled.
00073  *
00074  * Revision 1.5  2005/10/17 08:24:55  hwmaier
00075  * All platform specific initialisation (CPLD, IO pins etc.) has been consolidated using the new PLATFORM macro into a new function called NutCustomInit()
00076  *
00077  * Revision 1.4  2005/10/04 06:11:11  hwmaier
00078  * Added support for separating stack and conventional heap as required by AT09CAN128 MCUs
00079  *
00080  * Revision 1.3  2005/09/07 16:22:45  christianwelzel
00081  * Added MMnet02 CPLD initialization
00082  *
00083  * Revision 1.2  2005/08/02 17:46:46  haraldkipp
00084  * Major API documentation update.
00085  *
00086  * Revision 1.1  2005/05/27 17:17:31  drsung
00087  * Moved the file
00088  *
00089  * Revision 1.18  2005/05/16 08:49:37  haraldkipp
00090  * Arthernet requires different wait state settings.
00091  *
00092  * Revision 1.17  2005/02/28 08:44:54  drsung
00093  * Fixed missing return type of NutInitSP
00094  * Removed inlcude file avrpio.h
00095  *
00096  * Revision 1.16  2005/02/26 12:09:28  drsung
00097  * Moved heap initialization to section .init5 to support c++ constructors for static objects.
00098  *
00099  * Revision 1.15  2005/02/10 07:06:48  hwmaier
00100  * Changes to incorporate support for AT90CAN128 CPU
00101  *
00102  * Revision 1.12  2005/01/22 19:30:56  haraldkipp
00103  * Fixes Ethernut 1.3G memory bug.
00104  *
00105  * Revision 1.11  2004/11/08 18:58:59  haraldkipp
00106  * Configurable stack sizes
00107  *
00108  * Revision 1.10  2004/09/01 14:27:03  haraldkipp
00109  * Using configuration values from cfg/memory.h.
00110  * Added configurable reserved memory area.
00111  * Automatic check for external memory removed.
00112  *
00113  * Revision 1.9  2004/07/28 13:43:25  drsung
00114  * Corrected a misplaced #endif after last change.
00115  *
00116  * Revision 1.8  2004/07/09 19:51:17  freckle
00117  * Added new function NutThreadSetSleepMode to tell nut/os to set the MCU
00118  * into sleep mode when idle (avr-gcc && avr128 only)
00119  *
00120  * Revision 1.7  2004/07/09 14:40:43  freckle
00121  * Moved ((volatile u_char *) NUTRAMEND) cast into NUTRAMENDPTR define
00122  *
00123  * Revision 1.6  2004/07/09 14:23:13  freckle
00124  * Allow setting of NUTRAMEND by giving it as a compiler flag
00125  *
00126  * Revision 1.5  2004/05/25 17:13:48  drsung
00127  * Bit name SRW10 is not defined for atmega103, so added some defines to make it compatible.. :-X
00128  *
00129  * Revision 1.4  2004/05/25 12:03:37  olereinhardt
00130  * Sorry, fixed typing bug
00131  *
00132  * Revision 1.3  2004/05/25 12:00:37  olereinhardt
00133  * Newly added 3Waitstate support now needs to be enabled by
00134  * defining NUT_3WAITSTATES. By default this behaves like normal
00135  *
00136  *
00137  * Revision 1.1  2004/03/16 16:48:46  haraldkipp
00138  * Added Jan Dubiec's H8/300 port.
00139  *
00140  *
00141  */
00142 
00143 #include <sys/thread.h>
00144 #include <sys/heap.h>
00145 #include <cfg/memory.h>
00146 #include <cfg/os.h>
00147 #include <cfg/arch/avr.h>
00148 #include <cfg/arch.h>
00149 
00154 
00155 #ifdef NUTXMEM_SIZE
00156 
00159 #define NUTMEM_END (uint16_t)(NUTXMEM_START + (uint16_t)NUTXMEM_SIZE - 1U)
00160 
00161 #else
00162 
00168 #define NUTMEM_END (uint16_t)(NUTMEM_START + (uint16_t)NUTMEM_SIZE - 1U)
00169 
00170 #endif
00171 
00172 #ifndef NUT_THREAD_MAINSTACK
00173 #define NUT_THREAD_MAINSTACK    1024
00174 #endif
00175 
00176 #ifndef NUT_THREAD_IDLESTACK
00177 #if defined(__GNUC__)
00178 /* avr-gcc optimized code used 36 bytes. */
00179 #define NUT_THREAD_IDLESTACK    128
00180 #else
00181 /* icc-avr v7.19 used 132 bytes. */
00182 #define NUT_THREAD_IDLESTACK    256
00183 #endif
00184 #endif
00185 
00186 #ifdef NUTMEM_RESERVED
00187 
00197 uint8_t nutmem_onchip[NUTMEM_RESERVED];
00198 #endif
00199 
00200 /* sleep mode to put avr in idle thread, SLEEP_MODE_NONE is used for for non sleeping */
00201 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00202 uint8_t idle_sleep_mode = SLEEP_MODE_NONE;
00203 
00204 /* AT90CAN128 uses a different register to enter sleep mode */
00205 #if defined(SMCR)
00206 #define AVR_SLEEP_CTRL_REG    SMCR
00207 #else
00208 #define AVR_SLEEP_CTRL_REG    MCUCR
00209 #endif
00210 
00211 #endif
00212 
00213 /*
00214  * Macros used for RTL8019AS EEPROM Emulation.
00215  * See FakeNicEeprom().
00216  */
00217 #if defined(RTL_EESK_BIT) && defined(__GNUC__)
00218 
00219 #ifndef RTL_BASE_ADDR
00220 #define RTL_BASE_ADDR 0x8300
00221 #endif
00222 #define NIC_CR  _MMIO_BYTE(RTL_BASE_ADDR)
00223 #define NIC_EE  _MMIO_BYTE(RTL_BASE_ADDR + 1)
00224 
00225 #if (RTL_EEMU_AVRPORT == AVRPORTB)
00226 #define RTL_EEMU_PORT   PORTB
00227 #define RTL_EEMU_DDR    DDRB
00228 
00229 #elif (RTL_EEMU_AVRPORT == AVRPORTD)
00230 #define RTL_EEMU_PORT   PORTD
00231 #define RTL_EEMU_DDR    DDRD
00232 
00233 #elif (RTL_EEMU_AVRPORT == AVRPORTE)
00234 #define RTL_EEMU_PORT   PORTE
00235 #define RTL_EEMU_DDR    DDRE
00236 
00237 #elif (RTL_EEMU_AVRPORT == AVRPORTF)
00238 #define RTL_EEMU_PORT   PORTF
00239 #define RTL_EEMU_DDR    DDRF
00240 
00241 #else
00242 #define RTL_EE_MEMBUS
00243 #define RTL_EEMU_PORT   PORTC
00244 #define RTL_EEMU_DDR    DDRC
00245 
00246 #endif /* RTL_EEMU_AVRPORT */
00247 
00248 #if (RTL_EEDO_AVRPORT == AVRPORTB)
00249 #define RTL_EEDO_PORT   PORTB
00250 #define RTL_EEDO_DDR    DDRB
00251 
00252 #elif (RTL_EEDO_AVRPORT == AVRPORTD)
00253 #define RTL_EEDO_PORT   PORTD
00254 #define RTL_EEDO_DDR    DDRD
00255 
00256 #elif (RTL_EEDO_AVRPORT == AVRPORTE)
00257 #define RTL_EEDO_PORT   PORTE
00258 #define RTL_EEDO_DDR    DDRE
00259 
00260 #elif (RTL_EEDO_AVRPORT == AVRPORTF)
00261 #define RTL_EEDO_PORT   PORTF
00262 #define RTL_EEDO_DDR    DDRF
00263 
00264 #else
00265 #define RTL_EE_MEMBUS
00266 #define RTL_EEDO_PORT   PORTC
00267 #define RTL_EEDO_DDR    DDRC
00268 
00269 #endif /* RTL_EEDO_AVRPORT */
00270 
00271 #if (RTL_EESK_AVRPORT == AVRPORTB)
00272 #define RTL_EESK_PIN    PINB
00273 #define RTL_EESK_DDR    DDRB
00274 
00275 #elif (RTL_EESK_AVRPORT == AVRPORTD)
00276 #define RTL_EESK_PIN    PIND
00277 #define RTL_EESK_DDR    DDRD
00278 
00279 #elif (RTL_EESK_AVRPORT == AVRPORTE)
00280 #define RTL_EESK_PIN    PINE
00281 #define RTL_EESK_DDR    DDRE
00282 
00283 #elif (RTL_EESK_AVRPORT == AVRPORTF)
00284 #define RTL_EESK_PIN    PINF
00285 #define RTL_EESK_DDR    DDRF
00286 
00287 #else
00288 #define RTL_EE_MEMBUS
00289 #define RTL_EESK_PIN    PINC
00290 #define RTL_EESK_DDR    DDRC
00291 
00292 #endif /* RTL_EESK_AVRPORT */
00293 #endif /* RTL_EESK_BIT && __GNUC__ */
00294 
00295 #ifdef __GNUC__
00296 /*
00297  * Some special declarations for AVRGCC. The runtime library
00298  * executes section .init8 before finally jumping to main().
00299  * We never let it do that jump, but start main() as a
00300  * separate thread. This introduces new problems:
00301  * 1. The compiler reinitializes the stack pointer when
00302  *    entering main, at least version 3.3 does it.
00303  * 2. The compiler doesn't allow to redeclare main to make
00304  *    it fit for NutThreadCreate().
00305  * 3. The runtime library requires, that main is defined
00306  *    somewhere.
00307  * Solutions:
00308  * 1. We do not use main at all, but let the preprocessor
00309  *    redefine it to NutAppMain() in the application code.
00310  *    See compiler.h. Note, that the declaration of NutAppMain
00311  *    in this module differs from the one in the application
00312  *    code. Fortunately the linker doesn't detect this hack.
00313  * 2. We use a linker option to set the symbol main to zero.
00314  *
00315  * Thanks to Joerg Wunsch, who helped to solve this.
00316  */
00317 void NutInit(void) __attribute__ ((naked)) __attribute__ ((section(".init8")));
00318 extern void NutAppMain(void *arg) __attribute__ ((noreturn));
00319 #else
00320 extern void main(void *);
00321 #endif
00322 
00323 /*
00324  * External memory interface for GCC.
00325  */
00326 #if defined(__GNUC__) && defined(NUTXMEM_SIZE)
00327 
00328 /*
00329  * At the very beginning enable extended memory interface.
00330  */
00331 static void NutInitXRAM(void) __attribute__ ((naked, section(".init1"), used));
00332 void NutInitXRAM(void)
00333 {
00334 #if defined(__AVR_AT90CAN128__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
00335 /*
00336  * Note: Register structure of ATCAN128 differs from ATMEGA128 in regards
00337  * to wait states.
00338  */
00339 #ifdef NUT_3WAITSTATES /* One wait state 1 for low, 3 for high memory range */
00340     XMCRA = _BV(SRE) | _BV(SRL2) | _BV(SRW00) | _BV(SRW10) | _BV(SRW11);
00341 #else
00342     XMCRA = _BV(SRE) | _BV(SRW10); /* One wait state for the whole memory range */
00343 #endif
00344 
00345 #elif defined(__AVR_ATmega128__)
00346 
00347     MCUCR = _BV(SRE) | _BV(SRW10);
00348 
00349 /* Configure two sectors, lower sector = 0x1100 - 0x7FFF,
00350  * Upper sector = 0x8000 - 0xFFFF and run 3 wait states for the
00351  * upper sector (NIC), 1 wait state for lower sector (XRAM).
00352  */
00353 #ifdef NUT_3WAITSTATES
00354     XMCRA |= _BV(SRL2) | _BV(SRW00) | _BV(SRW11); /* SRW10 is set in MCUCR */
00355     XMCRB = 0;
00356 #endif
00357 
00358 #else  /* ATmega103 */
00359     MCUCR = _BV(SRE) | _BV(SRW);
00360 #endif
00361 }
00362 
00363 #endif
00364 
00365 
00366 #if defined(RTL_EESK_BIT) && defined(__GNUC__) && defined(NUTXMEM_SIZE)
00367 /*
00368  * Before using extended memory, we need to run the RTL8019AS EEPROM emulation.
00369  * Not doing this may put this controller in a bad state, where it interferes
00370  * the data/address bus.
00371  *
00372  * This function has to be called as early as possible but after the external
00373  * memory interface has been enabled.
00374  *
00375  * The following part is used by the GCC environment only. For ICCAVR it has
00376  * been included in the C startup file.
00377  */
00378 static void FakeNicEeprom(void) __attribute__ ((naked, section(".init1"), used));
00379 void FakeNicEeprom(void)
00380 {
00381     /*
00382      * Prepare the EEPROM emulation port bits. Configure the EEDO
00383      * and the EEMU lines as outputs and set both lines to high.
00384      */
00385 #ifdef RTL_EEMU_BIT
00386     sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00387     sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00388 #endif
00389     sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00390     sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00391 
00392     /* Force the chip to re-read the EEPROM contents. */
00393     NIC_CR = 0xE1;
00394     NIC_EE = 0x40;
00395 
00396     /* No external memory access beyond this point. */
00397 #ifdef RTL_EE_MEMBUS
00398     cbi(MCUCR, SRE);
00399 #endif
00400 
00401     /*
00402      * Loop until the chip stops toggling our EESK input. We do it in
00403      * assembly language to make sure, that no external RAM is used
00404      * for the counter variable.
00405      */
00406     __asm__ __volatile__("\n"   /* */
00407                          "EmuLoop:               " "\n" /* */
00408                          "        ldi  r24, 0    " "\n" /* Clear counter. */
00409                          "        ldi  r25, 0    " "\n" /* */
00410                          "        sbis %0, %1    " "\n" /* Check if EESK set. */
00411                          "        rjmp EmuClkClr " "\n" /* */
00412                          "EmuClkSet:             " "\n" /* */
00413                          "        adiw r24, 1    " "\n" /* Count loops with EESK set. */
00414                          "        breq EmuDone   " "\n" /* Exit loop on counter overflow. */
00415                          "        sbis %0, %1    " "\n" /* Test if EESK is still set. */
00416                          "        rjmp EmuLoop   " "\n" /* EESK changed, do another loop. */
00417                          "        rjmp EmuClkSet " "\n" /* Continue waiting. */
00418                          "EmuClkClr:             " "\n" /* */
00419                          "        adiw r24, 1    " "\n" /* Count loops with EESK clear. */
00420                          "        breq EmuDone   " "\n" /* Exit loop on counter overflow. */
00421                          "        sbic %0, %1    " "\n" /* Test if EESK is still clear. */
00422                          "        rjmp EmuLoop   " "\n" /* EESK changed, do another loop. */
00423                          "        rjmp EmuClkClr " "\n" /* Continue waiting. */
00424                          "EmuDone:               \n\t"  /* */
00425                          :      /* No outputs. */
00426                          :"I"(_SFR_IO_ADDR(RTL_EESK_PIN)), /* Emulation port. */
00427                           "I"(RTL_EESK_BIT)                 /* EESK bit. */
00428                          :"r24", "r25");
00429 
00430     /* Enable memory interface. */
00431 #ifdef RTL_EE_MEMBUS
00432     sbi(MCUCR, SRE);
00433 #endif
00434 
00435     /* Reset port outputs to default. */
00436 #ifdef RTL_EEMU_BIT
00437     cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00438     cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00439 #endif
00440     cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00441     cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00442 }
00443 
00444 #endif /* RTL_EESK_BIT && __GNUC__ && NUTXMEM_SIZE */
00445 
00457 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00458 uint8_t NutThreadSetSleepMode(uint8_t mode)
00459 {
00460     uint8_t old_mode = idle_sleep_mode;
00461     idle_sleep_mode = mode;
00462     return old_mode;
00463 }
00464 #endif
00465 
00471 THREAD(NutIdle, arg)
00472 {
00473 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00474     uint8_t sleep_mode;
00475 #endif
00476 #ifdef IDLE_HEARTBEAT_BIT
00477     uint8_t beat = 0;
00478 #endif
00479 
00480     /* Initialize system timers. */
00481     NutTimerInit();
00482 
00483     /* Create the main application thread. */
00484     NutThreadCreate("main", main, 0, 
00485         (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00486 
00487     /*
00488      * Run in an idle loop at the lowest priority. We can still
00489      * do something useful here, like killing terminated threads
00490      * or putting the CPU into sleep mode.
00491      */
00492     NutThreadSetPriority(254);
00493     for (;;) {
00494         NutThreadYield();
00495         NutThreadDestroy();
00496 
00497 #ifdef IDLE_HEARTBEAT_BIT
00498         if ((beat = !beat) == 0) {
00499             //UDR = '*';
00500             cbi(IDLE_HEARTBEAT_PORT, IDLE_HEARTBEAT_BIT);
00501         }
00502         else {
00503             sbi(IDLE_HEARTBEAT_PORT, IDLE_HEARTBEAT_BIT);
00504         }
00505         sbi(IDLE_HEARTBEAT_DDR, IDLE_HEARTBEAT_BIT);
00506 #endif
00507 
00508 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00509         if (idle_sleep_mode != SLEEP_MODE_NONE) {
00510             sleep_mode = AVR_SLEEP_CTRL_REG & _SLEEP_MODE_MASK;
00511             set_sleep_mode(idle_sleep_mode);
00512 #ifdef IDLE_THREAD_ADC_OFF
00513             uint8_t adc = bit_is_set(ADCSR, ADEN);
00514             cbi(ADCSR, ADEN); // disable ADC
00515 #endif
00516 #ifdef IDLE_THREAD_BUSKEEPER_OFF
00517             uint8_t bitkeeper = bit_is_set(XMCRB, XMBK);
00518             cbi(XMCRB, XMBK); // disable buskeeper
00519 #endif
00520             /* Note:  avr-libc has a sleep_mode() function, but it's broken for
00521             AT90CAN128 with avr-libc version earlier than 1.2 */
00522             AVR_SLEEP_CTRL_REG |= _BV(SE);
00523             __asm__ __volatile__ ("sleep" "\n\t" :: );
00524             AVR_SLEEP_CTRL_REG &= ~_BV(SE);
00525 #ifdef IDLE_THREAD_ADC_OFF
00526             if (bitkeeper) {
00527                 sbi(XMCRB, XMBK); // re-enable buskeeper
00528             }
00529 #endif
00530 #ifdef IDLE_THREAD_BUSKEEPER_OFF
00531             if (adc) {
00532                 sbi(ADCSR, ADEN); // re-enable ADC
00533             }
00534 #endif
00535             set_sleep_mode(sleep_mode);
00536         }
00537 #endif
00538     }
00539 }
00540 
00541 #if defined(__GNUC__)
00542 static void NutInitSP(void) __attribute__ ((naked, section (".init5"), used));
00543 void NutInitSP(void)
00544 {
00545 #if defined (NUTMEM_STACKHEAP)
00546     /* Stack must remain in internal RAM where avr-libc's runtime lib init placed it */
00547 #else
00548    /* Initialize stack pointer to end of external RAM while starting up the system
00549     * to avoid overwriting .data and .bss section.
00550     */
00551     SP = (uint16_t)(NUTMEM_END);
00552 #endif
00553 }
00554 #endif
00555 
00556 #if defined(__GNUC__)
00557 static void NutInitHeap(void) __attribute__ ((naked, section (".init5"), used));
00558 #endif
00559 void NutInitHeap()
00560 {
00561 #if defined (NUTMEM_STACKHEAP) /* Stack resides in internal memory */
00562     NutStackAdd((void *) NUTMEM_START, NUTMEM_STACKHEAP);
00563 #endif
00564     /* Then add the remaining RAM to heap.
00565      *
00566      * 20.Aug.2004 haraldkipp: This had been messed up somehow. It's nice to have
00567      * one continuous heap area, but we lost the ability to have systems with
00568      * a gap between internal and external RAM.
00569      */
00570     if ((uint16_t)NUTMEM_END - (uint16_t) (&__heap_start) > 384) {
00571         NutHeapAdd(&__heap_start, (uint16_t) NUTMEM_END - 256 - (uint16_t) (&__heap_start));
00572     }
00573 }
00574 
00575 #if defined(__GNUC__)
00576 static void NutCustomInit(void) __attribute__ ((naked, section (".init1"), used));
00577 #endif
00578 
00587 void NutCustomInit(void)
00588 /*
00589 * MMnet02..04 and MMnet102..104 CPLD initialization.
00590 */
00591 #if defined(MMNET02)  || defined(MMNET03)  || defined(MMNET04) ||\
00592     defined(MMNET102) || defined(MMNET103) || defined(MMNET104)
00593 {
00594     volatile uint8_t *breg = (uint8_t *)((size_t)-1 & ~0xFF);
00595 
00596     *(breg + 1) = 0x01; // Memory Mode 1, Banked Memory
00597 
00598     /* Assume 14.745600 MHz crystal, set to 115200bps */
00599     outp(7, UBRR);
00600     outp(7, UBRR1L);
00601 }
00602 /*
00603  * Arthernet CPLD initialization.
00604  */
00605 #elif defined(ARTHERNET1)
00606 {
00607     /* Arthernet1 memory setup - mt - TODO: check this
00608     Note: This overwrites the default settings of NutInitXRAM()!
00609     0x1100-0x14FF  CLPD area  -> use 3 Waitstates for 0x1100-0x1FFF (no Limit at 0x1500 available)
00610     0x1500-0xFFFF  Heap/Stack -> use 1 Waitstate  for 0x2000-0xFFFF
00611     */
00612     MCUCR  = _BV(SRE); /* enable xmem-Interface */
00613     XMCRA |= _BV(SRL0) | _BV(SRW01) | _BV(SRW00); /* sep. at 0x2000, 3WS for lower Sector */
00614     XMCRB = 0;
00615 
00616     *((volatile uint8_t *)(ARTHERCPLDSTART)) = 0x10; // arthernet cpld init - Bank
00617     *((volatile uint8_t *)(ARTHERCPLDSPI)) = 0xFF; // arthernet cpld init - SPI
00618 
00619     /* Assume standard Arthernet1 with 16 MHz crystal, set to 38400 bps */
00620     outp(25, UBRR);
00621     outp(25, UBRR1L);
00622 }
00623 /*
00624 * XNUT board initialization
00625 */
00626 #elif defined(XNUT_100) || defined(XNUT_105)
00627 {
00628     PORTB = 0x35;
00629     DDRB  = 0x3F;
00630     PORTD = 0xE8;
00631     DDRD  = 0xB0;
00632     PORTE = 0x0E;
00633     DDRE  = 0x02;
00634     PORTF = 0xF0;
00635     DDRF  = 0x0F;
00636     PORTG = 0x1F;
00637     DDRG  = 0x07;
00638 
00639     ACSR |= _BV(ACD); /* Switch off analog comparator to reduce power consumption */
00640 
00641     /* Init I2C bus w/ 100 kHz */
00642     TWSR = 0;
00643     TWBR = (NUT_CPU_FREQ / 100000UL - 16) / 2; /* 100 kHz I2C */
00644 
00645     /* Set default baudrate */
00646 #if NUT_CPU_FREQ == 14745600
00647     UBRR0L = (NUT_CPU_FREQ / (16 * 9600UL)) - 1;
00648     UBRR1L = (NUT_CPU_FREQ / (16 * 9600UL)) - 1;
00649 #else
00650     sbi(UCSR0A, U2X0);
00651     sbi(UCSR1A, U2X1);
00652     UBRR0L = (NUT_CPU_FREQ / (8 * 9600UL)) - 1;
00653     UBRR1L = (NUT_CPU_FREQ / (8 * 9600UL)) - 1;
00654 #endif
00655 }
00656 /*
00657  * Rest of the world and standard ETHERNUT 1/2
00658  */
00659 #else
00660 {
00661     /* Assume standard Ethernut with 14.745600 MHz crystal, set to 115200bps */
00662     outp(7, UBRR);
00663 #ifdef __AVR_ENHANCED__
00664     outp(7, UBRR1L);
00665 #endif
00666 }
00667 #endif
00668 
00701 void NutInit(void)
00702 {
00703     /*
00704      * We can't use local variables in naked functions.
00705      */
00706 
00707 #ifdef NUTDEBUG
00708     /* Note: The platform's default baudrate will be set in NutCustomInit() */
00709     outp(BV(RXEN) | BV(TXEN), UCR);
00710 #endif
00711 
00712 #ifndef __GNUC__
00713     NutCustomInit();
00714 
00715     /* Initialize stack pointer to end of external RAM while starting up the system
00716      * to avoid overwriting .data and .bss section.
00717      */
00718     SP = (uint16_t)(NUTMEM_END);
00719 
00720     /* Initialize the heap memory
00721      */
00722     NutInitHeap();
00723 #endif /* __GNUC__ */
00724 
00725     /* Read OS configuration from non-volatile memory. */
00726     NutLoadConfig();
00727 
00728     /* Create idle thread
00729      */
00730     NutThreadCreate("idle", NutIdle, 0, 
00731         (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00732 }
00733 

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