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

【经验分享】了解STM32启动过程,好优化程序

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

    % e5 Z5 H' _8 Y" y2 E6 T# ]

    8 n9 X9 p1 p! R( k
    .data和.bss是在__main里进行初始化的,对于ARM Compiler,__main主要执行以下函数:
XVER@XD2GEI[XK6N9715T.png
    其中__scatterload会对.data和.bss进行初始化。
加载数据段和初始化栈的参数
    加载数据段和初始化栈的参数分别有4个,这里只讲解加载数据段的参数,至于初始化栈的参数类似。
  1. 0x0800033c  Flash上的数据段(初始化数据段和未初始化数据段)起始地址
      B9 g- v3 O/ C/ O9 N8 w1 \- `, w% l
  2. 0x20000000  加载到SRAM上的目的地址
    6 [2 K4 b+ N5 F2 L) E
  3. 0x0000000c  数据段的总大小2 k: S- O' s% i- i- G
  4. 0x080002f4  调用函数_scatterload_copy
复制代码
$ M' m4 D, k; |: B, E% T4 d6 f
    需要说明的是初始化栈的函数-- 0x08000304与加载数据段的函数不一样,为 _scatterload_zeroinit,它的目的就是将栈空间清零。
3 数据在SRAM上的结构
    程序运行时(执行到main函数)时的SRAM数据结构
@X]PDH1~K1QIZ@DQ8}FA25Q.png
4 详细过程分析
    有了以上的基础,现在详细分析启动过程
上电后硬件设置SP、PC
    刚上电复位后,硬件会自动根据向量表偏移地址找到向量表,向量表偏移地址的定义如下:
]IJOOTZCW2CDWTD7R6%%EWW.png
    调试现象如下:
    看看我们的向量表内容(通过J-Flash打开hex文件)
SI6IDUCW8W9N}J{GQDKTO49.png
    硬件这时自动从0x0800 0000位置处读取数据赋给栈指针SP,然后自动从0x0800 0004位置处读取数据赋给PC,完成复位,结果为:
  1. SP = 0x02000810
    ' T$ D; D, h% W& i, s; S% l" J, g
  2. PC = 0x08000145
复制代码

1 |, B0 X2 {1 u5 q
设置系统时钟
    上一步中令 PC=0x08000145的地址没有对齐,硬件自动对齐到 0x08000144,执行 SystemInit函数初始化系统时钟。
软件设置SP+ t- N9 g6 V( c! W6 v
  1. LDR   R0,=__main8 I/ R- P: `  X$ w
  2.   BX   R0
复制代码
8 ^9 M& C2 V" [3 P. ?. w
    执行上两条之类,跳转到 __main程序段运行,注意不是main函数, ___main的地址是0x0800 0130。
    可以看到指令LDR.W sp,[pc,#12],结果SP=0x2000 0810。
加载.data、.bss,并初始化栈区- r- g) R% n  z# J5 u
  1. BL.W     __scatterload_rt2
复制代码

% h' Z+ H+ R& l# l. B( ~6 I
    进入 __scatterload_rt2代码段。
  1. __scatterload_rt2:/ G$ S) n" d7 @# S
  2. 0x080001684C06      LDR      r4,[pc,#24]  ; @0x08000184) Q3 V5 ?$ J, ]( |
  3. 0x0800016A4D07      LDR      r5,[pc,#28]  ; @0x08000188
    / y2 L2 _7 P0 m3 g6 [* w+ D! g9 p
  4. 0x0800016C E006      B        0x0800017C! Q& Q! K7 P5 i  \2 t
  5. 0x0800016E68E0      LDR      r0,[r4,#0x0C]
      z) o1 `8 o* A, v# W
  6. 0x08000170 F0400301  ORR      r3,r0,#0x01) W: L7 e3 S% j4 V  k% w( |
  7. 0x08000174 E8940007  LDM      r4,{r0-r2}
    : X* |# q* p0 W7 _: b1 d3 z2 @- |( B
  8. 0x080001784798      BLX      r3
    + c( c8 `8 g) [' S) F! I
  9. 0x0800017A3410      ADDS     r4,r4,#0x109 N3 C3 n% w5 h( q: \! n2 U
  10. 0x0800017C42AC      CMP      r4,r5
    ! H- y# Z* I$ ?# ~* S4 X2 e
  11. 0x0800017E D3F6      BCC      0x0800016E% C7 _! t2 V8 r! W% P
  12. 0x08000180 F7FFFFDA  BL.W     _main_init (0x08000138)
复制代码
, R, s; X) b0 N/ O$ ?$ [; }4 _& H8 A
    这段代码是个循环 (BCC0x0800016e),实际运行时候循环了两次。第一次运行的时候,读取“加载数据段的函数 (_scatterload_copy)”的地址并跳转到该函数处运行(注意加载已初始化数据段和未初始化数据段用的是同一个函数);第二次运行的时候,读取“初始化栈的函数 (_scatterload_zeroinit)”的地址并跳转到该函数处运行。相应的代码如下:
  1. 0x0800016E68E0      LDR      r0,[r4,#0x0C]. Z( T) U7 r) i6 K' G6 j6 n/ A# |
  2. 0x08000170 F0400301  ORR      r3,r0,#0x01
    # G, E" A# x! O% Y4 s5 a2 T
  3. 0x080001740 E) Z9 ?) C2 y6 Z. k
  4. 0x080001784798      BLX      r3
复制代码

  q1 n3 s) u9 x; j* X
    当然执行这两个函数的时候,还需要传入参数。至于参数,我们在“加载数据段和初始化栈的参数”环节已经阐述过了。当这两个函数都执行完后,结果就是“数据在SRAM上的结构”所展示的图。最后,也把事实加载和初始化的两个函数代码奉上如下:
  1. __scatterload_copy:' L$ |$ N3 U+ m. R; ?
  2. 0x080002F4 E002      B        0x080002FC
    1 j6 J. Z/ P( X! E2 L/ ]: f
  3. 0x080002F6 C808      LDM      r0!,{r3}
    2 x2 B5 w, o/ r
  4. 0x080002F81F12      SUBS     r2,r2,#47 i- i  u: l& l4 l. e: x( ?2 K3 a
  5. 0x080002FA C108      STM      r1!,{r3}
    8 e1 D1 b- ^0 T+ |: U9 }5 Q
  6. 0x080002FC2A00      CMP      r2,#0x003 s4 V/ a' v7 n
  7. 0x080002FE D1FA      BNE      0x080002F6
    - C2 {7 d9 b& |0 i
  8. 0x080003004770      BX       lr" ~" }3 P8 r1 B$ w1 a) s: @) R
  9. __scatterload_null:, U5 D0 l/ ^; n
  10. 0x080003024770      BX       lr! ], I1 D( N- c3 y9 \
  11. __scatterload_zeroinit:9 Q$ \: }) J1 u9 N7 m
  12. 0x080003042000      MOVS     r0,#0x00
      K5 j" H( H6 j& i9 U/ X# ]
  13. 0x08000306 E001      B        0x0800030C
    , v' K' f1 U+ R, A6 j/ D
  14. 0x08000308 C101      STM      r1!,{r0}
    & [5 }9 m* K- R3 o% P+ R
  15. 0x0800030A1F12      SUBS     r2,r2,#4/ p7 T3 V& _: ?* U: v; o
  16. 0x0800030C2A00      CMP      r2,#0x00
    " A6 p- U. y7 \( T: g
  17. 0x0800030E D1FB      BNE      0x08000308) L' w2 R! V% ^+ U/ H7 X! g- z0 k
  18. 0x080003104770      BX       lr
复制代码
& c0 `. |, g! X8 f0 ], ~' ^0 D
跳转到C文件的main函数% ^  k8 Q1 a, d
  1. _main_init:
    ) a) r3 j( Y) Q. \
  2. 0x080001384800      LDR      r0,[pc,#0]  ; @0x0800013C' w. p; h0 a) `
  3. 0x0800013A4700      BX       r0
复制代码
# M" q0 ?+ K) c1 Y
5 异常向量与中断向量表
# w8 G) X5 Q, O
  1. ; VectorTableMapped to Address0 at Reset6 m$ K9 L& g0 N. H
  2. AREA    RESET, DATA, READONLY  N. }1 f9 m7 A  l" T% p# |3 ]+ K
  3. EXPORT  __Vectors  n: {4 ^8 P; L) H; \
  4. EXPORT  __Vectors_End
    9 R8 N& M5 f# M. W* R
  5. EXPORT  __Vectors_Size
    ' g0 v, v4 v6 ~% p

  6. 2 N3 ]( B6 R+ `  o/ o; q" Z
  7. ) ~6 Y7 ~6 X6 t' z
  8. __Vectors       DCD     __initial_sp               ; Top of Stack
    - M5 B" u7 b5 s6 Q) [$ h
  9. DCD     Reset_Handler; ResetHandler
    % l2 y- m0 \2 v# a
  10. DCD     NMI_Handler                ; NMI Handler
    8 X7 x. s  r1 b4 X
  11. DCD     HardFault_Handler; HardFaultHandler* H8 H+ n; V' q) _% R
  12. DCD     MemManage_Handler; MPU FaultHandler
    , |  I( T9 _' n9 u+ n# ^: b
  13. DCD     BusFault_Handler; BusFaultHandler
    1 R9 C$ U& ?( b6 J  e" c2 b' s9 M4 N
  14. DCD     UsageFault_Handler; UsageFaultHandler! a& _' G0 ^; ~% p
  15. DCD     0; Reserved
    6 r+ d2 ]! a0 b1 w/ v
  16. DCD     0; Reserved
    1 U+ A: K( s4 K5 D! g' i" I
  17. DCD     0; Reserved/ @, H+ @: _7 p: l) p2 g8 F
  18. DCD     0; Reserved
    - i; \4 t) r- y6 j! L2 l
  19. DCD     SVC_Handler                ; SVCallHandler, |' j; b3 w* e  H: J$ A* F
  20. DCD     DebugMon_Handler; DebugMonitorHandler0 r' r' Y1 a% r- j9 Y  D
  21. DCD     0; Reserved
    2 k3 s( d8 W' E' R
  22. DCD     PendSV_Handler; PendSVHandler  a& O) Y( K1 h+ `; m
  23. DCD     SysTick_Handler; SysTickHandler
    " P- E3 I% b* X8 X

  24. * l7 N" h0 b6 a! r+ O; c  H, t

  25. : g6 c- `8 c& I% d. [9 q
  26. ; ExternalInterrupts8 Z& W8 X& L8 u0 d+ m; n
  27. DCD     WWDG_IRQHandler            ; WindowWatchdog
    2 p6 K  B. a) i2 H5 ?; u( g
  28. DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
    8 G+ p6 V( K# T& v
  29. DCD     TAMPER_IRQHandler          ; Tamper
      ?( R5 r) m& Q3 J: y8 m' G% |
  30. DCD     RTC_IRQHandler             ; RTC8 ?7 {( V# `5 }
  31. DCD     FLASH_IRQHandler           ; Flash4 B' \* Z( G) s* K: ?+ n. A) \
  32. DCD     RCC_IRQHandler             ; RCC
    & w* S( ^2 {9 ]/ R3 ^
  33. DCD     EXTI0_IRQHandler           ; EXTI Line0
    ! K, n! T8 E" c0 ~$ ]& k
  34. DCD     EXTI1_IRQHandler           ; EXTI Line1+ S- b6 Y6 ?+ I/ g
  35. DCD     EXTI2_IRQHandler           ; EXTI Line2) S- m4 F! o+ f
  36. DCD     EXTI3_IRQHandler           ; EXTI Line34 P" U7 w- n7 t% e
  37. DCD     EXTI4_IRQHandler           ; EXTI Line4- D: p5 u' b& W
  38. DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel1
      C4 z  p% _8 I% U. |) m* h$ P
  39. DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel2- `! L) C* w; y  J* {
  40. DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel3
    % Y7 C, ^4 y+ R. {$ y1 j( i
  41. DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel4
    " Z2 k3 q+ y( l4 W! ?1 L
  42. DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel5
    8 R! N/ z* p# g' `, Z
  43. DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel6
    0 t! W0 n. r# T7 z
  44. DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel7
    ( D$ C2 U7 y4 h3 V1 [& ?) M& U( j: l
  45. DCD     ADC1_2_IRQHandler          ; ADC1 & ADC2% P1 P* [" @, q1 O9 \3 K: u# x
  46. DCD     USB_HP_CAN1_TX_IRQHandler  ; USB HighPriority or CAN1 TX
    3 t2 f2 @* _/ \+ h: A$ U
  47. DCD     USB_LP_CAN1_RX0_IRQHandler ; USB LowPriority or CAN1 RX0& W4 u. Q5 J  U, S. E0 h
  48. DCD     CAN1_RX1_IRQHandler        ; CAN1 RX10 ]: f9 f5 ~- i: h1 C% w( P' ^5 {
  49. DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
    1 `9 w8 C& A' `3 H, o# r) r1 }
  50. DCD     EXTI9_5_IRQHandler         ; EXTI Line9..52 J2 s! {, J; D( N! @/ s1 B
  51. DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
    : I9 k. T8 u) m0 |. ]; `9 N8 r/ p
  52. DCD     TIM1_UP_IRQHandler         ; TIM1 Update
    4 [! `# `4 [- E# N: x2 l; L
  53. DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
    4 N; U, }2 K, Q# P: J! |; V! h5 {
  54. DCD     TIM1_CC_IRQHandler         ; TIM1 CaptureCompare2 n; Z0 h3 G7 [' S' z: E1 L- N
  55. DCD     TIM2_IRQHandler            ; TIM2
    " ?; {% b, A, p% P: V- A7 }1 n3 Z
  56. DCD     TIM3_IRQHandler            ; TIM3
    # s. r2 ^( V! d4 A+ G8 J4 o4 h
  57. DCD     TIM4_IRQHandler            ; TIM40 R) D) _, I+ U$ w/ h
  58. DCD     I2C1_EV_IRQHandler         ; I2C1 Event9 ^2 o( g5 x4 M9 Z4 j
  59. DCD     I2C1_ER_IRQHandler         ; I2C1 Error
    - V) a; c% V# b* T% I6 j' j$ @1 g
  60. DCD     I2C2_EV_IRQHandler         ; I2C2 Event" I1 p$ K* q' A: P
  61. DCD     I2C2_ER_IRQHandler         ; I2C2 Error
    # {- m9 _0 a0 Y1 B$ v) ~5 }
  62. DCD     SPI1_IRQHandler            ; SPI1
    % ~! ~/ s; c) D. f  U. p& W
  63. DCD     SPI2_IRQHandler            ; SPI2
    1 F$ I1 g; o$ S( @5 Y
  64. DCD     USART1_IRQHandler          ; USART1
    , L4 F& Y1 h5 J2 Q- S% p8 _! _! l
  65. DCD     USART2_IRQHandler          ; USART2
    1 J0 t$ A% N0 F! o6 e
  66. DCD     USART3_IRQHandler          ; USART3# b  C" N, |9 T! o$ X( j$ c8 F& b. m
  67. DCD     EXTI15_10_IRQHandler       ; EXTI Line15..10& y1 s( Q4 ^+ @2 F; C
  68. DCD     RTCAlarm_IRQHandler; RTC Alarm through EXTI Line
    $ y$ C  R* m$ G$ o  h7 L+ ^5 ?3 I7 y
  69. DCD     USBWakeUp_IRQHandler; USB Wakeup from suspend" d7 l5 q/ |6 |0 _, }# c
  70. DCD     TIM8_BRK_IRQHandler        ; TIM8 Break
    / n  n- ]1 `1 X7 \7 d/ L
  71. DCD     TIM8_UP_IRQHandler         ; TIM8 Update  b* R5 M* T9 \& F7 o. ^( f- Q
  72. DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation
    / J2 X/ l6 ^1 i: Y, Z2 P* L  s
  73. DCD     TIM8_CC_IRQHandler         ; TIM8 CaptureCompare, E2 d, B+ |0 W5 t% q6 h/ J# b
  74. DCD     ADC3_IRQHandler            ; ADC3
    / d! f; C5 A6 Z. J) o5 ?6 X3 ?
  75. DCD     FSMC_IRQHandler            ; FSMC
    7 ?8 n! m' u3 D, B5 n/ {. n  f
  76. DCD     SDIO_IRQHandler            ; SDIO1 r2 Z' [8 I7 P
  77. DCD     TIM5_IRQHandler            ; TIM5
    $ ]- W3 v+ Q' `' F9 u  a3 I
  78. DCD     SPI3_IRQHandler            ; SPI3
    & o8 Q! i- k; ?3 ~/ y; H
  79. DCD     UART4_IRQHandler           ; UART4+ ]( C3 ]+ X. D+ l
  80. DCD     UART5_IRQHandler           ; UART5* @# E: X- p; M" T( e1 o5 z; f, G
  81. DCD     TIM6_IRQHandler            ; TIM66 m, L2 L  H/ z1 v  N( P9 j+ W
  82. DCD     TIM7_IRQHandler            ; TIM7
    - a: e4 `' M, D. G. {0 }4 b1 i
  83. DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1
    # g: D# S* r  T7 ?3 E. q, a
  84. DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2
    " ^. g3 M  X) ^8 p! Z5 g2 H
  85. DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3( [/ t% d7 _# T( W3 l! p4 B
  86. DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4& Channel5
      \7 l/ n; r- d" H
  87. __Vectors_End
复制代码
8 f) P; G9 U( ]" I
    这段代码就是定义异常向量表,在之前有一个“J-Flash打开hex文件”的图片跟这个表格是一一对应的。编译器根据我们定义的函数 Reset_Handler、NMI_Handler等,在连接程序阶段将这个向量表填入这些函数的地址。
  1. startup_stm32f10x_hd.s内容:0 {# R0 C1 R% Q9 _- V+ B6 m1 g$ f0 h
  2. % `6 A3 z& M7 e7 Q' o7 f

  3. + J% ]) v4 {! K* l. V4 N" z
  4. NMI_Handler     PROC
    0 h. Y: A& x2 W* e. L! ~
  5. EXPORT  NMI_Handler                [WEAK]
    # `( x- ~. u# g- K: E7 a% h
  6. B       .
    3 u5 x2 H2 X# }% F
  7. ENDP
    * |5 k7 p8 \" B$ _
  8. # L0 j6 F: u" H2 N% u) Q

  9. 2 D& Y3 R; g, k# R9 ]" l/ g5 s# X
  10. * u5 W$ B, A3 Y0 O' e8 U3 u) c

  11. 8 R0 W# g6 ^# i. ]3 i2 K" j
  12. stm32f10x_it.c中内容:. k+ K6 E7 p( Z- k& _$ Q6 C' U
  13. void NMI_Handler(void)1 ]4 J" K6 ]% T0 e% j' p
  14. {3 U7 j) P( N4 W6 R* J* W& w- Q( g- H
  15. }
复制代码
. D4 T) `0 U& l  i0 S
    在启动汇编文件中已经定义了函数 NMI_Handler,但是使用了“弱”,它允许我们再重新定义一个 NMI_Handler函数,程序在编译的时候会将汇编文件中的弱函数“覆盖掉”--两个函数的代码在连接后都存在,只是在中断向量表中的地址填入的是我们重新定义函数的地址。
6 使用微库与不使用微库的区别
4OWR(Y50](DAOSWVYXYU{26.png
    使用微库就意味着我们不想使用MDK提供的库函数,而想用自己定义的库函数,比如说printf函数。那么这一点是怎样实现的呢?我们以printf函数为例进行说明。
不使用微库而使用系统库
    在连接程序时,肯定会把系统中包含printf函数的库拿来调用参与连接,即代码段有系统库的参与。
    在启动过程中,不使用微库而使用系统库在初始化栈的时候,还需要初始化堆(猜测系统库需要用到堆),而使用微库则是不需要的。
  1. IF      :DEF:__MICROLIB
    ; c/ a( m" @0 w# w: y

  2. 6 r9 z' P1 ~9 Z8 u) E/ ]

  3. / y  }/ S5 x2 @. d. ^
  4. EXPORT  __initial_sp
    / w* r2 z0 O* {. @9 G
  5. EXPORT  __heap_base
    & x6 b: g1 k' v6 q
  6. EXPORT  __heap_limit, h/ y, h# W1 C, k

  7. - A8 u/ i6 T- Q' s

  8. 6 [4 [/ D4 a& A& j' o* W
  9. ELSE
    & R  W! w! k, p" C* ^( z3 e
  10. ( _: i4 |! r: v& h8 m6 c$ W

  11. 2 E3 \4 B: k9 E, i
  12. IMPORT  __use_two_region_memory
    ) O) A& o0 z% v  N+ u
  13. EXPORT  __user_initial_stackheap' M4 [& l3 g' ?9 ?1 I1 P
  14. 0 S; `+ `; v# M
  15. 0 |+ L7 X0 y7 |/ O2 O: H! W
  16. __user_initial_stackheap$ P5 r- z! E, r+ p
  17. 9 e) k8 \9 h5 X8 \/ {- b

  18. ) u# q  I0 R1 z
  19. LDR     R0, =  Heap_Mem
    % D; ?! ]) C. }: M* ]# g
  20. LDR     R1, =(Stack_Mem+ Stack_Size)
      q  @& V& v. C# `. M* E* T$ ~0 }9 B
  21. LDR     R2, = (Heap_Mem+  Heap_Size)1 B9 w3 P* j- w
  22. LDR     R3, = Stack_Mem
    . x$ @! K: M! A8 M, q( T1 b. x
  23. BX      LR
    % y; j$ q8 s  |5 v* F0 K

  24. 0 b3 J5 a- V3 ?" \$ \

  25. 0 G  P! U6 f& v+ b9 y2 L) Z
  26. ALIGN6 e) H3 B5 s6 r) s! }

  27. / c! r5 g) q/ _! H6 t$ h

  28. 3 F5 ~+ O5 E! Q. U2 D: F5 u
  29. ENDIF
复制代码
- [8 Q: b# G2 p/ x5 f  w4 h
    另外,在执行 __main函数的过程中,不仅需要完成“使用微库”情况下的所有工作,额外的工作还需要进行库的初始化,才能使用系统库(这一部分我还没有深入探讨)。附上 __main函数的内容:
  1. __main:
    ! I9 U2 w0 b9 [
  2. 0x08000130 F000F802  BL.W     __scatterload_rt2_thumb_only (0x08000138)
    * q, l, Z, B- ^  g! p
  3. 0x08000134 F000F83C  BL.W     __rt_entry_sh (0x080001B0)5 c  p4 j4 l2 b  W5 z. w' m
  4. __scatterload_rt2_thumb_only:
    5 x  g9 V# x* _
  5. 0x08000138 A00A      ADR      r0,{pc}+4; @0x08000164/ J6 R. _. M# U
  6. 0x0800013A E8900C00  LDM      r0,{r10-r11}
    7 |9 C$ V9 w: b. k; x& O8 W
  7. 0x0800013E4482      ADD      r10,r10,r0- W* d( u& V6 b
  8. 0x080001404483      ADD      r11,r11,r01 v) r7 W  o; v$ J
  9. 0x08000142 F1AA0701  SUB      r7,r10,#0x01
    6 u1 u7 r- m/ b+ Y
  10. __scatterload_null:
    1 h5 v* C# `5 i5 P/ e5 G
  11. 0x0800014645DA      CMP      r10,r111 c% g* R/ p* I3 z4 v& |
  12. 0x08000148 D101      BNE      0x0800014E( l- L4 ]4 n  a& W$ x- Y
  13. 0x0800014A F000F831  BL.W     __rt_entry_sh (0x080001B0)
    9 l4 O3 O9 n! |3 z
  14. 0x0800014E F2AF0E09  ADR.W    lr,{pc}-0x07; @0x08000147+ B0 q/ f& d5 m& \
  15. 0x08000152 E8BA000F  LDM      r10!,{r0-r3}. |/ a0 {! v9 X* W
  16. 0x08000156 F0130F01  TST      r3,#0x017 ]% C7 a% x$ h9 |4 b' H6 w- I
  17. 0x0800015A BF18      IT       NE
    8 o6 q5 ~  p% l8 x
  18. 0x0800015C1AFB      SUBNE    r3,r7,r3  m0 R% o8 I! O8 G- `
  19. 0x0800015E F0430301  ORR      r3,r3,#0x01
    & V0 A# [* `) [  r
  20. 0x080001624718      BX       r3
    8 [$ @5 A% {+ m; K+ T
  21. 0x080001640298      LSLS     r0,r3,#10: w3 F" X: p$ c
  22. 0x080001660000      MOVS     r0,r03 p$ i6 h4 X8 [+ \7 D" h  C6 C
  23. 0x0800016802B8      LSLS     r0,r7,#10
    / _, a) Q* l/ Q! q$ n7 }" }- c
  24. 0x0800016A0000      MOVS     r0,r0
    , C; Z- H! d, d
  25. __scatterload_copy:
    2 ]' q" v. Z# C( S; j; h* `  q
  26. 0x0800016C3A10      SUBS     r2,r2,#0x10
    / B" ], F& \* L: V6 d
  27. 0x0800016E BF24      ITT      CS
    6 ]0 L2 P! a1 q5 [- P- g
  28. 0x08000170 C878      LDMCS    r0!,{r3-r6}) J" s0 P  A. K' @
  29. 0x08000172 C178      STMCS    r1!,{r3-r6}+ t0 f! v; I6 b5 A
  30. 0x08000174 D8FA      BHI      __scatterload_copy (0x0800016C)
    4 Q$ H& |! H. _" O! \
  31. 0x080001760752      LSLS     r2,r2,#29+ U, k3 C4 ~8 Z3 r
  32. 0x08000178 BF24      ITT      CS
    : b3 \) g! _% d9 n0 r) g7 q
  33. 0x0800017A C830      LDMCS    r0!,{r4-r5}
    2 ~0 }2 t- n0 R
  34. 0x0800017C C130      STMCS    r1!,{r4-r5}( K# _4 f  G$ J+ q* M  C% b
  35. 0x0800017E BF44      ITT      MI5 I+ D/ ^: i( l% m& r4 F% S; g
  36. 0x080001806804      LDRMI    r4,[r0,#0x00]1 Z, h9 N: N& t8 _
  37. 0x08000182600C      STRMI    r4,[r1,#0x00]
    4 Q1 s% `- u! f- P. a  u4 e
  38. 0x080001844770      BX       lr5 R8 Y) k* @' L1 G' T1 |2 u  E
  39. 0x080001860000      MOVS     r0,r0
    9 B/ G1 \$ a/ N5 B+ E! c
  40. __scatterload_zeroinit:
    1 d8 Z/ T( w3 _8 I3 m; N2 P
  41. 0x080001882300      MOVS     r3,#0x00
    7 g4 f' j& W% A6 |$ d8 x
  42. 0x0800018A2400      MOVS     r4,#0x00
    # V1 S- _6 |+ I' d
  43. 0x0800018C2500      MOVS     r5,#0x00
    + P1 f' G( H2 l- w
  44. 0x0800018E2600      MOVS     r6,#0x00
    . q3 L/ t: j3 U1 w
  45. 0x080001903A10      SUBS     r2,r2,#0x10$ ~2 a4 G: h7 l
  46. 0x08000192 BF28      IT       CS+ O6 A- W- \7 C7 R
  47. 0x08000194 C178      STMCS    r1!,{r3-r6}# q2 I) o0 z& c8 O# i
  48. 0x08000196 D8FB      BHI      0x08000190
    / @4 q9 [0 D6 J) ?0 [
  49. 0x080001980752      LSLS     r2,r2,#29! V& P  [: y$ b
  50. 0x0800019A BF28      IT       CS, z2 {- E9 M) x* {
  51. 0x0800019C C130      STMCS    r1!,{r4-r5}, o0 c# b: A8 e% o! j% x, M
  52. 0x0800019E BF48      IT       MI8 B2 V0 E- x8 C# u4 K3 _5 P
  53. 0x080001A0600B      STRMI    r3,[r1,#0x00]
    : y9 \3 O. h- t5 ?9 n
  54. 0x080001A24770      BX       lr
    7 D) k7 c- Z% Y2 C
  55. __rt_lib_init:" o) t% [* j1 |" N; C. a
  56. 0x080001A4 B51F      PUSH     {r0-r4,lr}
    9 s, R/ w  e3 F1 _) h! }
  57. 0x080001A6 F3AF8000  NOP.W
    + g3 Z0 T0 p* f% [  K" a  R4 z
  58. __rt_lib_init_user_alloc_1:/ U, }' r6 o. p# C& V3 L6 T" z
  59. 0x080001AA BD1F      POP      {r0-r4,pc}5 U. p! C! R4 X" ~+ z2 `
  60. __rt_lib_shutdown:
    2 o' f0 s" V; I6 M6 q4 V. e; b( ]
  61. 0x080001AC B510      PUSH     {r4,lr}. d/ t9 _3 n8 F7 R
  62. __rt_lib_shutdown_user_alloc_1:* P9 r0 R0 W: g+ Q, P" Z. l3 k
  63. 0x080001AE BD10      POP      {r4,pc}. a" o: b. q2 e
  64. __rt_entry_sh:
    4 G& w/ }7 A. S* A
  65. 0x080001B0 F000F82F  BL.W     __user_setup_stackheap (0x08000212)
    7 h0 W6 W2 j) q+ }2 O
  66. 0x080001B44611      MOV      r1,r2% _- D, c7 _" k! c) p3 D
  67. __rt_entry_postsh_1:
      |9 d& ?  ~" R& T9 [
  68. 0x080001B6 F7FFFFF5  BL.W     __rt_lib_init (0x080001A4); ?% N8 [3 ], I# e7 J6 N. `
  69. __rt_entry_postli_1:& E- t: G) w' d
  70. 0x080001BA F000F919  BL.W     main (0x080003F0)
复制代码
  p) A6 z# o, s& ~! e& L7 y, a: O, d
使用微库而不使用系统库
    在程序连接时,不会把包含printf函数的库连接到终极目标文件中,而使用我们定义的库。
    启动时需要完成的工作就是之前论述的步骤1、2、3、4、5,相比使用系统库,启动过程步骤更少。

8 a( t. u( T# P1 p: N- v; i
( A2 M" y2 k- t; n( l7 H: o2 ]: b8 G" `
]~6M3V[3`6DHL{0U_1TB0EW.png
赞 收藏 评论0 发布时间:2021-11-7 18:07

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版