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