startup.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * SPDX-License-Identifier: Apache-2.0
  3. *
  4. * Change Logs:
  5. * Date Author Notes
  6. * 2020-12-04 tyx first implementation
  7. */
  8. #include <rthw.h>
  9. #include <rtthread.h>
  10. #ifdef RT_USING_USER_MAIN
  11. #ifndef RT_MAIN_THREAD_STACK_SIZE
  12. #define RT_MAIN_THREAD_STACK_SIZE 2048
  13. #endif
  14. #ifndef RT_MAIN_THREAD_PRIORITY
  15. #define RT_MAIN_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 3)
  16. #endif
  17. #endif
  18. #ifdef RT_USING_COMPONENTS_INIT
  19. /*
  20. * Components Initialization will initialize some driver and components as following
  21. * order:
  22. * rti_start --> 0
  23. * BOARD_EXPORT --> 1
  24. * rti_board_end --> 1.end
  25. *
  26. * DEVICE_EXPORT --> 2
  27. * COMPONENT_EXPORT --> 3
  28. * FS_EXPORT --> 4
  29. * ENV_EXPORT --> 5
  30. * APP_EXPORT --> 6
  31. *
  32. * rti_end --> 6.end
  33. *
  34. * These automatically initialization, the driver or component initial function must
  35. * be defined with:
  36. * INIT_BOARD_EXPORT(fn);
  37. * INIT_DEVICE_EXPORT(fn);
  38. * ...
  39. * INIT_APP_EXPORT(fn);
  40. * etc.
  41. */
  42. #pragma section("rti_fn$a", read)
  43. const char __rti_fn_begin_name[] = "__rti_fn_start";
  44. __declspec(allocate("rti_fn$a")) const struct rt_init_desc __rti_fn_begin =
  45. {
  46. __rti_fn_begin_name,
  47. NULL
  48. };
  49. #pragma section("rti_fn$z", read)
  50. const char __rti_fn_end_name[] = "__rti_fn_end";
  51. __declspec(allocate("rti_fn$z")) const struct rt_init_desc __rti_fn_end =
  52. {
  53. __rti_fn_end_name,
  54. NULL
  55. };
  56. static int rti_start(void)
  57. {
  58. return 0;
  59. }
  60. INIT_EXPORT(rti_start, "0");
  61. static int rti_board_end(void)
  62. {
  63. return 0;
  64. }
  65. INIT_EXPORT(rti_board_end, "1_end");
  66. static int rti_end(void)
  67. {
  68. return 0;
  69. }
  70. INIT_EXPORT(rti_end, "6_end");
  71. /**
  72. * Find next init function
  73. */
  74. static const struct rt_init_desc* rt_init_find_next(const char* lv,
  75. unsigned int* begin, unsigned int* end)
  76. {
  77. const struct rt_init_desc* ptr;
  78. const struct rt_init_desc* ret_ptr = RT_NULL;
  79. while (begin < end)
  80. {
  81. if (*begin != 0)
  82. {
  83. ptr = (const struct rt_init_desc*)begin;
  84. if (ret_ptr != RT_NULL)
  85. {
  86. if (rt_strcmp(lv, ptr->level) < 0 &&
  87. rt_strcmp(ret_ptr->level, ptr->level) > 0)
  88. {
  89. ret_ptr = ptr;
  90. }
  91. }
  92. else
  93. {
  94. if (rt_strcmp(lv, ptr->level) < 0)
  95. {
  96. ret_ptr = ptr;
  97. }
  98. }
  99. begin += (sizeof(struct rt_init_desc) / sizeof(unsigned int));
  100. }
  101. else
  102. {
  103. begin++;
  104. }
  105. }
  106. return ret_ptr;
  107. }
  108. /**
  109. * RT-Thread Components Initialization for board
  110. */
  111. void rt_components_board_init(void)
  112. {
  113. const struct rt_init_desc* ptr;
  114. const char* lv_start = "0__rt_init_rti_start";
  115. const char* lv_end = "1_end__rt_init_rti_board_end";
  116. unsigned int* ptr_begin = (unsigned int*)&__rti_fn_begin;
  117. unsigned int* ptr_end = (unsigned int*)&__rti_fn_end;
  118. int result;
  119. ptr_begin += (sizeof(struct rt_init_desc) / sizeof(unsigned int));
  120. while (*ptr_begin == 0) ptr_begin++;
  121. do ptr_end--; while (*ptr_end == 0);
  122. while (1)
  123. {
  124. ptr = rt_init_find_next(lv_start, ptr_begin, ptr_end);
  125. if (ptr == RT_NULL ||
  126. rt_strcmp(ptr->level, lv_end) >= 0)
  127. {
  128. break;
  129. }
  130. if (ptr->fn)
  131. {
  132. #if RT_DEBUG_INIT
  133. rt_kprintf("initialize %s", ptr->fn_name);
  134. result = ptr->fn();
  135. rt_kprintf(":%d done\n", result);
  136. #else
  137. result = ptr->fn();
  138. #endif
  139. }
  140. lv_start = ptr->level;
  141. };
  142. }
  143. /**
  144. * RT-Thread Components Initialization
  145. */
  146. void rt_components_init(void)
  147. {
  148. const struct rt_init_desc* ptr;
  149. const char* lv_start = "1_end__rt_init_rti_board_end";
  150. const char* lv_end = "6_end__rt_init_rti_end";
  151. unsigned int* ptr_begin = (unsigned int*)&__rti_fn_begin;
  152. unsigned int* ptr_end = (unsigned int*)&__rti_fn_end;
  153. int result;
  154. ptr_begin += (sizeof(struct rt_init_desc) / sizeof(unsigned int));
  155. while (*ptr_begin == 0) ptr_begin++;
  156. do ptr_end--; while (*ptr_end == 0);
  157. while (1)
  158. {
  159. ptr = rt_init_find_next(lv_start, ptr_begin, ptr_end);
  160. if (ptr == RT_NULL ||
  161. rt_strcmp(ptr->level, lv_end) >= 0)
  162. {
  163. break;
  164. }
  165. if (ptr->fn)
  166. {
  167. #if RT_DEBUG_INIT
  168. rt_kprintf("initialize %s", ptr->fn_name);
  169. result = ptr->fn();
  170. rt_kprintf(":%d done\n", result);
  171. #else
  172. result = ptr->fn();
  173. #endif
  174. }
  175. lv_start = ptr->level;
  176. };
  177. }
  178. #endif /* RT_USING_COMPONENTS_INIT */
  179. #ifdef RT_USING_USER_MAIN
  180. void rt_application_init(void);
  181. void rt_hw_board_init(void);
  182. int rtthread_startup(void);
  183. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  184. extern int $Super$$main(void);
  185. /* re-define main function */
  186. int $Sub$$main(void)
  187. {
  188. rtthread_startup();
  189. return 0;
  190. }
  191. #elif defined(__ICCARM__)
  192. extern int main(void);
  193. /* __low_level_init will auto called by IAR cstartup */
  194. extern void __iar_data_init3(void);
  195. int __low_level_init(void)
  196. {
  197. // call IAR table copy function.
  198. __iar_data_init3();
  199. rtthread_startup();
  200. return 0;
  201. }
  202. #elif defined(__GNUC__)
  203. /* Add -eentry to arm-none-eabi-gcc argument */
  204. int entry(void)
  205. {
  206. rtthread_startup();
  207. return 0;
  208. }
  209. #endif
  210. #ifndef RT_USING_HEAP
  211. /* if there is not enable heap, we should use static thread and stack. */
  212. ALIGN(8)
  213. static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE];
  214. struct rt_thread main_thread;
  215. #endif
  216. /* the system main thread */
  217. void main_thread_entry(void *parameter)
  218. {
  219. extern int main(void);
  220. #ifdef RT_USING_COMPONENTS_INIT
  221. /* RT-Thread components initialization */
  222. rt_components_init();
  223. #endif
  224. #ifdef RT_USING_SMP
  225. rt_hw_secondary_cpu_up();
  226. #endif
  227. /* invoke system main function */
  228. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  229. {
  230. extern int $Super$$main(void);
  231. $Super$$main(); /* for ARMCC. */
  232. }
  233. #elif defined(__ICCARM__) || defined(__GNUC__) || defined(__TASKING__) || defined(_MSC_VER)
  234. main();
  235. #endif
  236. }
  237. void rt_application_init(void)
  238. {
  239. rt_thread_t tid;
  240. #ifdef RT_USING_HEAP
  241. tid = rt_thread_create("main", main_thread_entry, RT_NULL,
  242. RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
  243. RT_ASSERT(tid != RT_NULL);
  244. #else
  245. rt_err_t result;
  246. tid = &main_thread;
  247. result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
  248. main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
  249. RT_ASSERT(result == RT_EOK);
  250. /* if not define RT_USING_HEAP, using to eliminate the warning */
  251. (void)result;
  252. #endif
  253. rt_thread_startup(tid);
  254. }
  255. int rtthread_startup(void)
  256. {
  257. rt_hw_interrupt_disable();
  258. /* board level initialization
  259. * NOTE: please initialize heap inside board initialization.
  260. */
  261. rt_hw_board_init();
  262. /* show RT-Thread version */
  263. rt_show_version();
  264. /* timer system initialization */
  265. rt_system_timer_init();
  266. /* scheduler system initialization */
  267. rt_system_scheduler_init();
  268. #ifdef RT_USING_SIGNALS
  269. /* signal system initialization */
  270. rt_system_signal_init();
  271. #endif
  272. /* create init_thread */
  273. rt_application_init();
  274. /* timer thread initialization */
  275. rt_system_timer_thread_init();
  276. /* idle thread initialization */
  277. rt_thread_idle_init();
  278. #ifdef RT_USING_SMP
  279. rt_hw_spin_lock(&_cpus_lock);
  280. #endif /*RT_USING_SMP*/
  281. /* start scheduler */
  282. rt_system_scheduler_start();
  283. /* never reach here */
  284. return 0;
  285. }
  286. #endif