nutinit.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * Copyright (C) 2001-2005 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*
  34. * $Id: nutinit.c 5595 2014-03-21 09:48:21Z u_bonnes $
  35. */
  36. #include <cfg/arch.h>
  37. #include <cfg/memory.h>
  38. #include <cfg/os.h>
  39. #ifdef MCU_AT91
  40. #include <arch/arm/at91.h>
  41. #endif
  42. #include <dev/board.h>
  43. #include <dev/gpio.h>
  44. #ifdef EARLY_STDIO_DEV
  45. #include <sys/device.h>
  46. #include <stdio.h>
  47. #include <fcntl.h>
  48. #include <dev/debug.h>
  49. struct __iobuf {
  50. int iob_fd;
  51. uint16_t iob_mode;
  52. uint8_t iob_flags;
  53. int iob_unget;
  54. };
  55. #endif
  56. /*!
  57. * \addtogroup xgNutArchArmInit
  58. */
  59. /*@{*/
  60. #ifndef NUT_THREAD_MAINSTACK
  61. #define NUT_THREAD_MAINSTACK 1024
  62. #endif
  63. #ifndef NUT_THREAD_IDLESTACK
  64. /* arm-elf-gcc optimized code used 160 bytes. */
  65. #define NUT_THREAD_IDLESTACK 256
  66. #endif
  67. #ifdef __CROSSWORKS_ARM
  68. /*
  69. * A CrossWorks MemoryMap file will be used. Here the memory
  70. * between __heap_start__ and __External_RAM_segment_end__
  71. * can be used for NutOS.
  72. */
  73. extern void *__heap_start__;
  74. extern void *__RAM_END_segment_end__;
  75. #define HEAP_START &__heap_start__
  76. #define HEAP_SIZE ((uintptr_t)(&__RAM_END_segment_end__ - 1) - (uintptr_t)(HEAP_START) - 256)
  77. #else /* GCC */
  78. /*!
  79. * \brief Last memory address.
  80. */
  81. #define NUTMEM_END (uintptr_t)(NUTMEM_START + NUTMEM_SIZE - 1U)
  82. extern void *__heap_start;
  83. #define HEAP_START &__heap_start
  84. #define HEAP_SIZE ((uintptr_t) (NUTMEM_END - 256 - (uintptr_t) (&__heap_start)))
  85. #endif
  86. #if !defined(__arm__) && !defined(__cplusplus)
  87. extern void NutAppMain(void *arg) NUT_NORETURN_FUNC;
  88. #else
  89. extern void main(void *);
  90. #endif
  91. /*!
  92. * \brief Idle thread.
  93. *
  94. * \param arg Ignored by the idle thread.
  95. *
  96. * This function runs in an endless loop as a lowest priority thread.
  97. */
  98. THREAD(NutIdle, arg)
  99. {
  100. #ifdef NUT_INIT_IDLE
  101. NutIdleInit();
  102. #endif
  103. /* Initialize system timers. */
  104. NutTimerInit();
  105. #if defined(HEARTBEAT_IDLE_PORT) && defined(HEARTBEAT_IDLE_PIN)
  106. GpioPinConfigSet(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN,
  107. PIO_CFG_OUTPUT);
  108. GpioPinSetHigh(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN);
  109. #if defined(HEARTBEAT_IDLE_INVERT)
  110. #define HEARTBEAT_ACTIVE() \
  111. GpioPinSetLow(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  112. #define HEARTBEAT_IDLE() \
  113. GpioPinSetHigh(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  114. #else
  115. #define HEARTBEAT_ACTIVE() \
  116. GpioPinSetHigh(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  117. #define HEARTBEAT_IDLE() \
  118. GpioPinSetLow(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  119. #endif
  120. #else
  121. #define HEARTBEAT_ACTIVE()
  122. #define HEARTBEAT_IDLE()
  123. #endif
  124. /* Read OS configuration from non-volatile memory. We can't do this
  125. ** earlier, because the low level driver may be interrupt driven. */
  126. NutLoadConfig();
  127. #ifdef NUT_INIT_MAIN
  128. NutMainInit();
  129. #endif
  130. /* Create the main application thread. Watch this carefully when
  131. ** changing compilers and compiler versions. Some handle main()
  132. ** in a special way, like setting the stack pointer and other
  133. ** weird stuff that may break this code. */
  134. NutThreadCreate("main", main, 0,
  135. (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
  136. /* Enter an idle loop at the lowest priority. This will run when
  137. ** all other threads are waiting for an event. */
  138. NutThreadSetPriority(254);
  139. for (;;) {
  140. HEARTBEAT_ACTIVE();
  141. /* Check if other threads became ready to run. */
  142. NutThreadYield();
  143. /* Remove terminated threads. */
  144. NutThreadDestroy();
  145. /* We could do some power management. */
  146. HEARTBEAT_IDLE();
  147. }
  148. }
  149. /*!
  150. * \brief Nut/OS Initialization.
  151. *
  152. * Initializes the memory management and the thread system and starts
  153. * an idle thread, which in turn initializes the timer management.
  154. * Finally the application's main() function is called.
  155. */
  156. void NutInit(void)
  157. {
  158. /* Do some basic hardware initialization first. Frankly, these
  159. ** are all hacks and could be done in a more general way. */
  160. #if defined(MCU_AT91)
  161. McuInit();
  162. #endif
  163. #if defined(MCU_AT91SAM7X) || defined (MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE)
  164. {
  165. uint32_t freq = NutGetCpuClock();
  166. /* Set Flash Waite state. */
  167. outr(MC_FMR_EFC0, ((((freq + freq / 2) / 1000000UL) & 0xFF) << 16) | MC_FWS_2R3W);
  168. #if defined(MCU_AT91SAM7X512) || defined(MCU_AT91SAM9XE512) || defined(MCU_AT91SAM7SE512)
  169. outr(MC_FMR_EFC1, ((((freq + freq / 2) / 1000000UL) & 0xFF) << 16) | MC_FWS_2R3W);
  170. #endif
  171. }
  172. #endif
  173. #ifdef EARLY_STDIO_DEV
  174. /* We may optionally initialize stdout as early as possible.
  175. ** Be aware, that no heap is available and no threads are
  176. ** running. We need a very basic driver here, which won't
  177. ** use interrupts or call malloc, NutEventXxx, NutSleep etc. */
  178. {
  179. extern NUTFILE *__fds[FOPEN_MAX];
  180. extern FILE *__iob[FOPEN_MAX];
  181. extern NUTDEVICE EARLY_STDIO_DEV;
  182. static struct __iobuf early_stdout;
  183. /* Initialize the output device. */
  184. EARLY_STDIO_DEV.dev_init(&EARLY_STDIO_DEV);
  185. /* Assign a static iobuf. */
  186. stdout = &early_stdout;
  187. /* Open the device. */
  188. __fds[1] = (int) EARLY_STDIO_DEV.dev_open(&EARLY_STDIO_DEV, "", 0, 0);
  189. __iob[1] = stdout;
  190. stdout->iob_fd = 1;
  191. /* Set the mode. No idea if this is required. */
  192. stdout->iob_mode = _O_WRONLY | _O_CREAT | _O_TRUNC;
  193. /* A first trial. */
  194. puts("\nStarting Nut/OS");
  195. }
  196. #endif
  197. #ifdef NUT_INIT_BOARD
  198. NutBoardInit();
  199. #endif
  200. /* Initialize our heap memory. */
  201. NutHeapAdd(HEAP_START, HEAP_SIZE & ~3);
  202. /* Create idle thread. Note, that the first call to NutThreadCreate
  203. ** will never return. */
  204. NutThreadCreate("idle", NutIdle, 0,
  205. (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
  206. }
  207. /*@}*/