STM32 Rtthread启动流程基于GNU交叉编译' a& `6 B' t. |
Rtthread并不是直接从main函数开始启动的,而是从componets.c中通过entry函数启动的:
5 P9 r9 P9 ~( v* W- //需要在board.c中开启这个宏RT_USING_USER_MAIN! i# {: T( M9 R3 B
- * O/ d0 G2 w) d1 ?& c+ t$ e: s/ |
- //我使用的时GNU编译器,所以入口函数在这,可以在ld命令中指定entry为入口地址,
3 q1 K1 o$ [# O5 D - //也可以在startup_stm32f411xe.s中指定入口地址为entry2 T1 G5 R, ?( p/ q7 y1 k
- /* Add -eentry to arm-none-eabi-gcc argument */
' P( ], ^: j# ~ t6 C) h2 t - int entry(void)+ y+ o& g- P5 m! ^- K7 H
- {
# m: O9 ~+ d. D - rtthread_startup();
3 y2 d u) u4 v - return 0;. Q( D) Z7 D6 w. w2 W
- }
3 H3 L7 n( V3 n! K - . q0 j, J1 T- X; h
- int rtthread_startup(void)
# ^/ E/ `+ `+ q: s - {2 w' L" c: ?5 ?" X
- rt_hw_interrupt_disable();( Z9 c3 l9 Y I" B
- ( D5 A. a# S7 m
- /* board level initialization$ Z# h4 V! W1 }2 S& I
- * NOTE: please initialize heap inside board initialization.0 o; H/ o2 w* |7 o8 s
- */
. b1 ? W, ]- O, m+ T4 v! ~: A4 t$ s - rt_hw_board_init();' j% Q/ H, L; f( w0 s: q+ {
- ' g% Z3 J0 {: d* P
- /* show RT-Thread version */! J5 n5 A/ E( M! `6 h7 ~
- rt_show_version();) j& G3 U9 d4 W
6 A E; s s, M& I5 j+ `6 U- /* timer system initialization */
a, E6 j6 P' j0 D4 Y$ T( H) A+ _+ C - rt_system_timer_init();
' J& x- @( {. t2 {; W7 ]2 t+ N - . }* ]) W$ z0 g7 t7 _' d
- /* scheduler system initialization */; T5 c7 {% L. ~5 x, C. w& ^
- rt_system_scheduler_init();* R& j4 c" e3 j. T( z2 u& Q' w% U
! u0 V. B; c3 D5 L- /* create init_thread */9 [8 e7 Q ^# M& w& n Y
- rt_application_init();
" ], F/ l% T% o/ b* H. D; |% U - / ?3 b+ W& q4 g- o9 S. `6 L1 y
- /* timer thread initialization */( U# C% G5 V9 K8 c
- rt_system_timer_thread_init();) y' a: I8 @8 w0 R
- . t5 m- A! b" b
- /* idle thread initialization */& K. t3 o! q2 }; N2 o
- rt_thread_idle_init();# W+ C7 U/ y1 r
; {' q2 g2 f8 D) g+ s: O' `- /* start scheduler */
' H M" k" {# S5 V1 i. v/ y4 n - rt_system_scheduler_start();
$ ~5 s+ w* G5 { - : c# ?& P/ _# E' I! g/ A
- /* never reach here */
' X7 w' ~8 W' C; T" ^ - return 0;. _+ X& e/ Q/ r5 m2 a" n# c' }) f1 V
- }' Z- ^$ u, O" P5 p, s/ c7 P# K* s
- 6 p. F5 C+ V/ U" y5 Y! v* {
- //rt_hw_board_init函数在board.c中定义,主要功能是做硬件初始化7 T) N6 y4 N' \; d5 g
- void rt_hw_board_init()
: Q4 o. r' r! _ - {
' Y8 W4 W( N' n - USART1_Config(115200);//串口初始化2 O& d$ A! O l% M8 @
- KEY_Init();//按键初始化5 P4 R" [. l" {. D$ p
- LED_init();//LED初始化+ I6 I5 {; | \; u* A6 u
- /* System Clock Update */
! D: m, d1 K2 S0 D - //该函数在system_stm32f4xx.c中定义,主要功能是获取SystemCoreClock 的值。% i4 E2 Q4 b3 V3 ?: H! k
- SystemCoreClockUpdate();; \8 y' x' G3 ~- P
- + Q% P/ U3 ^# G9 M2 P$ q: Y% a
- /* System Tick Configuration */
8 |# H) x& X# a& q! A8 T - _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);//RT_TICK_PER_SECOND 1000
$ Z; `& L! i7 y8 R D, f1 I - 9 K! | I( k+ H. ?
- /* Call components board initial (use INIT_BOARD_EXPORT()) */% K- P$ Q0 X! P+ l0 Q. r* R" A
- #ifdef RT_USING_COMPONENTS_INIT- ^& F! m/ z) O5 [1 l
- rt_components_board_init();
5 j' q' A8 ~) u- z - #endif
4 _5 E! e3 c% |
$ O! t" k4 a& Z: E4 D- #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)$ g- `4 |( ~8 i) f: ]$ P
- //rt_console_set_device(RT_CONSOLE_DEVICE_NAME);% H9 h5 K9 d/ Z9 T% m1 S- x
- #endif$ B% O' h' e9 ^- o& U0 E
1 ]- o) R1 f6 }( c0 @. W' Q- #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) //初始化堆
* u$ @, i9 S4 e: q# j - rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());/ f4 g; z( `+ P/ M' `, G! g
- #endif
) O {9 ~1 o5 D/ y1 N) ^. |
( u d- M. ~- }' K3 y- }* ~- q' q+ L# A
- * n/ G$ {" S2 a$ _
- static uint32_t _SysTick_Config(rt_uint32_t ticks)2 A# _, O7 a: \9 B
- {7 s( O% b9 c: d6 `8 C9 @
- if ((ticks - 1) > 0xFFFFFF)
- d$ F& m# y1 R, [2 L/ h0 J7 F - {
4 j% c, a! b* V - return 1;- X R! _# ?" |+ H. N* m0 c- F3 J4 i
- }
' d# l4 U$ n8 f0 z7 E' `( d- p -
}% R- k7 j7 {: I. [3 B( V$ F0 ~8 c - _SYSTICK_LOAD = ticks - 1; //RELOAD VALUE
7 O, `/ r$ ~2 H - _SYSTICK_PRI = 0xFF; //PRIORITY OF SYSTICK LOW/ Y* y" i1 n( U
- _SYSTICK_VAL = 0; //CLEAR CURRENT VALUE OF SYSTICK COUNT2 ^, G5 b! L+ P# g- K
- //systick ctrl寄存器bit2 为1时使用AHB作为systic频率,不分频2 X# J* e6 Z* w
- _SYSTICK_CTRL = 0x07; //0x07 BIT2 ==1 使用AHB,0:使用内部时钟源,AHB/8& Z" t6 Y6 N- W" n2 h
- 4 d, o# s I0 W* X5 _/ A* M
- return 0;) Y1 a+ P' O) x0 b6 M
- }: u4 C2 g2 X7 \5 w ~+ {0 h7 m z4 p. }
- //rt_components_board_init函数会初始化INIT_EXPORT(fn, level) 宏包起来的函数. N( m0 E/ W. x' Z$ l8 |6 u
- //可以看看这篇文章:https://blog.csdn.net/qq_42370291/article/details/103639349& [- a o$ @- r
- void rt_components_board_init(void)$ K0 j: ~5 F" k8 J3 @# s5 k
- {2 I0 ?6 L8 e9 Z' K2 @3 e7 `
- #if RT_DEBUG_INIT //开了RT_DEBUG_INIT 将会打印出被调用的初始化的函数
/ J: ?4 Y+ o) a8 e - int result;
3 m9 G, B/ M+ _1 E& R - const struct rt_init_desc *desc;3 z' C6 [( @5 ~1 Q$ F
- for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
0 B7 ?, a, T# o# ]+ F5 [- ?) ] - {
5 T8 R" [* Q& k# R# m - rt_kprintf("initialize %s", desc->fn_name);7 {: `/ _% K6 J$ F8 o9 j
- result = desc->fn();
5 g$ S# i& @* S8 ^, o - rt_kprintf(":%d done\n", result);
+ {5 c" w0 s5 b, ?$ W+ D - }
9 C1 B7 k& H0 u2 d( v: i - #else
/ r) ?% W+ A& l8 a# Z4 M - volatile const init_fn_t *fn_ptr;
, C" I( T% m& X/ r a - ; L3 j8 \) E6 M0 `9 m) y. n
- for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)4 v! H) I% @: `, g
- {
. r; h% W& g) b* X0 I: ]) { - (*fn_ptr)();1 T' R6 }3 o# p/ r: ?
- }
. m1 B- P# ^: M - #endif
# r0 y3 V- d p* w/ [9 g - }
: Y& m5 q+ O0 v& e! g. ^7 e- @! F
复制代码
3 m1 p. L/ W& w在startup_stm32f411xe.s中指定入口地址为entry
1 m: M( Z, n& d, A- /* Call the application's entry point.*/
3 K9 w( k) C$ w3 i% Z2 Y/ e - bl entry //这里之前是main/ z8 r" o2 a- o- ]0 D; Q
- bx lr
复制代码 ————————————————9 E, {( z: t; c3 ?9 [( }" x7 o
版权声明:tony++$ t& t6 N* q+ J2 i, \' _. Q
1 ~# @1 n' D4 C; a$ ?, s
|