找回密码
 注册
关于网站域名变更的通知
查看: 319|回复: 1
打印 上一主题 下一主题

Cortex-M/R 内核启动流程之退出阶段

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-9-25 15:50 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
本帖最后由 uperrua 于 2020-9-25 15:52 编辑 6 \, w8 w" Q  m( N+ ~  M; ~
$ R! c4 g1 R4 I5 b1 @
  通常,嵌入式应用程序的执行永远不会结束。 如果推出了,则必须定义正确的结束行为。
( u4 M3 \& L/ m- j! ?  要以受控方式终止应用程序,请调用标准C库函数之一 exit,_Exit,quick_exit 或 abort,或从main 返回。 如果从main 返回,则自动执行 exit 函数,这意味着调用静态和全局变量的 C++ 析构函数(仅限C ++)并关闭所有打开的文件。
* k4 ?# a# t5 q0 o, G" o  当然,如果程序逻辑不正确,应用程序可能会以不受控制的异常方式终止 - 系统崩溃。
: U1 b$ K- g, _+ O+ h3 c7 P6 q* G' n ' f. g/ v* z& X1 q* \
; J5 R) Z: q7 F( n
应用程序可以通过两种不同方式正常终止:  [' y0 E# ?+ B, r1 d% ~- D

% x3 |% T3 S1 ]' h( N1 x! v, n, k* a! h
  • Return from the main function
  • Call the exit function.
    . q6 ^6 S& t& e( k4 P- i/ U: T  h
6 |* x0 r1 g6 O6 o* _; Z
  因为 C 标准声明这两个方法应该是等价的,所以如果main()函数返回,系统启动代码会调用exit() 函数。传递给exit()函数的参数是main()的返回值。: b$ z! r3 ^% L: g' k' g7 l
默认退出函数用C语言编写。它调用一个小的汇编程序函数_exit,它将:6 Q( F' ~$ f8 h/ R; i6 q2 B/ E$ g

7 h9 a, b: b% o+ w) l# F$ z
  • Call functions registered to be executed when the application ends. This includes C++ destructors for static and global variables, and functions registered with the standard function atexit. See also Setting up the atexit limit, page 110.
  • Close all open files
  • Call __exit
  • When __exit is reached, stop the system.
    * ]$ I* U: `$ S/ D3 w# }) m# x
" A8 A9 R0 `% c: V- C; k
  应用程序也可以通过调用 abort,_Exit 或 quick_exit 函数退出。中止函数只是调用__exit来暂停系统,并且不执行任何类型的清理。The _Exit function is equivalent to the abort function, except for the fact that _Exit takes an argument for passing exit status information._Exit函数等同于 abort 函数,事实上,_Exit接受一个参数来传递退出状态信息。The quick_exit function is equivalent to the _Exit function, except that it calls each function passed to at_quick_exit before calling __exit. quick_exit函数等同于__Exit函数,只是它在调用__exit之前会刁艳红每个传递给_quick_exit的函数。
- f$ }: j; k9 ?+ d7 A8 I  如果您希望应用程序在退出时执行任何额外操作,例如重置系统(如果使用atexit是不够的),您可以编写自己的__exit(int)函数实现。
4 |& @' i* S# L9 \( V
, u; W" f6 x2 C. w6 l) V7 s0 ]% G" O5 R5 S; X. j
启动相关函数
" b, O& [! M  Y0 @  在基于 ARM 的启动流程中,我们介绍了各启动相关的函数全部位于 ARM 编译套件的库文件中。IAR 则直接提供了相关函数的源代码,源码使用汇编语言编写!
1 i+ |  ^2 [0 q' h" r4 V' z, X  处理启动和终止的代码位于源文件cstartup.s,cmain.s,cexit.s中,这些文件位于arm\src\lib\arm 或 arm\src\lib\thumb目录中(针对 Cortex-M的 thumb 指令)和位于arm\src\lib\runtime目录中的low_level_init.c。其中,arm\src\lib\arm下面的文件如下图所示:- U8 F1 z0 N2 G& {0 m

7 J1 H! Q/ M9 F
: ~, r/ F% }) R3 g6 Z( |$ n, e/ C; m
关于 Thumb 指令的这里我们暂不说明
. A! I: Q& O3 p, u$ {& n
3 \5 N+ ?' w# M) J3 K1 g1 \6 I前面我们已经分析过,第一个需要调用的函数是__iar_program_start,该函数就位于cstartup.s这个文件中!6 ~9 x$ U' ~* \+ P8 T

9 R  g. X1 _% [- `- K; P
# a3 @5 {# z3 f6 v启动示例分析
8 q( ~' K. y( r" x8 W$ r% b/ x( o5 q* A/ @, C
下面我们以STM32F373CB片子为例,看看其在 IAR 中调试时的汇编代码。直接进调试模式,注意:需要将 设置 -> 调试器 -> Run to main 去掉,如下图:  B# Q2 C3 O  z6 j, f1 P% o

2 C- g. }' ?, x+ g! @& M( M! M
% A0 S. N; W/ n7 Z& b& P% ]- S$ `! x  v2 {% _% t# z
然后 直接进入调试模式,首先看看终端向量表部分:
4 s/ N/ A: s+ C' M% T( I; I( P  c; J+ @7 G/ [  r

/ U0 V- g  P9 u + J. }2 r0 r- D, l

; ^- p' f3 y' i+ I+ ], X3 ~符合前面文章介绍的 Cortex-M/R内核的规定!接着我们看到的就是复位中断的服务函数
7 P7 Q* F! l+ K" k' x- {# d$ z+ x" t* I7 B& y
    0x8003558: 0x04000401     DC32      0x4000401 (67109889)
# D( h) v- J2 p1 ?; |    0x800355c: 0x08000c77     DC32      USER_DLT645ReqAddr
; `0 M& }, I- D* Z% }- e! l: [    0x8003560: 0x00000000     DC32      0x0 (0)
- u, [9 ^2 ]# b  Q+ r$ z! m# V* ^    0x8003564: 0x04a01101     DC32      0x4a01101 (77598977)
3 S5 z! g$ I2 Q+ X2 u% Q    0x8003568: 0x08000ca1     DC32      USER_DLT645ReqUpGrade
1 C* Z* F0 F% F7 |    0x800356c: 0x00000000     DC32      0x0 (0)
3 B- n! [2 d1 \2 Q/ \" R, ?& H        LDR     R0, =SystemInit
# O! L) M4 s& D% l9 G2 V, W& sReset_Handler:
: \* k# x% O- F" @% N    0x8003570: 0x4801         LDR.N     R0, [PC, #0x4]          ; SystemInit
1 l: G0 [. C% T: W8 Q: `        BLX     R07 ?0 j2 ?: g" s* ~+ g( E4 c6 E
    0x8003572: 0x4780         BLX       R0                ; 这里跳转到 SystemInit 这是ST提供的( Z" n2 A( U# Z: o+ v) W
        LDR     R0, =__iar_program_start# `4 X/ p0 x, ^' I7 N
    0x8003574: 0x4801         LDR.N     R0, [PC, #0x4]          ; __iar_program_start2 G; u4 n. A3 ~7 D
        BX      R0
4 l- I) K5 v" U7 C2 b1 P* x    0x8003576: 0x4700         BX        R0                ; 这里跳转到 __iar_program_start
! [; o' ~4 j& J7 B8 g* A2 Y8 P0 ~        SECTION .text:CODE:REORDER(1)! K! K" |2 {) }
    0x8003578: 0x08003195     DC32      SystemInit& n, F% Q6 \- C+ a
        SECTION .text:CODE:REORDER(1)7 w" h3 i# Y/ p/ Z' }' y
    0x800357c: 0x08003581     DC32      __iar_program_start9 e% j( C. j3 B5 Q
__iar_program_start:# [) t; ^9 F3 h
    0x8003580: 0xf3af 0x8000  NOP.W
! k( `/ r5 u) ?6 L6 q8 C    0x8003584: 0xf3af 0x8000  NOP.W3 B: G; W0 ]3 V5 k, m) R
    0x8003588: 0xf7ff 0xffc2  BL        ?main                   ; 0x8003510 重点就在这个函数,
* _5 b, F$ N7 E+ m    0x800358c: 0x11111111     DC32      0x11111111 (286331153)! \$ ]* z$ l5 W6 |' S5 T& x. ^
    0x8003590: 0x00001111     DC32      0x1111 (4369)  G% d' |9 v# j+ n% f
    0x8003594: 0x90           DC8       144                     ; '.'. K+ ], [/ o9 R0 `1 i4 [; \+ B
    0x8003595: 0x00           DC8       0                       ; '.'
; ]% [0 A; S* q, X8 C8 m    0x8003596: 0x00           DC8       0                       ; '.'- J6 d9 t7 b+ F' a' M  M5 e# ^. o' G
    0x8003597: 0x00           DC8       0                       ; '.'/ e( w" O3 m2 Y  f. p* A! K4 y
        B NMI_Handler5 S- b; R" s, Q
    0x8003598: 0xf7ff 0xbf6a  B.W       NMI_Handler             ; 0x8003470% J9 W$ V5 r: K
    ; 后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!
# o4 {' ]2 {4 {4 s. Y% b  f: ~" F: d7 S4 j' y2 b; K& y# z1 W0 b
0 {4 i! N+ }, Q. I' `  v
从上面的汇编代码可以看出,__iar_program_start 跳转到了一个叫做?main的符号处,代码如下:
  ^% c# r  [. R4 i$ f
$ ?# A' R# j: `( K9 D    0x80034c8: 0xb510         PUSH      {R4, LR}
% Q4 l, Q& h9 i/ l% J    0x80034ca: 0x4907         LDR.N     R1, [PC, #0x1c]         ; 0x8 (8), }: q3 }; q# l8 z- W
    0x80034cc: 0x4479         ADD       R1, R1, PC2 Z: Y6 Q$ C% f1 R% S, L! P
    0x80034ce: 0x3118         ADDS      R1, R1, #24             ; 0x18
8 y( g- {' ~( y* A) ~6 n    0x80034d0: 0x4c06         LDR.N     R4, [PC, #0x18]         ; 0x24 (36)' `+ c2 l+ r. p  Y
    0x80034d2: 0x447c         ADD       R4, R4, PC
, V; k* f* s5 L" u$ l; a  \    0x80034d4: 0x3416         ADDS      R4, R4, #22             ; 0x16
$ C+ Z/ |- x: T& ]& b    0x80034d6: 0xe004         B.N       0x80034e2) m7 z! O1 X. h$ o% I2 z# Y
    0x80034d8: 0x680a         LDR       R2, [R1]
, }% h3 l' A% l& ^7 ~( Y    0x80034da: 0x1d08         ADDS      R0, R1, #4/ m; ~7 G0 Z/ O. y" h1 |9 T
    0x80034dc: 0x4411         ADD       R1, R1, R21 }  Q: {, i& `% q
    0x80034de: 0x4788         BLX       R1$ R) a: z. A/ P4 l. K5 Q
    0x80034e0: 0x4601         MOV       R1, R06 O1 A1 ?4 }3 `0 I% K
    0x80034e2: 0x42a1         CMP       R1, R4
( M6 ^# ?4 t$ a& ]6 `: g    0x80034e4: 0xd1f8         BNE.N     0x80034d8& M! l! k6 q8 M+ r/ h8 q. l3 v
    0x80034e6: 0xbd10         POP       {R4, PC}6 D) X& t3 V; h/ e4 |; g+ g& T4 i
    0x80034e8: 0x00000008     DC32      0x8 (8): M2 k9 X! ?! t4 r- P3 N1 [
    0x80034ec: 0x00000024     DC32      0x24 (36)
% A! v' f( p7 J' w2 V2 d( pRegion$$Table$$Base:
+ \; f1 b- X' N6 K7 T7 r: b8 K1 Z    0x80034f0: 0xffffdc57     DC32      0xffffdc57 (-9129)
! ]5 {/ O3 ]0 i0 H    0x80034f4: 0x0000085c     DC32      0x85c (2140)
$ E  s- Q+ u# E+ J/ H5 C' ~/ g    0x80034f8: 0x20000588     DC32      Uart1Info4 v$ K4 p5 R& d$ @  N
    0x80034fc: 0x00000000     DC32      0x0 (0)
1 z- [. m- p1 `    0x8003500: 0xffffdadf     DC32      0xffffdadf (-9505)
" F! Q  E. a2 s( {' P    0x8003504: 0x000001b8     DC32      0x1b8 (440)
2 d3 j# h4 j5 ~9 q4 [1 N5 N    0x8003508: 0x0000010c     DC32      0x10c (268)
: S" f0 K9 e2 j8 i- v    0x800350c: 0x20000000     DC32      UpGradeCtrl2 A4 d. [, p; ]
?main:( {; ]1 d5 Q$ d1 [6 l
Region$$Table$$Limit:
9 n# L8 j" b! h& F0 Q9 E__cmain:
! I' z. X5 a. b: e8 ~    0x8003510: 0xf000 0xf80d  BL        __low_level_init        ; 0x800352e
& z6 t% I! v1 `+ K5 c8 C$ B# d    0x8003514: 0x2800         CMP       R0, #0
! `3 C  y; f" d; p5 c    0x8003516: 0xd001         BEQ.N     _call_main              ; 0x800351c5 H: O. y8 E7 f$ |) ?; I
    0x8003518: 0xf7ff 0xffd6  BL        __iar_data_init3        ; 0x80034c8
9 s8 I0 a9 \# b& i) g_call_main:; L9 n5 G8 A4 L4 R& b7 L
    0x800351c: 0xf3af 0x8000  NOP.W
$ y1 z/ T/ S9 i    0x8003520: 0x2000         MOVS      R0, #0
" q+ V+ ?( E# ~/ [    0x8003522: 0xf3af 0x8000  NOP.W0 L8 y5 ]6 p8 g# C0 F' B9 F
    0x8003526: 0xf7ff 0xff2b  BL        main                    ; 0x8003380
: \% p0 n4 ]4 x! t6 T  z/ c! [: x_main:
% g! J' f' h* }8 [/ i/ m    0x800352a: 0xf000 0xf802  BL        exit                    ; 0x8003532
1 i+ U. h" B; S7 [8 X__low_level_init:
  T9 v6 }& t/ ^% E6 Q    0x800352e: 0x2001         MOVS      R0, #1
! e* a# S9 \; ~0 {! T1 d    0x8003530: 0x4770         BX        LR
4 G' @1 [. W- r9 Iexit:1 t9 v8 ~& y" j/ _
    0x8003532: 0xf000 0xb801  B.W       _exit                   ; 0x8003538  C2 j) S! q2 a+ W) \: v
    0x8003536: 0x0000         MOVS      R0, R0
# ^" s% s9 k: x_exit:
9 o" h0 l: `; K9 F% V* f2 P    0x8003538: 0x4607         MOV       R7, R0
9 P3 S9 G/ U9 v* E    0x800353a: 0x4638         MOV       R0, R7
: A4 q6 _/ G# S) S6 H8 X    0x800353c: 0xf000 0xf802  BL        __exit                  ; 0x8003544
9 o  u/ `0 A! `  w6 v( Y& H2 m    0x8003540: 0xe7fb         B.N       0x800353a
1 [, i" A& k; x5 r2 e# n0 c6 {0 K- w    0x8003542: 0x0000         MOVS      R0, R0& V& }' e  c9 I$ ]
__exit:
7 }5 K8 Z$ B' C9 v, _    0x8003544: 0xb580         PUSH      {R7, LR}1 c$ }% h# u. T& Z
    0x8003546: 0xf3af 0x8000  NOP.W% S: f4 Y  _7 r
    0x800354a: 0x4a02         LDR.N     R2, [PC, #0x8]          ; 0x20026 (131110)$ K% w: S) Z7 d0 [) d2 u5 }$ h. t
    0x800354c: 0x0011         MOVS      R1, R2# u& a$ p" }# `6 D& v, U# {8 ]4 b4 q
    0x800354e: 0x2018         MOVS      R0, #24                 ; 0x185 V5 V& {* z; N- j' H7 O
    0x8003550: 0xbeab         BKPT      #0xab. B( e6 Q, M' H. _' A3 B
    0x8003552: 0xe7fb         B.N       0x800354c+ V  W$ w1 P& I0 I
    0x8003554: 0x00020026     DC32      0x20026 (131110)8 R4 t5 s# m) m4 l2 x1 ^
; 后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!后面的省略!2 {  l" z  c# ]( o$ ^7 A

* ?, H6 C* u- c4 f/ `! u2 A4 a: [, ]7 D

4 Z. r; X9 S2 d+ s/ H0 D5 B5 \. v; m5 V( A3 ]% K
  • TA的每日心情
    慵懒
    2020-6-13 15:46
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2020-9-25 16:35 | 只看该作者
    Cortex-M/R 内核启动流程之退出阶段
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-24 20:47 , Processed in 0.187500 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表