1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2012-09-20     Bernard      Change the name to components.c
9  *                             And all components related header files.
10  * 2012-12-23     Bernard      fix the pthread initialization issue.
11  * 2013-06-23     Bernard      Add the init_call for components initialization.
12  * 2013-07-05     Bernard      Remove initialization feature for MS VC++ compiler
13  * 2015-02-06     Bernard      Remove the MS VC++ support and move to the kernel
14  * 2015-05-04     Bernard      Rename it to components.c because compiling issue
15  *                             in some IDEs.
16  * 2015-07-29     Arda.Fu      Add support to use RT_USING_USER_MAIN with IAR
17  * 2018-11-22     Jesven       Add secondary cpu boot up
18  * 2023-09-15     xqyjlj       perf rt_hw_interrupt_disable/enable
19  */
20 
21 #include <rthw.h>
22 #include <rtthread.h>
23 
24 #ifdef RT_USING_USER_MAIN
25 #ifndef RT_MAIN_THREAD_STACK_SIZE
26 #define RT_MAIN_THREAD_STACK_SIZE     2048
27 #endif /* RT_MAIN_THREAD_STACK_SIZE */
28 #ifndef RT_MAIN_THREAD_PRIORITY
29 #define RT_MAIN_THREAD_PRIORITY       (RT_THREAD_PRIORITY_MAX / 3)
30 #endif /* RT_MAIN_THREAD_PRIORITY */
31 #endif /* RT_USING_USER_MAIN */
32 
33 #ifdef RT_USING_COMPONENTS_INIT
34 /*
35  * Components Initialization will initialize some driver and components as following
36  * order:
37  * rti_start         --> 0
38  * BOARD_EXPORT      --> 1
39  * rti_board_end     --> 1.end
40  *
41  * DEVICE_EXPORT     --> 2
42  * COMPONENT_EXPORT  --> 3
43  * FS_EXPORT         --> 4
44  * ENV_EXPORT        --> 5
45  * APP_EXPORT        --> 6
46  *
47  * rti_end           --> 6.end
48  *
49  * These automatically initialization, the driver or component initial function must
50  * be defined with:
51  * INIT_BOARD_EXPORT(fn);
52  * INIT_DEVICE_EXPORT(fn);
53  * ...
54  * INIT_APP_EXPORT(fn);
55  * etc.
56  */
rti_start(void)57 static int rti_start(void)
58 {
59     return 0;
60 }
61 INIT_EXPORT(rti_start, "0");
62 
rti_board_start(void)63 static int rti_board_start(void)
64 {
65     return 0;
66 }
67 INIT_EXPORT(rti_board_start, "0.end");
68 
rti_board_end(void)69 static int rti_board_end(void)
70 {
71     return 0;
72 }
73 INIT_EXPORT(rti_board_end, "1.end");
74 
rti_end(void)75 static int rti_end(void)
76 {
77     return 0;
78 }
79 INIT_EXPORT(rti_end, "6.end");
80 
81 /**
82  * @brief  Onboard components initialization. In this function, the board-level
83  *         initialization function will be called to complete the initialization
84  *         of the on-board peripherals.
85  */
rt_components_board_init(void)86 void rt_components_board_init(void)
87 {
88 #ifdef RT_DEBUGING_AUTO_INIT
89     int result;
90     const struct rt_init_desc *desc;
91     for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
92     {
93         rt_kprintf("initialize %s\n", desc->fn_name);
94         result = desc->fn();
95         rt_kprintf(":%d done\n", result);
96     }
97 #else
98     volatile const init_fn_t *fn_ptr;
99 
100     for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
101     {
102         (*fn_ptr)();
103     }
104 #endif /* RT_DEBUGING_AUTO_INIT */
105 }
106 
107 /**
108  * @brief  RT-Thread Components Initialization.
109  */
rt_components_init(void)110 void rt_components_init(void)
111 {
112 #ifdef RT_DEBUGING_AUTO_INIT
113     int result;
114     const struct rt_init_desc *desc;
115 
116     rt_kprintf("do components initialization.\n");
117     for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
118     {
119         rt_kprintf("initialize %s\n", desc->fn_name);
120         result = desc->fn();
121         rt_kprintf(":%d done\n", result);
122     }
123 #else
124     volatile const init_fn_t *fn_ptr;
125 
126     for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
127     {
128         (*fn_ptr)();
129     }
130 #endif /* RT_DEBUGING_AUTO_INIT */
131 }
132 #endif /* RT_USING_COMPONENTS_INIT */
133 
134 #ifdef RT_USING_USER_MAIN
135 
136 void rt_application_init(void);
137 void rt_hw_board_init(void);
138 int rtthread_startup(void);
139 
140 #ifdef __ARMCC_VERSION
141 extern int $Super$$main(void);
142 /* re-define main function */
$Sub$$main(void)143 int $Sub$$main(void)
144 {
145     rtthread_startup();
146     return 0;
147 }
148 #elif defined(__ICCARM__)
149 /* __low_level_init will auto called by IAR cstartup */
150 extern void __iar_data_init3(void);
__low_level_init(void)151 int __low_level_init(void)
152 {
153     // call IAR table copy function.
154     __iar_data_init3();
155     rtthread_startup();
156     return 0;
157 }
158 #elif defined(__GNUC__)
159 /* Add -eentry to arm-none-eabi-gcc argument */
entry(void)160 int entry(void)
161 {
162     rtthread_startup();
163     return 0;
164 }
165 #endif
166 
167 #ifndef RT_USING_HEAP
168 /* if there is not enable heap, we should use static thread and stack. */
169 rt_align(RT_ALIGN_SIZE)
170 static rt_uint8_t main_thread_stack[RT_MAIN_THREAD_STACK_SIZE];
171 struct rt_thread main_thread;
172 #endif /* RT_USING_HEAP */
173 
174 /**
175  * @brief  The system main thread. In this thread will call the rt_components_init()
176  *         for initialization of RT-Thread Components and call the user's programming
177  *         entry main().
178  *
179  * @param  parameter is the arg of the thread.
180  */
main_thread_entry(void * parameter)181 static void main_thread_entry(void *parameter)
182 {
183     extern int main(void);
184     RT_UNUSED(parameter);
185 
186 #ifdef RT_USING_COMPONENTS_INIT
187     /* RT-Thread components initialization */
188     rt_components_init();
189 #endif /* RT_USING_COMPONENTS_INIT */
190 
191 #ifdef RT_USING_SMP
192     rt_hw_secondary_cpu_up();
193 #endif /* RT_USING_SMP */
194     /* invoke system main function */
195 #ifdef __ARMCC_VERSION
196     {
197         extern int $Super$$main(void);
198         $Super$$main(); /* for ARMCC. */
199     }
200 #elif defined(__ICCARM__) || defined(__GNUC__) || defined(__TASKING__) || defined(__TI_COMPILER_VERSION__)
201     main();
202 #endif /* __ARMCC_VERSION */
203 }
204 
205 /**
206  * @brief  This function will create and start the main thread, but this thread
207  *         will not run until the scheduler starts.
208  */
rt_application_init(void)209 void rt_application_init(void)
210 {
211     rt_thread_t tid;
212 
213 #ifdef RT_USING_HEAP
214     tid = rt_thread_create("main", main_thread_entry, RT_NULL,
215                            RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
216     RT_ASSERT(tid != RT_NULL);
217 #else
218     rt_err_t result;
219 
220     tid = &main_thread;
221     result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
222                             main_thread_stack, sizeof(main_thread_stack), RT_MAIN_THREAD_PRIORITY, 20);
223     RT_ASSERT(result == RT_EOK);
224 
225     /* if not define RT_USING_HEAP, using to eliminate the warning */
226     (void)result;
227 #endif /* RT_USING_HEAP */
228 
229     rt_thread_startup(tid);
230 }
231 
232 /**
233  * @brief  This function will call all levels of initialization functions to complete
234  *         the initialization of the system, and finally start the scheduler.
235  *
236  * @return Normally never returns. If 0 is returned, the scheduler failed.
237  */
rtthread_startup(void)238 int rtthread_startup(void)
239 {
240 #ifdef RT_USING_SMP
241     rt_hw_spin_lock_init(&_cpus_lock);
242 #endif
243     rt_hw_local_irq_disable();
244 
245     /* board level initialization
246      * NOTE: please initialize heap inside board initialization.
247      */
248     rt_hw_board_init();
249 
250     /* show RT-Thread version */
251     rt_show_version();
252 
253     /* timer system initialization */
254     rt_system_timer_init();
255 
256     /* scheduler system initialization */
257     rt_system_scheduler_init();
258 
259 #ifdef RT_USING_SIGNALS
260     /* signal system initialization */
261     rt_system_signal_init();
262 #endif /* RT_USING_SIGNALS */
263 
264     /* create init_thread */
265     rt_application_init();
266 
267     /* timer thread initialization */
268     rt_system_timer_thread_init();
269 
270     /* idle thread initialization */
271     rt_thread_idle_init();
272 
273     /* defunct thread initialization */
274     rt_thread_defunct_init();
275 
276 #ifdef RT_USING_SMP
277     rt_hw_spin_lock(&_cpus_lock);
278 #endif /* RT_USING_SMP */
279 
280     /* start scheduler */
281     rt_system_scheduler_start();
282 
283     /* never reach here */
284     return 0;
285 }
286 #endif /* RT_USING_USER_MAIN */
287