Nut/OS  4.10.3
API Reference
nutinit.c
Go to the documentation of this file.
00001 
00036 /*
00037  * $Log: nutinit.c,v $
00038  *
00039  *
00040  */
00041 
00042 #include <cfg/clock.h>
00043 #include <cfg/arch.h>
00044 #include <cfg/memory.h>
00045 #include <cfg/os.h>
00046 #include <sys/heap.h>
00047 #include <sys/confos.h>
00048 #include <sys/thread.h>
00049 #include <sys/timer.h>
00050 
00051 #include <arch/avr32.h>
00052 
00053 #include <arch/avr32/pm.h>
00054 #include <arch/avr32/ihndlr.h>
00055 
00056 
00061 
00062 #ifndef NUT_THREAD_MAINSTACK
00063 #define NUT_THREAD_MAINSTACK    1024
00064 #endif
00065 
00066 /* Unknown optimized value */
00067 #ifndef NUT_THREAD_IDLESTACK
00068 #define NUT_THREAD_IDLESTACK    512
00069 #endif
00070 
00071 
00072 extern void *__heap_start;
00073 
00074 extern void *__ram_start__;
00075 extern void *__ram_size__;
00076 
00080 #undef NUTMEM_START
00081 #define NUTMEM_START ((uint32_t)&__ram_start__)
00082 
00083 #undef NUTMEM_SIZE
00084 #define NUTMEM_SIZE ((uint32_t)&__ram_size__)
00085 
00086 #define NUTMEM_END (uptr_t)(NUTMEM_START + NUTMEM_SIZE - 1U)
00087 extern void *__heap_start;
00088 
00089 #define HEAP_START  &__heap_start
00090 #define HEAP_SIZE  ((uptr_t) (NUTMEM_END - 256 - (uptr_t) (&__heap_start)))
00091 
00092 
00093 #if !defined(__cplusplus)
00094 extern void NutAppMain(void *arg) __attribute__ ((noreturn));
00095 #else
00096 extern void main(void *);
00097 #endif
00098 
00099 
00100 typedef union {
00101     unsigned long fcr;
00102     avr32_flashc_fcr_t FCR;
00103 } u_avr32_flashc_fcr_t;
00104 
00105 static void flashc_set_wait_state(unsigned int wait_state)
00106 {
00107     u_avr32_flashc_fcr_t u_avr32_flashc_fcr = { AVR32_FLASHC.fcr };
00108     u_avr32_flashc_fcr.FCR.fws = wait_state;
00109     AVR32_FLASHC.fcr = u_avr32_flashc_fcr.fcr;
00110 }
00111 
00119 THREAD(NutIdle, arg)
00120 {
00121     /* Init INTC */
00122     init_interrupts();
00123 
00124     /* Initialize system timers. */
00125     NutTimerInit();
00126 
00127     /* Read OS configuration from non-volatile memory. We can't do this
00128      ** earlier, because the low level driver may be interrupt driven. */
00129     NutLoadConfig();
00130 
00131     /* Create the main application thread. Watch this carefully when
00132      ** changing compilers and compiler versions. Some handle main()
00133      ** in a special way, like setting the stack pointer and other
00134      ** weird stuff that may break this code. */
00135     NutThreadCreate("main", main, 0, (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00136 
00137     /*
00138      * Run in an idle loop at the lowest priority. We can still
00139      * do something useful here, like killing terminated threads
00140      * or putting the CPU into sleep mode.
00141      */
00142     NutThreadSetPriority(254);
00143     for (;;) {
00144         NutThreadYield();
00145         NutThreadDestroy();
00146     }
00147 }
00148 
00156 void NutInit(void)
00157 {
00158     uint32_t CPUFrequency;
00159 
00160     /* Switch main clock to Oscillator 0 */
00161     pm_switch_to_osc0(&AVR32_PM, OSC0_VAL, AVR32_PM_OSCCTRL0_STARTUP_2048_RCOSC);
00162 
00163     pm_pll_setup(&AVR32_PM, 0,  /* use PLL0     */
00164                  PLL_MUL_VAL,   /* MUL          */
00165                  PLL_DIV_VAL,   /* DIV          */
00166                  0,             /* Oscillator 0 */
00167                  16);           /* lockcount in main clock for the PLL wait lock */
00168 
00169     /*
00170      * This function will set a PLL option.
00171      *
00172      * pm             Base address of the Power Manager (i.e. &AVR32_PM)
00173      * pll            PLL number 0
00174      * pll_freq       Set to 1 for VCO frequency range 80-180MHz,
00175      *                set to 0 for VCO frequency range 160-240Mhz.
00176      * pll_div2       Divide the PLL output frequency by 2 (this settings does
00177      *                not change the FVCO value)
00178      * pll_wbwdisable 1 Disable the Wide-Bandwidth Mode (Wide-Bandwidth mode
00179      *                allow a faster startup time and out-of-lock time). 0 to
00180      *                enable the Wide-Bandwidth Mode.
00181      */
00182     pm_pll_set_option(&AVR32_PM, 0,     /* use PLL0 */
00183                       PLL_FREQ_VAL,     /* pll_freq */
00184                       PLL_DIV2_VAL,     /* pll_div2 */
00185                       PLL_WBWD_VAL);    /* pll_wbwd */
00186 
00187     /* Enable PLL0 */
00188     pm_pll_enable(&AVR32_PM, 0);
00189 
00190     /* Wait for PLL0 locked */
00191     pm_wait_for_pll0_locked(&AVR32_PM);
00192 
00193     /* Create PBA, PBB and HSB clock */
00194     pm_cksel(&AVR32_PM, PLL_PBADIV_VAL, /* pbadiv */
00195              PLL_PBASEL_VAL,    /* pbasel */
00196              PLL_PBBDIV_VAL,    /* pbbdiv */
00197              PLL_PBBSEL_VAL,    /* pbbsel */
00198              PLL_HSBDIV_VAL,    /* hsbdiv */
00199              PLL_HSBSEL_VAL);   /* hsbsel */
00200 
00201     /* Calculate CPU frequency */
00202     CPUFrequency = (OSC0_VAL * (PLL_MUL_VAL + 1)) / PLL_DIV_VAL;
00203     CPUFrequency = (PLL_DIV2_VAL == 0) ? CPUFrequency : CPUFrequency >> 1;
00204 
00205     if (PLL_HSBDIV_VAL > 0) {
00206         CPUFrequency = CPUFrequency >> (PLL_HSBSEL_VAL + 1);
00207     }
00208 
00209     if (CPUFrequency > AVR32_FLASHC_FWS_0_MAX_FREQ) {
00210         /*
00211          * Set one wait-state (WS) for the flash controller if the 
00212          * HSB/CPU is more than AVR32_FLASHC_FWS_0_MAX_FREQ.
00213          */
00214         flashc_set_wait_state(1);
00215     }
00216 
00217     /* Switch PLL to main clock */
00218     pm_switch_to_clock(&AVR32_PM, AVR32_PM_MCSEL_PLL0);
00219 
00220 #ifdef EARLY_STDIO_DEV
00221     /* We may optionally initialize stdout as early as possible.
00222      ** Be aware, that no heap is available and no threads are 
00223      ** running. We need a very basic driver here, which won't
00224      ** use interrupts or call malloc, NutEventXxx, NutSleep etc. */
00225     {
00226         extern NUTDEVICE EARLY_STDIO_DEV;
00227         static struct __iobuf early_stdout;
00228         /* Initialize the output device. */
00229         EARLY_STDIO_DEV.dev_init(&EARLY_STDIO_DEV);
00230         /* Assign a static iobuf. */
00231         stdout = &early_stdout;
00232         /* Open the device. */
00233         stdout->iob_fd = (int) EARLY_STDIO_DEV.dev_open(&EARLY_STDIO_DEV, "", 0, 0);
00234         /* Set the mode. No idea if this is required. */
00235         stdout->iob_mode = _O_WRONLY | _O_CREAT | _O_TRUNC;
00236         /* A first trial. */
00237         puts("\nStarting Nut/OS");
00238     }
00239 #endif
00240 
00241     /* Initialize our heap memory. */
00242     NutHeapAdd(HEAP_START, HEAP_SIZE);
00243 
00244     /* Create idle thread. Note, that the first call to NutThreadCreate 
00245      ** will never return. */
00246     NutThreadCreate("idle", NutIdle, 0, (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
00247 }
00248