nutinit.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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 5650 2014-04-07 14:01:47Z u_bonnes $
  35. */
  36. #include <compiler.h>
  37. #include <sys/heap.h>
  38. #include <sys/thread.h>
  39. #include <sys/timer.h>
  40. #include <sys/confos.h>
  41. #include <string.h>
  42. #include <string.h>
  43. #include <cfg/arch.h>
  44. #include <cfg/memory.h>
  45. #include <cfg/os.h>
  46. #include <sys/heap.h>
  47. #include <dev/board.h>
  48. #include <dev/gpio.h>
  49. #include <arch/cm3.h>
  50. #if defined(MCU_STM32F3) || defined(MCU_STM32F4) || defined(MCU_LPC407x_8x)
  51. #include <arch/cm3/core_cm4.h>
  52. #elif defined(MCU_STM32F0)
  53. #include <arch/cm3/core_cm0.h>
  54. #else
  55. #include <arch/cm3/core_cm3.h>
  56. #endif
  57. #if defined(MCU_STM32)
  58. #include <arch/cm3/stm/stm32_clk.h>
  59. #include <arch/cm3/stm/stm32xxxx.h>
  60. #elif defined(MCU_LPC176x)
  61. #include <arch/cm3/nxp/lpc176x.h>
  62. #include <arch/cm3/nxp/lpc176x_clk.h>
  63. #elif defined(MCU_LPC177x_8x)
  64. #include <arch/cm3/nxp/lpc177x_8x.h>
  65. #include <arch/cm3/nxp/lpc177x_8x_clk.h>
  66. #elif defined(MCU_LPC407x_8x)
  67. #include <arch/cm3/nxp/lpc407x_8x.h>
  68. #include <arch/cm3/nxp/lpc407x_8x_clk.h>
  69. #else
  70. #warning "Unknown CM3 family"
  71. #endif
  72. #ifdef EARLY_STDIO_DEV
  73. #include <sys/device.h>
  74. #include <stdio.h>
  75. #include <fcntl.h>
  76. #include <dev/debug.h>
  77. struct __iobuf {
  78. int iob_fd;
  79. uint16_t iob_mode;
  80. uint8_t iob_flags;
  81. int iob_unget;
  82. };
  83. #endif
  84. #ifdef __CROSSWORKS_ARM
  85. #define ATTRIBUTE_NUTINIT_SECTION
  86. #else
  87. #if defined(MCU_LPC17xx)
  88. #define ATTRIBUTE_NUTINIT_SECTION __attribute__((section(".nutinit")))
  89. #else
  90. #define ATTRIBUTE_NUTINIT_SECTION __attribute__((section(".nutinit")))
  91. #endif
  92. #endif
  93. /*!
  94. * \addtogroup xgNutArchArmInit
  95. */
  96. /*@{*/
  97. #ifndef NUT_THREAD_MAINSTACK
  98. #define NUT_THREAD_MAINSTACK 1024
  99. #endif
  100. #ifndef NUT_THREAD_IDLESTACK
  101. /* arm-elf-gcc optimized code used 160 bytes. */
  102. #define NUT_THREAD_IDLESTACK 256
  103. #endif
  104. #ifdef __CROSSWORKS_ARM
  105. /*
  106. * A CrossWorks MemoryMap file will be used. Here the memory
  107. * between __heap_start__ and __External_RAM_segment_end__
  108. * can be used for NutOS.
  109. */
  110. extern void *__RAM_segment_used_end__;
  111. extern void *__RAM_segment_end__;
  112. #define HEAP_START &__RAM_segment_used_end__
  113. #define HEAP_SIZE ((uintptr_t)(&__RAM_segment_end__ - 1) - (uintptr_t)(HEAP_START) - 256)
  114. #else /* GCC */
  115. /*!
  116. * \brief Last memory address.
  117. */
  118. extern void *_ramend;
  119. #define NUTMEM_END &_ramend
  120. /*!
  121. * \brief Start of heap.
  122. */
  123. extern void *__heap_start;
  124. extern void *_ramend;
  125. #define HEAP_START &__heap_start
  126. #define HEAP_SIZE ((uintptr_t)(NUTMEM_END) - (uintptr_t)(HEAP_START))
  127. #endif
  128. #if !defined(__arm__) && !defined(__cplusplus)
  129. extern void NutAppMain(void *arg) __attribute__ ((noreturn));
  130. #else
  131. extern void main(void *);
  132. #endif
  133. static NutIdleCallback IdleCall;
  134. NutIdleCallback NutRegisterIdleCallback(NutIdleCallback func)
  135. {
  136. NutIdleCallback last = IdleCall;
  137. IdleCall = func;
  138. return last;
  139. }
  140. /*!
  141. * \brief Idle thread.
  142. *
  143. * \param arg Ignored by the idle thread.
  144. *
  145. * This function runs in an endless loop as a lowest priority thread.
  146. */
  147. THREAD(ATTRIBUTE_NUTINIT_SECTION NutIdle, arg)
  148. {
  149. #ifdef NUT_INIT_IDLE
  150. NutIdleInit();
  151. #endif
  152. /* Initialize system timers. */
  153. NutTimerInit();
  154. #if defined(HEARTBEAT_IDLE_PORT) && defined(HEARTBEAT_IDLE_PIN)
  155. GpioPinConfigSet(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN, GPIO_CFG_OUTPUT);
  156. GpioPinSetHigh(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN);
  157. #if defined(HEARTBEAT_IDLE_INVERT)
  158. #define HEARTBEAT_ACTIVE() \
  159. GpioPinSetLow(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  160. #define HEARTBEAT_IDLE() \
  161. GpioPinSetHigh(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  162. #else
  163. #define HEARTBEAT_ACTIVE() \
  164. GpioPinSetHigh(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  165. #define HEARTBEAT_IDLE() \
  166. GpioPinSetLow(HEARTBEAT_IDLE_PORT, HEARTBEAT_IDLE_PIN)
  167. #endif
  168. #else
  169. #define HEARTBEAT_ACTIVE()
  170. #define HEARTBEAT_IDLE()
  171. #endif
  172. /* Read OS configuration from non-volatile memory. We can't do this
  173. ** earlier, because the low level driver may be interrupt driven. */
  174. NutLoadConfig();
  175. #ifdef NUT_INIT_MAIN
  176. NutMainInit();
  177. #error main
  178. #endif
  179. /* Create the main application thread. Watch this carefully when
  180. ** changing compilers and compiler versions. Some handle main()
  181. ** in a special way, like setting the stack pointer and other
  182. ** weird stuff that may break this code. */
  183. NutThreadCreate("main", main, 0,
  184. (NUT_THREAD_MAINSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
  185. /* Enter an idle loop at the lowest priority. This will run when
  186. ** all other threads are waiting for an event. */
  187. NutThreadSetPriority(254);
  188. for (;;) {
  189. /* Check if other threads became ready to run. */
  190. NutThreadYield();
  191. /* Remove terminated threads. */
  192. NutThreadDestroy();
  193. if (IdleCall) {
  194. IdleCall();
  195. }
  196. #if defined(HW_MCU_LPC17xx)
  197. /* We could do some power management. */
  198. LPC_SC->PCON = 0x00;
  199. /* Sleep Mode*/
  200. #endif
  201. HEARTBEAT_IDLE();
  202. __WFI();
  203. HEARTBEAT_ACTIVE();
  204. }
  205. }
  206. /*!
  207. * \brief Nut/OS Initialization.
  208. *
  209. * Initializes the memory management and the thread system and starts
  210. * an idle thread, which in turn initializes the timer management.
  211. * Finally the application's main() function is called.
  212. */
  213. void ATTRIBUTE_NUTINIT_SECTION NutInit(void)
  214. {
  215. #if defined(NUTDEBUG_LAZY)
  216. extern uint32_t _stack_end;
  217. static const uint32_t stack_end = (uint32_t)&_stack_end;
  218. __asm__ __volatile__
  219. (
  220. "ldr sp, %0\n\t"
  221. :
  222. : "m"(stack_end)
  223. : "sp"
  224. );
  225. #endif
  226. /* Do some basic hardware initialization first. Frankly, these
  227. ** are all hacks and could be done in a more general way. */
  228. SystemInit();
  229. /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
  230. /* Configure the Flash Latency cycles and enable prefetch buffer */
  231. SetSysClock();
  232. /* Load data segment into ram, clear bss segment, initialize stacks... */
  233. Cortex_Start();
  234. #ifdef EARLY_STDIO_DEV
  235. /* We may optionally initialize stdout as early as possible.
  236. ** Be aware, that no heap is available and no threads are
  237. ** running. We need a very basic driver here, which won't
  238. ** use interrupts or call malloc, NutEventXxx, NutSleep etc. */
  239. {
  240. extern NUTFILE *__fds[FOPEN_MAX];
  241. extern FILE *__iob[FOPEN_MAX];
  242. extern NUTDEVICE EARLY_STDIO_DEV;
  243. static struct __iobuf early_stdout;
  244. /* Initialize the output device. */
  245. EARLY_STDIO_DEV.dev_init(&EARLY_STDIO_DEV);
  246. /* Assign a static iobuf. */
  247. stdout = &early_stdout;
  248. /* Open the device. */
  249. __fds[1] = (int) EARLY_STDIO_DEV.dev_open(&EARLY_STDIO_DEV, "", 0, 0);
  250. __iob[1] = stdout;
  251. stdout->iob_fd = 1;
  252. /* Set the mode. No idea if this is required. */
  253. stdout->iob_mode = _O_WRONLY | _O_CREAT | _O_TRUNC;
  254. /* A first trial. */
  255. puts("\nStarting Nut/OS");
  256. }
  257. #endif
  258. #ifdef NUT_INIT_BOARD
  259. NutBoardInit();
  260. #endif
  261. /* Initialize our heap memory. */
  262. NutHeapAdd(HEAP_START, HEAP_SIZE & ~3);
  263. /* Create idle thread. Note, that the first call to NutThreadCreate
  264. ** will never return. */
  265. NutThreadCreate("idle", NutIdle, 0,
  266. (NUT_THREAD_IDLESTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD);
  267. }
  268. /*@}*/