startup.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  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. struct rt_init_tag
  72. {
  73. const char *level;
  74. init_fn_t fn;
  75. #ifdef RT_DEBUGING_AUTO_INIT
  76. const char *fn_name;
  77. #endif
  78. };
  79. static rt_size_t rt_init_num = 0;
  80. static struct rt_init_tag rt_init_table[2048] = { 0 };
  81. static rt_bool_t rt_init_flag = RT_FALSE;
  82. static int rt_init_objects_sort(void)
  83. {
  84. rt_size_t index_i, index_j;
  85. struct rt_init_tag init_temp = { 0 };
  86. unsigned int *ptr_begin = (unsigned int *)&__rti_fn_begin;
  87. unsigned int *ptr_end = (unsigned int *)&__rti_fn_end;
  88. struct rt_init_tag *table = rt_init_table;
  89. ptr_begin += (sizeof(struct rt_init_desc) / sizeof(unsigned int));
  90. if (rt_init_flag)
  91. return rt_init_num;
  92. while (*ptr_begin == 0)
  93. ptr_begin++;
  94. do (ptr_end--);
  95. while (*ptr_end == 0);
  96. while (ptr_begin < ptr_end)
  97. {
  98. if (*ptr_begin != 0)
  99. {
  100. table->level = ((struct rt_init_desc *)ptr_begin)->level;
  101. table->fn = ((struct rt_init_desc *)ptr_begin)->fn;
  102. #ifdef RT_DEBUGING_AUTO_INIT
  103. table->fn_name = ((struct rt_init_desc *)ptr_begin)->fn_name;
  104. #endif
  105. ptr_begin += sizeof(struct rt_init_desc) / sizeof(unsigned int);
  106. table++;
  107. rt_init_num += 1;
  108. }
  109. else
  110. {
  111. ptr_begin++;
  112. }
  113. }
  114. if (rt_init_num == 0) /* no need sort */
  115. return rt_init_num;
  116. /* bubble sort algorithms */
  117. for (index_i = 0; index_i < (rt_init_num - 1); index_i++)
  118. {
  119. for (index_j = 0; index_j < ((rt_init_num - 1) - index_i); index_j++)
  120. {
  121. if (rt_strcmp(rt_init_table[index_j].level, rt_init_table[index_j + 1].level) > 0)
  122. {
  123. init_temp = rt_init_table[index_j];
  124. rt_init_table[index_j] = rt_init_table[index_j + 1];
  125. rt_init_table[index_j + 1] = init_temp;
  126. }
  127. }
  128. }
  129. rt_init_flag = RT_TRUE;
  130. return rt_init_num;
  131. }
  132. /**
  133. * RT-Thread Components Initialization for board
  134. */
  135. void rt_components_board_init(void)
  136. {
  137. const char* lv_start = ".rti_fn.0";
  138. const char* lv_end = ".rti_fn.1.end";
  139. rt_size_t index_i;
  140. int result;
  141. rt_init_objects_sort();
  142. for (index_i = 0; index_i < rt_init_num; index_i++)
  143. {
  144. if (rt_init_table[index_i].fn)
  145. {
  146. if (rt_strcmp(rt_init_table[index_i].level, lv_end) >= 0)
  147. {
  148. break;
  149. }
  150. #ifdef RT_DEBUGING_AUTO_INIT
  151. rt_kprintf("initialize %s", rt_init_table[index_i].fn_name);
  152. result = rt_init_table[index_i].fn();
  153. rt_kprintf(":%d done\n", result);
  154. #else
  155. result = rt_init_table[index_i].fn();
  156. #endif /* RT_DEBUGING_AUTO_INIT */
  157. }
  158. }
  159. }
  160. /**
  161. * RT-Thread Components Initialization
  162. */
  163. void rt_components_init(void)
  164. {
  165. const char* lv_start = ".rti_fn.1.end";
  166. const char* lv_end = ".rti_fn.6.end";
  167. int result;
  168. rt_size_t index_i;
  169. rt_init_objects_sort();
  170. for (index_i = 0; index_i < rt_init_num; index_i++)
  171. {
  172. if (rt_init_table[index_i].fn)
  173. {
  174. if (rt_strcmp(rt_init_table[index_i].level, lv_start) <= 0)
  175. {
  176. continue;
  177. }
  178. if (rt_strcmp(rt_init_table[index_i].level, lv_end) >= 0)
  179. {
  180. break;
  181. }
  182. #ifdef RT_DEBUGING_AUTO_INIT
  183. rt_kprintf("initialize %s", rt_init_table[index_i].fn_name);
  184. result = rt_init_table[index_i].fn();
  185. rt_kprintf(":%d done\n", result);
  186. #else
  187. result = rt_init_table[index_i].fn();
  188. #endif
  189. }
  190. }
  191. }
  192. #endif /* RT_USING_COMPONENTS_INIT */
  193. #ifdef RT_USING_USER_MAIN
  194. void rt_application_init(void);
  195. void rt_hw_board_init(void);
  196. int rtthread_startup(void);
  197. #if defined(__ARMCC_VERSION)
  198. extern int $Super$$main(void);
  199. /* re-define main function */
  200. int $Sub$$main(void)
  201. {
  202. rtthread_startup();
  203. return 0;
  204. }
  205. #elif defined(__ICCARM__)
  206. extern int main(void);
  207. /* __low_level_init will auto called by IAR cstartup */
  208. extern void __iar_data_init3(void);
  209. int __low_level_init(void)
  210. {
  211. // call IAR table copy function.
  212. __iar_data_init3();
  213. rtthread_startup();
  214. return 0;
  215. }
  216. #elif defined(__GNUC__)
  217. /* Add -eentry to arm-none-eabi-gcc argument */
  218. int entry(void)
  219. {
  220. rtthread_startup();
  221. return 0;
  222. }
  223. #endif
  224. #ifndef RT_USING_HEAP
  225. /* if there is not enable heap, we should use static thread and stack. */
  226. rt_align(8)
  227. static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE];
  228. struct rt_thread main_thread;
  229. #endif
  230. /* the system main thread */
  231. void main_thread_entry(void *parameter)
  232. {
  233. extern int main(void);
  234. #ifdef RT_USING_COMPONENTS_INIT
  235. /* RT-Thread components initialization */
  236. rt_components_init();
  237. #endif
  238. #ifdef RT_USING_SMP
  239. rt_hw_secondary_cpu_up();
  240. #endif
  241. /* invoke system main function */
  242. #if defined(__ARMCC_VERSION)
  243. {
  244. extern int $Super$$main(void);
  245. $Super$$main(); /* for ARMCC. */
  246. }
  247. #elif defined(__ICCARM__) || defined(__GNUC__) || defined(__TASKING__) || defined(_MSC_VER)
  248. main();
  249. #endif
  250. }
  251. void rt_application_init(void)
  252. {
  253. rt_thread_t tid;
  254. #ifdef RT_USING_HEAP
  255. tid = rt_thread_create("main", main_thread_entry, RT_NULL,
  256. RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
  257. RT_ASSERT(tid != RT_NULL);
  258. #else
  259. rt_err_t result;
  260. tid = &main_thread;
  261. result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
  262. main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
  263. RT_ASSERT(result == RT_EOK);
  264. /* if not define RT_USING_HEAP, using to eliminate the warning */
  265. (void)result;
  266. #endif
  267. rt_thread_startup(tid);
  268. }
  269. int rtthread_startup(void)
  270. {
  271. rt_hw_interrupt_disable();
  272. /* board level initialization
  273. * NOTE: please initialize heap inside board initialization.
  274. */
  275. rt_hw_board_init();
  276. /* show RT-Thread version */
  277. rt_show_version();
  278. /* timer system initialization */
  279. rt_system_timer_init();
  280. /* scheduler system initialization */
  281. rt_system_scheduler_init();
  282. #ifdef RT_USING_SIGNALS
  283. /* signal system initialization */
  284. rt_system_signal_init();
  285. #endif
  286. /* create init_thread */
  287. rt_application_init();
  288. /* timer thread initialization */
  289. rt_system_timer_thread_init();
  290. /* idle thread initialization */
  291. rt_thread_idle_init();
  292. #ifdef RT_USING_SMP
  293. rt_hw_spin_lock(&_cpus_lock);
  294. #endif /*RT_USING_SMP*/
  295. /* start scheduler */
  296. rt_system_scheduler_start();
  297. /* never reach here */
  298. return 0;
  299. }
  300. #endif