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
9 #include <rthw.h>
10 #include <rtthread.h>
11
12 #ifdef RT_USING_USER_MAIN
13 #ifndef RT_MAIN_THREAD_STACK_SIZE
14 #define RT_MAIN_THREAD_STACK_SIZE 2048
15 #endif
16 #ifndef RT_MAIN_THREAD_PRIORITY
17 #define RT_MAIN_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX / 3)
18 #endif
19 #endif
20
21 #ifdef RT_USING_COMPONENTS_INIT
22 /*
23 * Components Initialization will initialize some driver and components as following
24 * order:
25 * rti_start --> 0
26 * BOARD_EXPORT --> 1
27 * rti_board_end --> 1.end
28 *
29 * DEVICE_EXPORT --> 2
30 * COMPONENT_EXPORT --> 3
31 * FS_EXPORT --> 4
32 * ENV_EXPORT --> 5
33 * APP_EXPORT --> 6
34 *
35 * rti_end --> 6.end
36 *
37 * These automatically initialization, the driver or component initial function must
38 * be defined with:
39 * INIT_BOARD_EXPORT(fn);
40 * INIT_DEVICE_EXPORT(fn);
41 * ...
42 * INIT_APP_EXPORT(fn);
43 * etc.
44 */
45
46 #pragma section("rti_fn$a", read)
47 const char __rti_fn_begin_name[] = "__rti_fn_start";
48 __declspec(allocate("rti_fn$a")) const struct rt_init_desc __rti_fn_begin =
49 {
50 __rti_fn_begin_name,
51 NULL
52 };
53
54 #pragma section("rti_fn$z", read)
55 const char __rti_fn_end_name[] = "__rti_fn_end";
56 __declspec(allocate("rti_fn$z")) const struct rt_init_desc __rti_fn_end =
57 {
58 __rti_fn_end_name,
59 NULL
60 };
61
rti_start(void)62 static int rti_start(void)
63 {
64 return 0;
65 }
66 INIT_EXPORT(rti_start, "0");
67
rti_board_end(void)68 static int rti_board_end(void)
69 {
70 return 0;
71 }
72 INIT_EXPORT(rti_board_end, "1.end");
73
rti_end(void)74 static int rti_end(void)
75 {
76 return 0;
77 }
78 INIT_EXPORT(rti_end, "6.end");
79
80 struct rt_init_tag
81 {
82 const char *level;
83 init_fn_t fn;
84 #ifdef RT_DEBUGING_AUTO_INIT
85 const char *fn_name;
86 #endif
87 };
88
89 static rt_size_t rt_init_num = 0;
90 static struct rt_init_tag rt_init_table[2048] = { 0 };
91 static rt_bool_t rt_init_flag = RT_FALSE;
92
rt_init_objects_sort(void)93 static int rt_init_objects_sort(void)
94 {
95 rt_size_t index_i, index_j;
96 struct rt_init_tag init_temp = { 0 };
97 unsigned int *ptr_begin = (unsigned int *)&__rti_fn_begin;
98 unsigned int *ptr_end = (unsigned int *)&__rti_fn_end;
99 struct rt_init_tag *table = rt_init_table;
100 ptr_begin += (sizeof(struct rt_init_desc) / sizeof(unsigned int));
101
102 if (rt_init_flag)
103 return rt_init_num;
104
105 while (*ptr_begin == 0)
106 ptr_begin++;
107
108 do (ptr_end--);
109 while (*ptr_end == 0);
110
111 while (ptr_begin < ptr_end)
112 {
113 if (*ptr_begin != 0)
114 {
115 table->level = ((struct rt_init_desc *)ptr_begin)->level;
116 table->fn = ((struct rt_init_desc *)ptr_begin)->fn;
117 #ifdef RT_DEBUGING_AUTO_INIT
118 table->fn_name = ((struct rt_init_desc *)ptr_begin)->fn_name;
119 #endif
120 ptr_begin += sizeof(struct rt_init_desc) / sizeof(unsigned int);
121 table++;
122 rt_init_num += 1;
123 }
124 else
125 {
126 ptr_begin++;
127 }
128 }
129
130 if (rt_init_num == 0) /* no need sort */
131 return rt_init_num;
132
133 /* bubble sort algorithms */
134 for (index_i = 0; index_i < (rt_init_num - 1); index_i++)
135 {
136 for (index_j = 0; index_j < ((rt_init_num - 1) - index_i); index_j++)
137 {
138 if (rt_strcmp(rt_init_table[index_j].level, rt_init_table[index_j + 1].level) > 0)
139 {
140 init_temp = rt_init_table[index_j];
141 rt_init_table[index_j] = rt_init_table[index_j + 1];
142 rt_init_table[index_j + 1] = init_temp;
143 }
144 }
145 }
146
147 rt_init_flag = RT_TRUE;
148 return rt_init_num;
149 }
150
151 /**
152 * RT-Thread Components Initialization for board
153 */
rt_components_board_init(void)154 void rt_components_board_init(void)
155 {
156 const char* lv_start = ".rti_fn.0";
157 const char* lv_end = ".rti_fn.1.end";
158 rt_size_t index_i;
159 int result;
160
161 rt_init_objects_sort();
162
163 for (index_i = 0; index_i < rt_init_num; index_i++)
164 {
165 if (rt_init_table[index_i].fn)
166 {
167 if (rt_strcmp(rt_init_table[index_i].level, lv_end) >= 0)
168 {
169 break;
170 }
171 #ifdef RT_DEBUGING_AUTO_INIT
172 rt_kprintf("initialize %s", rt_init_table[index_i].fn_name);
173 result = rt_init_table[index_i].fn();
174 rt_kprintf(":%d done\n", result);
175 #else
176 result = rt_init_table[index_i].fn();
177 #endif /* RT_DEBUGING_AUTO_INIT */
178 }
179 }
180 }
181
182 /**
183 * RT-Thread Components Initialization
184 */
rt_components_init(void)185 void rt_components_init(void)
186 {
187 const char* lv_start = ".rti_fn.1.end";
188 const char* lv_end = ".rti_fn.6.end";
189 int result;
190 rt_size_t index_i;
191
192 rt_init_objects_sort();
193
194 for (index_i = 0; index_i < rt_init_num; index_i++)
195 {
196 if (rt_init_table[index_i].fn)
197 {
198 if (rt_strcmp(rt_init_table[index_i].level, lv_start) <= 0)
199 {
200 continue;
201 }
202 if (rt_strcmp(rt_init_table[index_i].level, lv_end) >= 0)
203 {
204 break;
205 }
206 #ifdef RT_DEBUGING_AUTO_INIT
207 rt_kprintf("initialize %s", rt_init_table[index_i].fn_name);
208 result = rt_init_table[index_i].fn();
209 rt_kprintf(":%d done\n", result);
210 #else
211 result = rt_init_table[index_i].fn();
212 #endif
213 }
214 }
215 }
216 #endif /* RT_USING_COMPONENTS_INIT */
217
218 #ifdef RT_USING_USER_MAIN
219
220 void rt_application_init(void);
221 void rt_hw_board_init(void);
222 int rtthread_startup(void);
223
224 /* system entry */
225 extern int rtthread_startup(void);
wmain(int argc,char * argv[])226 int wmain(int argc, char* argv[])
227 {
228 /* disable interrupt first */
229 rt_hw_interrupt_disable();
230 /* startup RT-Thread RTOS */
231 rtthread_startup();
232 }
233 #pragma comment(linker, "/subsystem:console /entry:wmainCRTStartup")
234
235 #ifndef RT_USING_HEAP
236 /* if there is not enable heap, we should use static thread and stack. */
237 rt_align(8)
238 static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE];
239 struct rt_thread main_thread;
240 #endif
241
242 /* the system main thread */
main_thread_entry(void * parameter)243 void main_thread_entry(void *parameter)
244 {
245 extern int main(void);
246
247 #ifdef RT_USING_COMPONENTS_INIT
248 /* RT-Thread components initialization */
249 rt_components_init();
250 #endif
251
252 #ifdef RT_USING_SMP
253 rt_hw_secondary_cpu_up();
254 #endif
255
256 /* invoke system main function */
257 main();
258 }
259
rt_application_init(void)260 void rt_application_init(void)
261 {
262 rt_thread_t tid;
263
264 #ifdef RT_USING_HEAP
265 tid = rt_thread_create("main", main_thread_entry, RT_NULL,
266 RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
267 RT_ASSERT(tid != RT_NULL);
268 #else
269 rt_err_t result;
270
271 tid = &main_thread;
272 result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
273 main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
274 RT_ASSERT(result == RT_EOK);
275
276 /* if not define RT_USING_HEAP, using to eliminate the warning */
277 (void)result;
278 #endif
279
280 rt_thread_startup(tid);
281 }
282
rtthread_startup(void)283 int rtthread_startup(void)
284 {
285 rt_hw_interrupt_disable();
286
287 /* board level initialization
288 * NOTE: please initialize heap inside board initialization.
289 */
290 rt_hw_board_init();
291
292 /* show RT-Thread version */
293 rt_show_version();
294
295 /* timer system initialization */
296 rt_system_timer_init();
297
298 /* scheduler system initialization */
299 rt_system_scheduler_init();
300
301 #ifdef RT_USING_SIGNALS
302 /* signal system initialization */
303 rt_system_signal_init();
304 #endif
305
306 /* create init_thread */
307 rt_application_init();
308
309 /* timer thread initialization */
310 rt_system_timer_thread_init();
311
312 /* idle thread initialization */
313 rt_thread_idle_init();
314
315 #ifdef RT_USING_SMP
316 rt_hw_spin_lock(&_cpus_lock);
317 #endif /*RT_USING_SMP*/
318
319 /* start scheduler */
320 rt_system_scheduler_start();
321
322 /* never reach here */
323 return 0;
324 }
325 #endif
326