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