你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32启动过程--启动文件--分析

[复制链接]
STMCU小助手 发布时间:2022-1-13 21:00
一、概述
1、说明
  每一款芯片的启动文件都值得去研究,因为它可是你的程序跑的最初一段路,不可以不知道。通过了解启动文件,我们可以体会到处理器的架构、指令集、中断向量安排等内容,是非常值得玩味的。
  STM32作为一款高端Cortex-M3系列单片机,有必要了解它的启动文件。打好基础,为以后优化程序,写出高质量的代码最准备。
  本文以一个实际测试代码--START_TEST为例进行阐述。
2、整体过程概括
  STM整个启动过程是指从上电开始,一直到运行到main函数之间的这段过程,步骤为(以使用微库为例):
①上电后硬件设置SP、PC
②设置系统时钟
③软件设置SP
④加载.data、.bss,并初始化栈区
⑤跳转到C文件的main函数
3、整个启动过程涉及的代码
  启动过程涉及的文件不仅包含startup_stm32f10x_hd.s,还涉及到了MDK自带的连接库文件entry.o、entry2.o、entry5.o、entry7.o等(从生成的map文件可以看出来)。
二、程序在Flash上的存储结构
  在真正讲解启动过程之前,先要讲解程序下载到Flash上的结构和程序运行时(执行到main函数)时的SRAM数据结构。程序在用户Flash上的结构如下图所示。下图是通过阅读hex文件和在MDK下调试综合提炼出来的。

2 E" s/ r# m; V; }6 p/ c2 J
092018031206060.png

' R4 t. ^, P  E) }
MSP初始值        编译器生成,主堆栈的初始值
异常向量表        不多说
外部中断向量表      不多说
代码段          存放代码
初始化数据段       .data
未初始化数据段      .bss
加载数据段和初始化栈的参数
  加载数据段和初始化栈的参数分别有4个,这里只讲解加载数据段的参数,至于初始化栈的参数类似。
0x0800 033c  Flash上的数据段(初始化数据段和未初始化数据段)起始地址
0x2000 0000  加载到SRAM上的目的地址
0x0000 000c  数据段的总大小
0x0800 02f4  调用函数_scatterload_copy
  需要说明的是初始化栈的函数--0x0800 0304与加载数据段的函数不一样,为_scatterload_zeroinit,它的目的就是将栈空间清零。

, r8 o$ x1 V% \: y7 z6 W. T2 C8 u
092032461983346.png
9 T  ^$ e5 ]& a9 Z
三、数据在SRAM上的结构
  程序运行时(执行到main函数)时的SRAM数据结构
+ {1 M; T" A2 u  E% J$ `; `
092025271358977.png
8 m' B: s* k8 l; W* i: r8 y7 Y& \0 ?
四、详细过程分析
  有了以上的基础,现在详细分析启动过程。
1、上电后硬件设置SP、PC
  刚上电复位后,硬件会自动根据向量表偏移地址找到向量表,向量表偏移地址的定义如下:

: ?1 o  p- F4 G" H+ E
092045343233846.png
# J7 i. s- Z9 t; A
  调试现象如下:

4 Q, C" O; V3 |- r, T
092046570579821.png

; ]' ~0 Q1 t2 S8 K
  看看我们的向量表内容(通过J-Flash打开hex文件)

: M  Q  Z  O& k# ]. F3 V1 x
092048562138825.png

) ~9 O  u  A6 t
  硬件这时自动从0x0800 0000位置处读取数据赋给栈指针SP,然后自动从0x0800 0004位置处读取数据赋给PC,完成复位,结果为:
SP = 0x0200 0810
PC = 0x0800 0145
2、设置系统时钟
# g- l$ A1 h" V3 \9 w+ a
092052446511680.png

4 R  d% u8 x( M2 g+ A7 u
  上一步中令PC=0x0800 0145的地址没有对齐,硬件自动对齐到0x0800 0144,执行SystemInit函数初始化系统时钟。
3、软件设置SP
  1. LDR   R0,=__main  
    $ n7 r2 b; [- j; j% ^9 R
  2. BX   R0
复制代码

1 J' E  N+ ]9 T
  执行上两条之类,跳转到__main程序段运行,注意不是main函数,___main的地址是0x0800 0130。
" o8 r* [, R: l- P- F- ?
092100522921657.png
0 I$ j5 Z, m3 v
  可以看到指令LDR.W sp,[pc,#12],结果SP=0x2000 0810。
4、加载.data、.bss,并初始化栈区
  1. BL.W     __scatterload_rt2
复制代码
  进入 __scatterload_rt2代码段。
  1. __scatterload_rt2:
    ! R: ?/ _6 \6 D" [/ p, C" Y4 q! m# ]0 c1 Y
  2. 0x08000168 4C06      LDR      r4,[pc,#24]  ; @0x08000184
    ; C% ^+ {0 N. v3 E- N
  3. 0x0800016A 4D07      LDR      r5,[pc,#28]  ; @0x08000188; S9 s: ?2 A$ D
  4. 0x0800016C E006      B        0x0800017C
    0 Q: }; J" R5 k! N0 N( Z0 {1 n- V
  5. 0x0800016E 68E0      LDR      r0,[r4,#0x0C]
    ' i8 k3 b6 c% f8 D2 z  ~$ i
  6. 0x08000170 F0400301  ORR      r3,r0,#0x017 U' p$ O' y: U2 u) z9 q( w
  7. 0x08000174 E8940007  LDM      r4,{r0-r2}, h% o& {5 J4 ]( j& [
  8. 0x08000178 4798      BLX      r30 h3 r  O, v) R2 l: R
  9. 0x0800017A 3410      ADDS     r4,r4,#0x10
    6 a" K3 c; x9 A  ?1 p
  10. 0x0800017C 42AC      CMP      r4,r5
    0 `6 t5 H7 Q! [! c% Q4 i5 l
  11. 0x0800017E D3F6      BCC      0x0800016E" c' D/ ?! N8 w7 P
  12. 0x08000180 F7FFFFDA  BL.W     _main_init (0x08000138)
复制代码
* ?) O  b, I, N( t- g* B
  这段代码是个循环(BCC 0x0800016e),实际运行时候循环了两次。第一次运行的时候,读取“加载数据段的函数(_scatterload_copy)”的地址并跳转到该函数处运行(注意加载已初始化数据段和未初始化数据段用的是同一个函数);第二次运行的时候,读取“初始化栈的函数(_scatterload_zeroinit)”的地址并跳转到该函数处运行。 相应的代码如下:
0x0800016E 68E0      LDR      r0,[r4,#0x0C]0x08000170 F0400301  ORR      r3,r0,#0x010x08000174  6 N/ k* K1 ^. S, E
0x08000178 4798      BLX      r38 z: I! F5 t5 |) t  }
  
  T8 q  p6 O# k! N  当然执行这两个函数的时候,还需要传入参数。至于参数,我们在“加载数据段和初始化栈的参数”环节已经阐述过了。当这两个函数都执行完后,结果就是“数据在SRAM上的结构”所展示的图。最后,也把事实加载和初始化的两个函数代码奉上如下:6 q9 A* V# K' \0 Y
  1. 0x0800016E 68E0      LDR      r0,[r4,#0x0C]! U8 M: [/ ?* l" s& ^' X! E
  2. 0x08000170 F0400301  ORR      r3,r0,#0x01
    ' A0 j/ @3 r2 p& D
  3. 0x08000174  
    ' B- O* b8 o( u
  4. 0x08000178 4798      BLX      r3
复制代码
当然执行这两个函数的时候,还需要传入参数。至于参数,我们在“加载数据段和初始化栈的参数”环节已经阐述过了。当这两个函数都执行完后,结果就是“数据在SRAM上的结构”所展示的图。最后,也把事实加载和初始化的两个函数代码奉上如下:
  1.                  __scatterload_copy:  o( q, M3 Q9 `9 x7 l; x# i* ~
  2. 0x080002F4 E002      B        0x080002FC
    . h9 L3 l2 j5 S5 h
  3. 0x080002F6 C808      LDM      r0!,{r3}
    6 @8 w& a/ V+ j+ a: M
  4. 0x080002F8 1F12      SUBS     r2,r2,#4. e+ s" l4 S) W/ |
  5. 0x080002FA C108      STM      r1!,{r3}
    2 x. h% j5 k1 C  L: b  A0 ]
  6. 0x080002FC 2A00      CMP      r2,#0x001 E- @5 ~) R8 a( g+ ]) R
  7. 0x080002FE D1FA      BNE      0x080002F6  p' u; g9 ]' l3 a7 y8 c& v
  8. 0x08000300 4770      BX       lr6 v/ \2 }# `7 f/ P' W/ q- ~# K( q
  9.                  __scatterload_null:! Q; R( n( O: a
  10. 0x08000302 4770      BX       lr
    - Y0 p. L; I* c) M5 ]/ }3 R
  11.                  __scatterload_zeroinit:
    ) X1 S" ?; s$ l9 I4 a7 F; j
  12. 0x08000304 2000      MOVS     r0,#0x002 R6 b! X+ j+ [2 n' V
  13. 0x08000306 E001      B        0x0800030C; f' Z9 n' }8 I3 s; B7 Q- d
  14. 0x08000308 C101      STM      r1!,{r0}1 o% h( q* y9 X2 R* D, k
  15. 0x0800030A 1F12      SUBS     r2,r2,#4
      E* I  h8 X/ [
  16. 0x0800030C 2A00      CMP      r2,#0x00
    ; u9 s9 a7 I( r( H7 h: p0 {8 a9 H
  17. 0x0800030E D1FB      BNE      0x08000308$ R! b$ x* M1 T. R# v( J  k
  18. 0x08000310 4770      BX       lr
复制代码
% |1 I) W0 Q2 m
5、跳转到C文件的main函数
  1.                  _main_init:$ W3 |# q) k! q& B- Q
  2. 0x08000138 4800      LDR      r0,[pc,#0]  ; @0x0800013C1 E# u6 [: k  c7 |) Q! I
  3. 0x0800013A 4700      BX       r0
复制代码
; R6 Y# h) }& s) }, a( H
# Q7 p% j8 `4 S& {5 }$ R
五、异常向量与中断向量表
  1. ; Vector Table Mapped to Address 0 at Reset. K9 u; O! F" w; r
  2.                 AREA    RESET, DATA, READONLY
    7 N- K# O  A( h4 g4 \: f
  3.                 EXPORT  __Vectors; V9 h' n. _/ ~2 l* h7 C
  4.                 EXPORT  __Vectors_End6 E7 s5 X1 C* `4 t
  5.                 EXPORT  __Vectors_Size
    1 U0 j! a2 r9 m+ K. Z8 U. D, S: T
  6. + V. Y3 c. N4 s' `/ m: ]
  7. __Vectors       DCD     __initial_sp               ; Top of Stack$ }; r; P# \% `% O/ a$ L9 R
  8.                 DCD     Reset_Handler              ; Reset Handler
    . u( Z' X% o2 G6 S* W# n
  9.                 DCD     NMI_Handler                ; NMI Handler
      q9 W4 E2 S, K6 |: N3 [
  10.                 DCD     HardFault_Handler          ; Hard Fault Handler/ O2 [# c: B- W; `7 n+ `: _& Z' F2 z
  11.                 DCD     MemManage_Handler          ; MPU Fault Handler: ?" v$ O$ g* v
  12.                 DCD     BusFault_Handler           ; Bus Fault Handler
    $ o, V# b" ?/ S# Y, n* M: O: h
  13.                 DCD     UsageFault_Handler         ; Usage Fault Handler1 s7 H8 w9 j1 s0 A$ ]8 T* q
  14.                 DCD     0                          ; Reserved
    0 x! [/ @9 W, s3 g7 X# Z
  15.                 DCD     0                          ; Reserved4 O7 Z: k% d. d. I- g# I
  16.                 DCD     0                          ; Reserved
    0 C, {8 m+ Q) a& m9 k3 g7 D, j# \
  17.                 DCD     0                          ; Reserved# W) f9 @% L; P) T5 K- U% w; l3 b
  18.                 DCD     SVC_Handler                ; SVCall Handler7 e$ N+ n; p1 S2 Y$ B
  19.                 DCD     DebugMon_Handler           ; Debug Monitor Handler
    6 I5 m9 f' F% Y9 b. E& _$ W
  20.                 DCD     0                          ; Reserved3 k1 P. J3 \  x. A
  21.                 DCD     PendSV_Handler             ; PendSV Handler
    6 H) n: R$ B) X; R' ~& w
  22.                 DCD     SysTick_Handler            ; SysTick Handler* M/ s" j$ w+ A! w3 \0 Z# Y
  23. " e" s* @. h2 q
  24.                 ; External Interrupts
    7 Y- I8 ^, W& H5 |4 _8 H* H8 _2 X
  25.                 DCD     WWDG_IRQHandler            ; Window Watchdog8 @; l: M1 _& S4 h
  26.                 DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
    ( n: d) o+ J7 [8 h$ z( d; f
  27.                 DCD     TAMPER_IRQHandler          ; Tamper9 F8 i4 N% J; x$ @$ j
  28.                 DCD     RTC_IRQHandler             ; RTC& P2 p& E" M+ ?
  29.                 DCD     FLASH_IRQHandler           ; Flash
    ; }$ S5 v' I# h5 R+ h! s
  30.                 DCD     RCC_IRQHandler             ; RCC' V' r! `7 g9 P0 N
  31.                 DCD     EXTI0_IRQHandler           ; EXTI Line 0
    0 i7 ?2 k" A- G( \2 r! U
  32.                 DCD     EXTI1_IRQHandler           ; EXTI Line 1
    ' t! q. c' |3 [5 z& m
  33.                 DCD     EXTI2_IRQHandler           ; EXTI Line 2; M: @# P# }5 E; Q; D$ x: n6 Y
  34.                 DCD     EXTI3_IRQHandler           ; EXTI Line 3
    8 Q# H: r2 T2 K# Y9 o; X. _
  35.                 DCD     EXTI4_IRQHandler           ; EXTI Line 4$ X% E0 ~% ~, E; G5 d
  36.                 DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
    9 |2 c* n; p# _# A. n% t- h
  37.                 DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2' [5 y+ \5 ~3 A- j6 J
  38.                 DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3. x; B( J8 K7 v; G" c7 T7 d
  39.                 DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
    # W* N7 G% w2 l3 l8 y
  40.                 DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
    " L* h" P$ ], t# n* c9 k  T, k
  41.                 DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 65 s8 D! k( W1 a% M+ D) h8 t# S6 @# |0 ?
  42.                 DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
    " D+ _6 Y$ S" j6 Q; F
  43.                 DCD     ADC1_2_IRQHandler          ; ADC1 & ADC2  x* u% h8 s. F
  44.                 DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX. t" c; ^- r$ x2 X8 B, h
  45.                 DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
    / g2 L4 y9 y! H! t
  46.                 DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1. f2 L- E8 ~& C8 ]
  47.                 DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE2 m2 k7 N8 N2 Y( ?* D0 n% m& ]4 I
  48.                 DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..56 _1 D1 [( k( B2 i) o
  49.                 DCD     TIM1_BRK_IRQHandler        ; TIM1 Break3 q4 Q" M! Z0 \. [( y' [
  50.                 DCD     TIM1_UP_IRQHandler         ; TIM1 Update; [% H$ E( C6 p2 ~& _
  51.                 DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation7 M: w: @: @) l& g
  52.                 DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare, x* Y0 r* x" A$ {; |
  53.                 DCD     TIM2_IRQHandler            ; TIM2
    0 t% A& r# @4 {& t0 x
  54.                 DCD     TIM3_IRQHandler            ; TIM3
    ( i% O  ^  Y: f7 q
  55.                 DCD     TIM4_IRQHandler            ; TIM4, n, c+ r2 s/ r: A7 X- f
  56.                 DCD     I2C1_EV_IRQHandler         ; I2C1 Event5 ^' _% {$ Z. p. m2 Q  W9 [8 D  D. U
  57.                 DCD     I2C1_ER_IRQHandler         ; I2C1 Error; i  o' W5 L. F$ Q; s* @
  58.                 DCD     I2C2_EV_IRQHandler         ; I2C2 Event
    3 u# ~/ q9 b/ Z6 j9 O* v
  59.                 DCD     I2C2_ER_IRQHandler         ; I2C2 Error
    4 y( L! u$ P( n6 x
  60.                 DCD     SPI1_IRQHandler            ; SPI1- J6 ?4 y3 Z9 U" w
  61.                 DCD     SPI2_IRQHandler            ; SPI2
    ; h5 _5 M9 |+ M2 i$ r
  62.                 DCD     USART1_IRQHandler          ; USART1
    ! g  P4 c0 d% G& d3 Q
  63.                 DCD     USART2_IRQHandler          ; USART2, Z( J& D/ F$ K4 o% r  v
  64.                 DCD     USART3_IRQHandler          ; USART3
    2 l7 D- a  {7 _/ O" X( V' T  u
  65.                 DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..109 s& `6 c/ f0 I) I& b
  66.                 DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
    ' L5 ?8 b7 J  b
  67.                 DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend4 D: f) q) r3 E- @. O5 l  ?6 g8 `
  68.                 DCD     TIM8_BRK_IRQHandler        ; TIM8 Break
    ) h- G; Y/ r* i/ |- ^
  69.                 DCD     TIM8_UP_IRQHandler         ; TIM8 Update. T$ n3 ^2 n, _8 R
  70.                 DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation
    ; S' P+ @: d! F8 A. q
  71.                 DCD     TIM8_CC_IRQHandler         ; TIM8 Capture Compare
    " k6 X+ d7 L. c7 z9 g2 V- C  T# h# {
  72.                 DCD     ADC3_IRQHandler            ; ADC3
    : t4 d7 J/ F5 o, L
  73.                 DCD     FSMC_IRQHandler            ; FSMC
    6 l, ?# A# K8 ^* e
  74.                 DCD     SDIO_IRQHandler            ; SDIO
    ' E$ Q9 E: y% s% V
  75.                 DCD     TIM5_IRQHandler            ; TIM5- g- \1 T: m% Q6 B
  76.                 DCD     SPI3_IRQHandler            ; SPI3
    7 Z+ }+ h) \5 _# t! L0 X* i1 ~
  77.                 DCD     UART4_IRQHandler           ; UART4% {7 S2 ~. L) j  \6 t+ q
  78.                 DCD     UART5_IRQHandler           ; UART5
    * `, N9 c% b, Z( ]& V+ H0 u8 }
  79.                 DCD     TIM6_IRQHandler            ; TIM6
      n$ G( g" X* t- v  S/ r* W
  80.                 DCD     TIM7_IRQHandler            ; TIM7
    # t4 i( V7 o) n
  81.                 DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1/ v3 x- f9 a, s/ C* L) B* d$ {# C
  82.                 DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel23 t" m4 A* h/ M0 j# o2 k" t
  83.                 DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel38 X( R/ l8 V- p2 @
  84.                 DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
    - [- }2 W  h7 l
  85. __Vectors_End
复制代码

1 S  y( W" }  p* Z+ C
  这段代码就是定义异常向量表,在之前有一个“J-Flash打开hex文件”的图片跟这个表格是一一对应的。编译器根据我们定义的函数 Reset_Handler、NMI_Handler等,在连接程序阶段将这个向量表填入这些函数的地址。
  1. startup_stm32f10x_hd.s内容:7 V! @( P8 d3 O0 x
  2. - W8 P, M2 F' t# W3 H
  3. NMI_Handler     PROC# e, z8 r6 }5 @
  4.                 EXPORT  NMI_Handler                [WEAK]
    9 |. ~) a) A: U) p" B4 U% ~
  5.                 B       .
    ( S# {8 B$ A; e' t# Z6 V
  6.                 ENDP
    * @, w# R* T2 {
  7. 4 e# I/ ?( C" z* e8 M

  8. 8 l# E  [7 r0 S  H( D2 v
  9. stm32f10x_it.c中内容:9 r4 M. b+ \+ A# b
  10. void NMI_Handler(void)
    ! b1 A& f) E( O( |3 a* Z
  11. {
    1 H, W, p' q; n) i  A3 @
  12. }
复制代码
9 ]: `" ^) E  v+ D# r
  在启动汇编文件中已经定义了函数NMI_Handler,但是使用了“弱”,它允许我们再重新定义一个NMI_Handler函数,程序在编译的时候会将汇编文件中的弱函数“覆盖掉”--两个函数的代码在连接后都存在,只是在中断向量表中的地址填入的是我们重新定义函数的地址。
六、使用微库与不使用微库的区别
092134086673127.png
/ x. y" K4 v- a7 u
  使用微库就意味着我们不想使用MDK提供的库函数,而想用自己定义的库函数,比如说printf函数。那么这一点是怎样实现的呢?我们以printf函数为例进行说明。
1、不使用微库而使用系统库
  在连接程序时,肯定会把系统中包含printf函数的库拿来调用参与连接,即代码段有系统库的参与。
  在启动过程中,不使用微库而使用系统库在初始化栈的时候,还需要初始化堆(猜测系统库需要用到堆),而使用微库则是不需要的。
  1.                  IF      :DEF:__MICROLIB% H% _( n4 {# f  U# o& A
  2.                
    4 S/ Q4 a, n9 t' u! u9 y9 f
  3.                  EXPORT  __initial_sp( _$ G# ^/ F; w' V6 z% @; K0 J  F
  4.                  EXPORT  __heap_base
    3 e  T  \" B& f
  5.                  EXPORT  __heap_limit* E3 s! A* A2 \7 ?  n4 Q
  6.                
    , N6 {) t( ]1 g, _' A0 ]
  7.                  ELSE1 e3 D3 Y# q5 Z- P5 l
  8.                
    & p! w" B! l6 b' G* t& i
  9.                  IMPORT  __use_two_region_memory7 i) x9 \1 T6 p. ?$ \4 D% n4 h6 Y! y- C
  10.                  EXPORT  __user_initial_stackheap
    ) Z9 ^" ]& x9 g# X8 b
  11.                  9 i/ h6 _4 R' j
  12. __user_initial_stackheap0 B) b3 G, q! _) ~3 D0 ?2 I7 E
  13. 4 z/ y- N! B9 m5 c
  14.                  LDR     R0, =  Heap_Mem
    ; n# I2 s- b4 j1 s4 t( |" d
  15.                  LDR     R1, =(Stack_Mem + Stack_Size)* i# ^" h$ X  O/ h6 b7 \3 l
  16.                  LDR     R2, = (Heap_Mem +  Heap_Size); R2 |5 i$ `0 }! S* E5 E9 I; p- X
  17.                  LDR     R3, = Stack_Mem
    " W2 d) N9 D. l  M
  18.                  BX      LR, }# }& c4 _2 M
  19. 6 a, [  r4 `3 }; {
  20.                  ALIGN5 ?- Z/ ~; P# C) k# |' ^
  21. ' G7 F/ a0 z* O/ i0 k
  22.                  ENDIF
复制代码
# u7 H" a3 f( E4 a% S
  另外,在执行__main函数的过程中,不仅需要完成“使用微库”情况下的所有工作,额外的工作还需要进行库的初始化,才能使用系统库(这一部分我还没有深入探讨)。附上__main函数的内容:
  1.                   __main:; y: n& |& p! b0 x/ {
  2. 0x08000130 F000F802  BL.W     __scatterload_rt2_thumb_only (0x08000138)0 d$ o. n2 h; V8 E- h5 W
  3. 0x08000134 F000F83C  BL.W     __rt_entry_sh (0x080001B0)- F$ ~+ i/ q- H& K/ ]/ }
  4.                  __scatterload_rt2_thumb_only:6 n0 i; L0 \; m7 y4 ^: n
  5. 0x08000138 A00A      ADR      r0,{pc}+4  ; @0x08000164& o4 X9 {" m# c: N3 K
  6. 0x0800013A E8900C00  LDM      r0,{r10-r11}
    . f$ O3 C% K7 c7 T- P7 P7 P
  7. 0x0800013E 4482      ADD      r10,r10,r0
    - m3 x6 E" h0 `; }
  8. 0x08000140 4483      ADD      r11,r11,r04 L1 ]' [; u8 _3 T
  9. 0x08000142 F1AA0701  SUB      r7,r10,#0x01% K$ n: M0 t) G. V8 ^/ O
  10.                  __scatterload_null:
    ) Y9 f6 q$ c8 ?2 k' V* ^
  11. 0x08000146 45DA      CMP      r10,r11  t: r2 ~8 Q4 L* {& w
  12. 0x08000148 D101      BNE      0x0800014E: q! E6 V- |) C9 p8 D: e
  13. 0x0800014A F000F831  BL.W     __rt_entry_sh (0x080001B0)2 A7 u# s6 T: W* Y4 t
  14. 0x0800014E F2AF0E09  ADR.W    lr,{pc}-0x07  ; @0x080001472 g& b1 B+ t$ c- ?0 [
  15. 0x08000152 E8BA000F  LDM      r10!,{r0-r3}/ h1 [( S; X1 \1 O6 h5 }# \
  16. 0x08000156 F0130F01  TST      r3,#0x011 V1 H1 Z' V- L  N8 S
  17. 0x0800015A BF18      IT       NE
    0 m/ M2 M( d; a" [: _5 |! T; U
  18. 0x0800015C 1AFB      SUBNE    r3,r7,r35 G9 R1 D( m! j5 a/ \7 |
  19. 0x0800015E F0430301  ORR      r3,r3,#0x017 n/ I" R! ?7 Y* `* E0 z, d, Q+ D
  20. 0x08000162 4718      BX       r39 J9 s8 h5 ^4 \3 l) c" M
  21. 0x08000164 0298      LSLS     r0,r3,#10- n2 j0 @  G% b9 F6 t# c$ c: M. B
  22. 0x08000166 0000      MOVS     r0,r05 ]. k( c' t/ B0 }1 l$ J
  23. 0x08000168 02B8      LSLS     r0,r7,#103 j9 z- K, r9 y1 M# V$ U
  24. 0x0800016A 0000      MOVS     r0,r0- s  I4 o  t! F
  25.                  __scatterload_copy:+ ]+ }: I8 R7 g  \# k7 q* X% P- `
  26. 0x0800016C 3A10      SUBS     r2,r2,#0x10
    * p( S4 ~2 t( y
  27. 0x0800016E BF24      ITT      CS
    ! l2 }( w/ D0 A0 J3 E
  28. 0x08000170 C878      LDMCS    r0!,{r3-r6}
    + a! F9 F& T5 A
  29. 0x08000172 C178      STMCS    r1!,{r3-r6}1 j' u! E- ]7 ]: r  P$ V3 W+ T
  30. 0x08000174 D8FA      BHI      __scatterload_copy (0x0800016C)5 e2 Y7 `" T& u2 c2 e, P
  31. 0x08000176 0752      LSLS     r2,r2,#29& L+ e& |( {  q+ @* Q
  32. 0x08000178 BF24      ITT      CS
    ( [6 Q  n! P" V2 Y# X6 m
  33. 0x0800017A C830      LDMCS    r0!,{r4-r5}$ s0 T8 o8 U$ K; D. r: t; Q' A
  34. 0x0800017C C130      STMCS    r1!,{r4-r5}
    . J+ U3 ]8 ^  H
  35. 0x0800017E BF44      ITT      MI
    0 O& G4 N5 B* Y9 ]) F, L. k. [) L
  36. 0x08000180 6804      LDRMI    r4,[r0,#0x00]
    1 k1 v2 @5 ^0 b5 t/ V% A
  37. 0x08000182 600C      STRMI    r4,[r1,#0x00]( c. G0 t0 n6 q" O+ {
  38. 0x08000184 4770      BX       lr2 r% G8 p! x# l, S: `
  39. 0x08000186 0000      MOVS     r0,r0$ \4 T' g+ f6 q
  40.                  __scatterload_zeroinit:4 ~3 y0 y  z( d/ V; ^
  41. 0x08000188 2300      MOVS     r3,#0x00
    : w, v% Z9 Y6 b3 H- \
  42. 0x0800018A 2400      MOVS     r4,#0x00
    $ e: P& y8 {( C3 V% F* J
  43. 0x0800018C 2500      MOVS     r5,#0x00( w8 H( q& ~, n/ k: i
  44. 0x0800018E 2600      MOVS     r6,#0x00
    : j' ~4 ?# b8 G  \, u8 H. |
  45. 0x08000190 3A10      SUBS     r2,r2,#0x10
    : n0 L# I1 ~( t. u. e% n6 w
  46. 0x08000192 BF28      IT       CS' @  r. B3 I2 s1 k
  47. 0x08000194 C178      STMCS    r1!,{r3-r6}
      [0 S1 x' b- y
  48. 0x08000196 D8FB      BHI      0x08000190: o. o/ R$ L7 q( j9 P+ }5 `5 {' ~
  49. 0x08000198 0752      LSLS     r2,r2,#29
    : \0 d9 x) A# J* i4 Y5 u
  50. 0x0800019A BF28      IT       CS
    4 C1 f( M9 d& E  n5 ?: ]3 ?5 [
  51. 0x0800019C C130      STMCS    r1!,{r4-r5}
    + s* t0 A0 c5 q# x
  52. 0x0800019E BF48      IT       MI
    , V* b9 ^  y) t3 L
  53. 0x080001A0 600B      STRMI    r3,[r1,#0x00]
    + U5 k1 |/ J0 e, p/ n5 p
  54. 0x080001A2 4770      BX       lr
    6 ^9 Q- d- h0 g) f* \; N" Z
  55.                  __rt_lib_init:& M- m3 k/ H( q+ D
  56. 0x080001A4 B51F      PUSH     {r0-r4,lr}+ A3 K' O" ?6 Z* C% V
  57. 0x080001A6 F3AF8000  NOP.W    - e2 y8 g! O6 N1 ^
  58.                  __rt_lib_init_user_alloc_1:
    / U5 o1 n9 V8 }% B' n8 m
  59. 0x080001AA BD1F      POP      {r0-r4,pc}  T! i/ k; C7 z3 l  [2 i
  60.                  __rt_lib_shutdown:( S- Q# z& P8 U8 [) @
  61. 0x080001AC B510      PUSH     {r4,lr}# D; A% ^+ `! x9 `) q
  62.                  __rt_lib_shutdown_user_alloc_1:& w4 a' q$ l; o; m+ }# k
  63. 0x080001AE BD10      POP      {r4,pc}
    + `0 W0 E7 _7 B
  64.                  __rt_entry_sh:
    - t9 j# k9 c9 d
  65. 0x080001B0 F000F82F  BL.W     __user_setup_stackheap (0x08000212)$ x# d9 j' F4 @; ~
  66. 0x080001B4 4611      MOV      r1,r20 K+ t+ `8 q1 s& L6 R: C5 F
  67.                  __rt_entry_postsh_1:
    5 P6 n* ?9 q+ b" k( m) a
  68. 0x080001B6 F7FFFFF5  BL.W     __rt_lib_init (0x080001A4)
    : A, s) s6 Y3 W
  69.                  __rt_entry_postli_1:
    . ^/ E# w+ t# @- k
  70. 0x080001BA F000F919  BL.W     main (0x080003F0)
复制代码
. m  a# r4 w9 T6 n0 E
2、使用微库而不使用系统库
  在程序连接时,不会把包含printf函数的库连接到终极目标文件中,而使用我们定义的库。
  启动时需要完成的工作就是之前论述的步骤1、2、3、4、5,相比使用系统库,启动过程步骤更少。

* J, D, g7 l. ?5 N1 B- m# r
9 i( W- g6 f8 j4 g2 u+ i
收藏 评论0 发布时间:2022-1-13 21:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版