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: nutinit.c,v $
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 /* avr-gcc optimized code used 36 bytes. */
00178 #define NUT_THREAD_IDLESTACK    128
00179 #endif
00180 
00181 #ifdef NUTMEM_RESERVED
00182 
00192 uint8_t nutmem_onchip[NUTMEM_RESERVED];
00193 #endif
00194 
00195 /* sleep mode to put avr in idle thread, SLEEP_MODE_NONE is used for for non sleeping */
00196 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00197 uint8_t idle_sleep_mode = SLEEP_MODE_NONE;
00198 
00199 /* AT90CAN128 uses a different register to enter sleep mode */
00200 #if defined(SMCR)
00201 #define AVR_SLEEP_CTRL_REG    SMCR
00202 #else
00203 #define AVR_SLEEP_CTRL_REG    MCUCR
00204 #endif
00205 
00206 #endif
00207 
00208 /*
00209  * Macros used for RTL8019AS EEPROM Emulation.
00210  * See FakeNicEeprom().
00211  */
00212 #if defined(RTL_EESK_BIT) && defined(__GNUC__)
00213 
00214 #ifndef RTL_BASE_ADDR
00215 #define RTL_BASE_ADDR 0x8300
00216 #endif
00217 #define NIC_CR  _MMIO_BYTE(RTL_BASE_ADDR)
00218 #define NIC_EE  _MMIO_BYTE(RTL_BASE_ADDR + 1)
00219 
00220 #if (RTL_EEMU_AVRPORT == AVRPORTB)
00221 #define RTL_EEMU_PORT   PORTB
00222 #define RTL_EEMU_DDR    DDRB
00223 
00224 #elif (RTL_EEMU_AVRPORT == AVRPORTD)
00225 #define RTL_EEMU_PORT   PORTD
00226 #define RTL_EEMU_DDR    DDRD
00227 
00228 #elif (RTL_EEMU_AVRPORT == AVRPORTE)
00229 #define RTL_EEMU_PORT   PORTE
00230 #define RTL_EEMU_DDR    DDRE
00231 
00232 #elif (RTL_EEMU_AVRPORT == AVRPORTF)
00233 #define RTL_EEMU_PORT   PORTF
00234 #define RTL_EEMU_DDR    DDRF
00235 
00236 #else
00237 #define RTL_EE_MEMBUS
00238 #define RTL_EEMU_PORT   PORTC
00239 #define RTL_EEMU_DDR    DDRC
00240 
00241 #endif /* RTL_EEMU_AVRPORT */
00242 
00243 #if (RTL_EEDO_AVRPORT == AVRPORTB)
00244 #define RTL_EEDO_PORT   PORTB
00245 #define RTL_EEDO_DDR    DDRB
00246 
00247 #elif (RTL_EEDO_AVRPORT == AVRPORTD)
00248 #define RTL_EEDO_PORT   PORTD
00249 #define RTL_EEDO_DDR    DDRD
00250 
00251 #elif (RTL_EEDO_AVRPORT == AVRPORTE)
00252 #define RTL_EEDO_PORT   PORTE
00253 #define RTL_EEDO_DDR    DDRE
00254 
00255 #elif (RTL_EEDO_AVRPORT == AVRPORTF)
00256 #define RTL_EEDO_PORT   PORTF
00257 #define RTL_EEDO_DDR    DDRF
00258 
00259 #else
00260 #define RTL_EE_MEMBUS
00261 #define RTL_EEDO_PORT   PORTC
00262 #define RTL_EEDO_DDR    DDRC
00263 
00264 #endif /* RTL_EEDO_AVRPORT */
00265 
00266 #if (RTL_EESK_AVRPORT == AVRPORTB)
00267 #define RTL_EESK_PIN    PINB
00268 #define RTL_EESK_DDR    DDRB
00269 
00270 #elif (RTL_EESK_AVRPORT == AVRPORTD)
00271 #define RTL_EESK_PIN    PIND
00272 #define RTL_EESK_DDR    DDRD
00273 
00274 #elif (RTL_EESK_AVRPORT == AVRPORTE)
00275 #define RTL_EESK_PIN    PINE
00276 #define RTL_EESK_DDR    DDRE
00277 
00278 #elif (RTL_EESK_AVRPORT == AVRPORTF)
00279 #define RTL_EESK_PIN    PINF
00280 #define RTL_EESK_DDR    DDRF
00281 
00282 #else
00283 #define RTL_EE_MEMBUS
00284 #define RTL_EESK_PIN    PINC
00285 #define RTL_EESK_DDR    DDRC
00286 
00287 #endif /* RTL_EESK_AVRPORT */
00288 #endif /* RTL_EESK_BIT && __GNUC__ */
00289 
00290 #ifdef __GNUC__
00291 /*
00292  * Some special declarations for AVRGCC. The runtime library
00293  * executes section .init8 before finally jumping to main().
00294  * We never let it do that jump, but start main() as a
00295  * separate thread. This introduces new problems:
00296  * 1. The compiler reinitializes the stack pointer when
00297  *    entering main, at least version 3.3 does it.
00298  * 2. The compiler doesn't allow to redeclare main to make
00299  *    it fit for NutThreadCreate().
00300  * 3. The runtime library requires, that main is defined
00301  *    somewhere.
00302  * Solutions:
00303  * 1. We do not use main at all, but let the preprocessor
00304  *    redefine it to NutAppMain() in the application code.
00305  *    See compiler.h. Note, that the declaration of NutAppMain
00306  *    in this module differs from the one in the application
00307  *    code. Fortunately the linker doesn't detect this hack.
00308  * 2. We use a linker option to set the symbol main to zero.
00309  *
00310  * Thanks to Joerg Wunsch, who helped to solve this.
00311  */
00312 void NutInit(void) __attribute__ ((naked)) __attribute__ ((section(".init8")));
00313 extern void NutAppMain(void *arg) __attribute__ ((noreturn));
00314 #else
00315 extern void main(void *);
00316 #endif
00317 
00318 /*
00319  * External memory interface for GCC.
00320  */
00321 #if defined(__GNUC__) && defined(NUTXMEM_SIZE)
00322 
00323 /*
00324  * At the very beginning enable extended memory interface.
00325  */
00326 static void NutInitXRAM(void) __attribute__ ((naked, section(".init1"), used));
00327 void NutInitXRAM(void)
00328 {
00329 #if defined(__AVR_AT90CAN128__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
00330 /*
00331  * Note: Register structure of ATCAN128 differs from ATMEGA128 in regards
00332  * to wait states.
00333  */
00334 #ifdef NUT_3WAITSTATES /* One wait state 1 for low, 3 for high memory range */
00335     XMCRA = _BV(SRE) | _BV(SRL2) | _BV(SRW00) | _BV(SRW10) | _BV(SRW11);
00336 #else
00337     XMCRA = _BV(SRE) | _BV(SRW10); /* One wait state for the whole memory range */
00338 #endif
00339 
00340 #elif defined(__AVR_ATmega128__)
00341 
00342     MCUCR = _BV(SRE) | _BV(SRW10);
00343 
00344 /* Configure two sectors, lower sector = 0x1100 - 0x7FFF,
00345  * Upper sector = 0x8000 - 0xFFFF and run 3 wait states for the
00346  * upper sector (NIC), 1 wait state for lower sector (XRAM).
00347  */
00348 #ifdef NUT_3WAITSTATES
00349     XMCRA |= _BV(SRL2) | _BV(SRW00) | _BV(SRW11); /* SRW10 is set in MCUCR */
00350     XMCRB = 0;
00351 #endif
00352 
00353 #else  /* ATmega103 */
00354     MCUCR = _BV(SRE) | _BV(SRW);
00355 #endif
00356 }
00357 
00358 #endif
00359 
00360 
00361 #if defined(RTL_EESK_BIT) && defined(__GNUC__) && defined(NUTXMEM_SIZE)
00362 /*
00363  * Before using extended memory, we need to run the RTL8019AS EEPROM emulation.
00364  * Not doing this may put this controller in a bad state, where it interferes
00365  * the data/address bus.
00366  *
00367  * This function has to be called as early as possible but after the external
00368  * memory interface has been enabled.
00369  *
00370  * The following part is used by the GCC environment only. For ICCAVR it has
00371  * been included in the C startup file.
00372  */
00373 static void FakeNicEeprom(void) __attribute__ ((naked, section(".init1"), used));
00374 void FakeNicEeprom(void)
00375 {
00376     /*
00377      * Prepare the EEPROM emulation port bits. Configure the EEDO
00378      * and the EEMU lines as outputs and set both lines to high.
00379      */
00380 #ifdef RTL_EEMU_BIT
00381     sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00382     sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00383 #endif
00384     sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00385     sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00386 
00387     /* Force the chip to re-read the EEPROM contents. */
00388     NIC_CR = 0xE1;
00389     NIC_EE = 0x40;
00390 
00391     /* No external memory access beyond this point. */
00392 #ifdef RTL_EE_MEMBUS
00393     cbi(MCUCR, SRE);
00394 #endif
00395 
00396     /*
00397      * Loop until the chip stops toggling our EESK input. We do it in
00398      * assembly language to make sure, that no external RAM is used
00399      * for the counter variable.
00400      */
00401     __asm__ __volatile__("\n"   /* */
00402                          "EmuLoop:               " "\n" /* */
00403                          "        ldi  r24, 0    " "\n" /* Clear counter. */
00404                          "        ldi  r25, 0    " "\n" /* */
00405                          "        sbis %0, %1    " "\n" /* Check if EESK set. */
00406                          "        rjmp EmuClkClr " "\n" /* */
00407                          "EmuClkSet:             " "\n" /* */
00408                          "        adiw r24, 1    " "\n" /* Count loops with EESK set. */
00409                          "        breq EmuDone   " "\n" /* Exit loop on counter overflow. */
00410                          "        sbis %0, %1    " "\n" /* Test if EESK is still set. */
00411                          "        rjmp EmuLoop   " "\n" /* EESK changed, do another loop. */
00412                          "        rjmp EmuClkSet " "\n" /* Continue waiting. */
00413                          "EmuClkClr:             " "\n" /* */
00414                          "        adiw r24, 1    " "\n" /* Count loops with EESK clear. */
00415                          "        breq EmuDone   " "\n" /* Exit loop on counter overflow. */
00416                          "        sbic %0, %1    " "\n" /* Test if EESK is still clear. */
00417                          "        rjmp EmuLoop   " "\n" /* EESK changed, do another loop. */
00418                          "        rjmp EmuClkClr " "\n" /* Continue waiting. */
00419                          "EmuDone:               \n\t"  /* */
00420                          :      /* No outputs. */
00421                          :"I"(_SFR_IO_ADDR(RTL_EESK_PIN)), /* Emulation port. */
00422                           "I"(RTL_EESK_BIT)                 /* EESK bit. */
00423                          :"r24", "r25");
00424 
00425     /* Enable memory interface. */
00426 #ifdef RTL_EE_MEMBUS
00427     sbi(MCUCR, SRE);
00428 #endif
00429 
00430     /* Reset port outputs to default. */
00431 #ifdef RTL_EEMU_BIT
00432     cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);
00433     cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);
00434 #endif
00435     cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);
00436     cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);
00437 }
00438 
00439 #endif /* RTL_EESK_BIT && __GNUC__ && NUTXMEM_SIZE */
00440 
00452 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00453 uint8_t NutThreadSetSleepMode(uint8_t mode)
00454 {
00455     uint8_t old_mode = idle_sleep_mode;
00456     idle_sleep_mode = mode;
00457     return old_mode;
00458 }
00459 #endif
00460 
00466 THREAD(NutIdle, arg)
00467 {
00468 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00469     uint8_t sleep_mode;
00470 #endif
00471 #ifdef IDLE_HEARTBEAT_BIT
00472     uint8_t beat = 0;
00473 #endif
00474 
00475     /* Initialize system timers. */
00476     NutTimerInit();
00477 
00478     /* Create the main application thread. */
00479     NutThreadCreate("main", main, 0, 
00480         (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00481 
00482     /*
00483      * Run in an idle loop at the lowest priority. We can still
00484      * do something useful here, like killing terminated threads
00485      * or putting the CPU into sleep mode.
00486      */
00487     NutThreadSetPriority(254);
00488     for (;;) {
00489         NutThreadYield();
00490         NutThreadDestroy();
00491 
00492 #ifdef IDLE_HEARTBEAT_BIT
00493         if ((beat = !beat) == 0) {
00494             //UDR = '*';
00495             cbi(IDLE_HEARTBEAT_PORT, IDLE_HEARTBEAT_BIT);
00496         }
00497         else {
00498             sbi(IDLE_HEARTBEAT_PORT, IDLE_HEARTBEAT_BIT);
00499         }
00500         sbi(IDLE_HEARTBEAT_DDR, IDLE_HEARTBEAT_BIT);
00501 #endif
00502 
00503 #if defined(__GNUC__) && defined(__AVR_ENHANCED__)
00504         if (idle_sleep_mode != SLEEP_MODE_NONE) {
00505             sleep_mode = AVR_SLEEP_CTRL_REG & _SLEEP_MODE_MASK;
00506             set_sleep_mode(idle_sleep_mode);
00507 #ifdef IDLE_THREAD_ADC_OFF
00508             uint8_t adc = bit_is_set(ADCSR, ADEN);
00509             cbi(ADCSR, ADEN); // disable ADC
00510 #endif
00511 #ifdef IDLE_THREAD_BUSKEEPER_OFF
00512             uint8_t bitkeeper = bit_is_set(XMCRB, XMBK);
00513             cbi(XMCRB, XMBK); // disable buskeeper
00514 #endif
00515             /* Note:  avr-libc has a sleep_mode() function, but it's broken for
00516             AT90CAN128 with avr-libc version earlier than 1.2 */
00517             AVR_SLEEP_CTRL_REG |= _BV(SE);
00518             __asm__ __volatile__ ("sleep" "\n\t" :: );
00519             AVR_SLEEP_CTRL_REG &= ~_BV(SE);
00520 #ifdef IDLE_THREAD_ADC_OFF
00521             if (bitkeeper) {
00522                 sbi(XMCRB, XMBK); // re-enable buskeeper
00523             }
00524 #endif
00525 #ifdef IDLE_THREAD_BUSKEEPER_OFF
00526             if (adc) {
00527                 sbi(ADCSR, ADEN); // re-enable ADC
00528             }
00529 #endif
00530             set_sleep_mode(sleep_mode);
00531         }
00532 #endif
00533     }
00534 }
00535 
00536 #if defined(__GNUC__)
00537 static void NutInitSP(void) __attribute__ ((naked, section (".init5"), used));
00538 void NutInitSP(void)
00539 {
00540 #if defined (__AVR_AT90CAN128__)
00541     /* Stack must remain in internal RAM where avr-libc's runtime lib init placed it */
00542 #else
00543    /* Initialize stack pointer to end of external RAM while starting up the system
00544     * to avoid overwriting .data and .bss section.
00545     */
00546     SP = (uint16_t)(NUTMEM_END);
00547 #endif
00548 }
00549 #endif
00550 
00551 #if defined(__GNUC__)
00552 static void NutInitHeap(void) __attribute__ ((naked, section (".init5"), used));
00553 #endif
00554 void NutInitHeap()
00555 {
00556 #if defined (NUTMEM_STACKHEAP) /* Stack resides in internal memory */
00557     NutStackAdd((void *) NUTMEM_START, NUTMEM_STACKHEAP);
00558 #endif
00559     /* Then add the remaining RAM to heap.
00560      *
00561      * 20.Aug.2004 haraldkipp: This had been messed up somehow. It's nice to have
00562      * one continuous heap area, but we lost the ability to have systems with
00563      * a gap between internal and external RAM.
00564      */
00565     if ((uint16_t)NUTMEM_END - (uint16_t) (&__heap_start) > 384) {
00566         NutHeapAdd(&__heap_start, (uint16_t) NUTMEM_END - 256 - (uint16_t) (&__heap_start));
00567     }
00568 }
00569 
00570 #if defined(__GNUC__)
00571 static void NutCustomInit(void) __attribute__ ((naked, section (".init1"), used));
00572 #endif
00573 
00582 void NutCustomInit(void)
00583 /*
00584 * MMnet02..04 and MMnet102..104 CPLD initialization.
00585 */
00586 #if defined(MMNET02)  || defined(MMNET03)  || defined(MMNET04) ||\
00587     defined(MMNET102) || defined(MMNET103) || defined(MMNET104)
00588 {
00589     volatile uint8_t *breg = (uint8_t *)((size_t)-1 & ~0xFF);
00590 
00591     *(breg + 1) = 0x01; // Memory Mode 1, Banked Memory
00592 
00593     /* Assume 14.745600 MHz crystal, set to 115200bps */
00594     outp(7, UBRR);
00595     outp(7, UBRR1L);
00596 }
00597 /*
00598  * Arthernet CPLD initialization.
00599  */
00600 #elif defined(ARTHERNET1)
00601 {
00602     /* Arthernet1 memory setup - mt - TODO: check this
00603     Note: This overwrites the default settings of NutInitXRAM()!
00604     0x1100-0x14FF  CLPD area  -> use 3 Waitstates for 0x1100-0x1FFF (no Limit at 0x1500 available)
00605     0x1500-0xFFFF  Heap/Stack -> use 1 Waitstate  for 0x2000-0xFFFF
00606     */
00607     MCUCR  = _BV(SRE); /* enable xmem-Interface */
00608     XMCRA |= _BV(SRL0) | _BV(SRW01) | _BV(SRW00); /* sep. at 0x2000, 3WS for lower Sector */
00609     XMCRB = 0;
00610 
00611     *((volatile uint8_t *)(ARTHERCPLDSTART)) = 0x10; // arthernet cpld init - Bank
00612     *((volatile uint8_t *)(ARTHERCPLDSPI)) = 0xFF; // arthernet cpld init - SPI
00613 
00614     /* Assume standard Arthernet1 with 16 MHz crystal, set to 38400 bps */
00615     outp(25, UBRR);
00616     outp(25, UBRR1L);
00617 }
00618 /*
00619 * XNUT board initialization
00620 */
00621 #elif defined(XNUT_100) || defined(XNUT_105)
00622 {
00623     PORTB = 0x35;
00624     DDRB  = 0x3F;
00625     PORTD = 0xE8;
00626     DDRD  = 0xB0;
00627     PORTE = 0x0E;
00628     DDRE  = 0x02;
00629     PORTF = 0xF0;
00630     DDRF  = 0x0F;
00631     PORTG = 0x1F;
00632     DDRG  = 0x07;
00633 
00634     ACSR |= _BV(ACD); /* Switch off analog comparator to reduce power consumption */
00635 
00636     /* Init I2C bus w/ 100 kHz */
00637     TWSR = 0;
00638     TWBR = (NUT_CPU_FREQ / 100000UL - 16) / 2; /* 100 kHz I2C */
00639 
00640     /* Set default baudrate */
00641 #if NUT_CPU_FREQ == 14745600
00642     UBRR0L = (NUT_CPU_FREQ / (16 * 9600UL)) - 1;
00643     UBRR1L = (NUT_CPU_FREQ / (16 * 9600UL)) - 1;
00644 #else
00645     sbi(UCSR0A, U2X0);
00646     sbi(UCSR1A, U2X1);
00647     UBRR0L = (NUT_CPU_FREQ / (8 * 9600UL)) - 1;
00648     UBRR1L = (NUT_CPU_FREQ / (8 * 9600UL)) - 1;
00649 #endif
00650 }
00651 /*
00652  * Rest of the world and standard ETHERNUT 1/2
00653  */
00654 #else
00655 {
00656     /* Assume standard Ethernut with 14.745600 MHz crystal, set to 115200bps */
00657     outp(7, UBRR);
00658 #ifdef __AVR_ENHANCED__
00659     outp(7, UBRR1L);
00660 #endif
00661 }
00662 #endif
00663 
00696 void NutInit(void)
00697 {
00698     /*
00699      * We can't use local variables in naked functions.
00700      */
00701 
00702 #ifdef NUTDEBUG
00703     /* Note: The platform's default baudrate will be set in NutCustomInit() */
00704     outp(BV(RXEN) | BV(TXEN), UCR);
00705 #endif
00706 
00707 #ifndef __GNUC__
00708     NutCustomInit();
00709 
00710     /* Initialize stack pointer to end of external RAM while starting up the system
00711      * to avoid overwriting .data and .bss section.
00712      */
00713     SP = (uint16_t)(NUTMEM_END);
00714 
00715     /* Initialize the heap memory
00716      */
00717     NutInitHeap();
00718 #endif /* __GNUC__ */
00719 
00720     /* Read OS configuration from non-volatile memory. */
00721     NutLoadConfig();
00722 
00723     /* Create idle thread
00724      */
00725     NutThreadCreate("idle", NutIdle, 0, 
00726         (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00727 }
00728 

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