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

Cortex-M/R 内核启动过程 / 程序启动流程之启动实例分析

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x

- d4 G0 i2 M: ~3 t% u  U* p启动实例分析- B+ y2 j5 ]; C9 H
  下面我们以STM32F407VG片子为例,看看其调试时的汇编代码(Keil5中)。直接进调试模式,注意:最好将汇编窗口右键改为assembly mode。
1 n( s4 W) W6 i2 B+ T* [, K% z2 T
6 C: b$ Z2 f* N
6 P$ q8 @6 ^' K2 N2 b首先看看定义的中断向量表部分,如下图:
: H- a$ W2 ?! v1 A
9 M3 z  `5 R0 ?" H
2 U$ ]4 U) g1 h/ l  ?( E, C! H
- f, F9 Q$ z* l8 [! q) f其中,SystemInit为 ST 提供的时钟初始化函数(如果使用了外部RAM,可能还包含外部RAM的配置)。接着,就会有如下汇编代码(具体看里面的注释即可):
/ E; M" C. e: x) E' ?# Q  m" e# w. X! t
  • 0x08000180 0243      DCW           0x0243       ; 小端模式,地址:0x08000243
  • 0x08000182 0800      DCW           0x0800
  • 0x08000184 0243      DCW           0x0243       ; 小端模式,地址:0x08000243
  • 0x08000186 0800      DCW           0x0800
  • ; 从此往上即为中断向量表,与开发环境的启动文件中的中断向量表相对应,32位地址,小端模式
  • ; 下面就是上文介绍的启动流程:
  •                  __main:
  • 0x08000188 F000F802  BL.W          __scatterload (0x08000190)       ; 负责把RW/RO输出段从装载域地址复制到运行域地址,并完成了ZI运行域的初始化工作。
  • 0x0800018C F000F83C  BL.W          __rt_entry (0x08000208)          ; 负责初始化堆、栈,完成C库函数的初始化。其会调用一系列初始化函数,最后自动跳转向main()函数。
  • ; 执行完后,R10和R11就被赋给成了下面两个值,Map文件中的symbol:
  • ;       Region$$Table$$Base                      0x08000898   Number         0  anon$$obj.o(Region$$Table)
  • ;       Region$$Table$$Limit                     0x080008b8   Number         0  anon$$obj.o(Region$$Table)
  • ; !!!-----------注意:以下注释中括号中的数据为我在调试时的值,自行调试时值可能有变化-----------!!!
  • ; !!!-----------注意:以下注释中非括号中的数据一般为左侧地址或者立即数-----------!!!
  •                  __scatterload:
  • 0x08000190 A00A      ADR           r0,{pc}+0x2C     ; 将基于PC相对偏移的地址值(0x080001BC)读取到寄存器r0中。
  • 0x08000192 E8900C00  LDM           r0,{r10-r11}     ; 将R0对应地址存放的的2个字copy到R10~R11中。即:r10 = 0x000006DC; r11 = 0x000006FC
  • 0x08000196 4482      ADD           r10,r10,r0       ; r10 = r10 + r0 = 0x000006DC + 0x080001BC = 0x08000898
  • 0x08000198 4483      ADD           r11,r11,r0       ; r11 = r11 + r0 = 0x000006FC + 0x080001BC = 0x080008B8
  • 0x0800019A F1AA0701  SUB           r7,r10,#0x01     ; r7 = r10 - 0x01 = 0x08000898 - 0x01 = 0x08000897
  •                  __scatterload_null:
  • 0x0800019E 45DA      CMP           r10,r11          ; 比较r10和r11。实际做r10-r11操作,根据结果修改CPSR中条件标志位的值
  • 0x080001A0 D101      BNE           0x080001A6       ; Z 标志位不等于零时, 跳转到0x080001A6
  • 0x080001A2 F000F831  BL.W          __rt_entry (0x08000208)  ; 最后一步:在执行完__scatterload_copy和__scatterload_zeroinit后,r10 == r11 ,上面的跳转不成立,执行该句
  • 0x080001A6 F2AF0E09  ADR.W         lr,{pc}-0x07     ; 将基于PC相对偏移的地址值(0x0800019F)读取到寄存器lr中。lr = 0x0800019F
  • 0x080001AA E8BA000F  LDM           r10!,{r0-r3}     ; 将R10对应地址存放的的4个双字copy到R0~R3中,!表示执行语句后将地址赋值给r10。r10 = r10 + 4*4 = 0x08000898 + 0x10 = 0x080008A8.
  •                                                     ;       R0:表示的是程序加载视图的RW区的起始地址(0x080008B8)
  •                                                     ;       R1:要复制到的运行域地址(RAM中0x20000000)
  •                                                     ;       R2:要复制的RW数据的个数(0x00000020)
  •                                                     ;       R3:是__scatterload_copy函数的起始地址0x080001C4
  • 0x080001AE F0130F01  TST           r3,#0x01         ;
  • 0x080001B2 BF18      IT            NE
  • 0x080001B4 1AFB      SUBNE         r3,r7,r3
  • 0x080001B6 F0430301  ORR           r3,r3,#0x01
  • 0x080001BA 4718      BX            r3               ; 跳转到r3,也就是__scatterload_copy函数,开始复制数据
  • 0x080001BC 06DC      DCW           0x06DC
  • 0x080001BE 0000      DCW           0x0000
  • 0x080001C0 06FC      DCW           0x06FC
  • 0x080001C2 0000      DCW           0x0000
  •                  __scatterload_copy:                ; 该函数负责将镜像中的RW数据复制到芯片的ARM
  • 0x080001C4 3A10      SUBS          r2,r2,#0x10      ; 循环:R2=R2-0x10,SUBS中S表示把进位结果写入CPSR。
  • 0x080001C6 BF24      ITT           CS
  • 0x080001C8 C878      LDMCS         r0!,{r3-r6}
  • 0x080001CA C178      STMCS         r1!,{r3-r6}
  • 0x080001CC D8FA      BHI           __scatterload_copy (0x080001C4)  ; 循环:条件成立跳转到回去
  • 0x080001CE 0752      LSLS          r2,r2,#29
  • 0x080001D0 BF24      ITT           CS
  • 0x080001D2 C830      LDMCS         r0!,{r4-r5}
  • 0x080001D4 C130      STMCS         r1!,{r4-r5}
  • 0x080001D6 BF44      ITT           MI
  • 0x080001D8 6804      LDRMI         r4,[r0,#0x00]
  • 0x080001DA 600C      STRMI         r4,[r1,#0x00]
  • 0x080001DC 4770      BX            lr               ; 这里返回到lr = 0x0800019F,即在此调用__scatterload_null。会继续将R10对应地址存放的的4个双字copy到R0~R3中,但是,此时的R10由于之前的一次调用,其值已经增加
  •                                                     ;       R0:是程序加载视图的RW区的起始地址(0x080008D8 = 0x080008B8 + 0x20 上面执行后面的部分)
  •                                                     ;       R1:是要输出的执行视图的RW区的地址(RAM中 0x20000020)
  •                                                     ;       R2:要复制的RW数据的个数(0x00000660)
  •                                                     ;       R3:是__scatterload_zeroinit函数的起始地址0x080001E0
  •                                                     ;       接下来就会跳转到__scatterload_zeroinit
  • 0x080001DE 0000      MOVS          r0,r0
  •                  __scatterload_zeroinit:
  • 0x080001E0 2300      MOVS          r3,#0x00
  • 0x080001E2 2400      MOVS          r4,#0x00
  • 0x080001E4 2500      MOVS          r5,#0x00
  • 0x080001E6 2600      MOVS          r6,#0x00
  • 0x080001E8 3A10      SUBS          r2,r2,#0x10      ; 循环:
  • 0x080001EA BF28      IT            CS
  • 0x080001EC C178      STMCS         r1!,{r3-r6}
  • 0x080001EE D8FB      BHI           0x080001E8       ; 循环:条件成立跳转到回去
  • 0x080001F0 0752      LSLS          r2,r2,#29
  • 0x080001F2 BF28      IT            CS
  • 0x080001F4 C130      STMCS         r1!,{r4-r5}
  • 0x080001F6 BF48      IT            MI
  • 0x080001F8 600B      STRMI         r3,[r1,#0x00]
  • 0x080001FA 4770      BX            lr               ; 这里返回到lr = 0x0800019F,即在此调用__scatterload_null。这次回去后r10 == r11.回去后会跳转到__rt_entry
  •                  __rt_lib_init:
  • 0x080001FC B51F      PUSH          {r0-r4,lr}
  •                  __rt_lib_init_fp_1:
  • 0x080001FE F000FB45  BL.W          _fp_init (0x0800088C)
  •                  __rt_lib_init_alloca_1:
  • 0x08000202 BD1F      POP           {r0-r4,pc}
  •                  __rt_lib_shutdown:
  • 0x08000204 B510      PUSH          {r4,lr}
  •                  __rt_lib_shutdown_cpp_1:
  • 0x08000206 BD10      POP           {r4,pc}
  •                  __rt_entry:                        ; 在执行完__scatterload后,会紧接着执行该函数
  • 0x08000208 F000F831  BL.W          __user_setup_stackheap (0x0800026E)  ; 设置堆栈的函数,该函数中会调用由用户实现的__user_initial_stackheap函数,如第二节的启动文件中最后的代码即为用户实现的堆栈初始化该函数
  • 0x0800020C 4611      MOV           r1,r2
  •                  __rt_entry_li:
  • 0x0800020E F7FFFFF5  BL.W          __rt_lib_init (0x080001FC)   ; 初始化C库
  •                  __rt_entry_main:
  • 0x08000212 F000FA3B  BL.W          main (0x0800068C)            ; 跳转到C的main函数
  • 0x08000216 F000F84F  BL.W          exit (0x080002B8)            ; 如果main返回,则执行该函数,结束程序运行
  •                  __rt_exit:
  • 0x0800021A B403      PUSH          {r0-r1}
  •                  __rt_exit_ls:
  • 0x0800021C F7FFFFF2  BL.W          __rt_lib_shutdown (0x08000204)
  •                  __rt_exit_exit:
  • 0x08000220 BC03      POP           {r0-r1}
  • 0x08000222 F000F857  BL.W          _sys_exit (0x080002D4)
  • 0x08000226 0000      MOVS          r0,r0
  • 0x08000226 0000      MOVS          r0,r0
  • ; 此处往下,就是定义的各个中断向量的实现代码,第一个就是复位中断,程序就是从复位中断开始执行的
  •                  Reset_Handler:
  • 0x08000228 4809      LDR           r0,[pc,#36]  ; @0x08000250
  • 0x0800022A 4780      BLX           r0
  • 0x0800022C 4809      LDR           r0,[pc,#36]  ; @0x08000254
  • 0x0800022E 4700      BX            r0
  •                  NMI_Handler:
  • 0x08000230 E7FE      B             NMI_Handler (0x08000230)
  •                  HardFault_Handler:
  • 0x08000232 E7FE      B             HardFault_Handler (0x08000232)
  •                  MemManage_Handler:
  • 0x08000234 E7FE      B             MemManage_Handler (0x08000234)
  •                  BusFault_Handler:
  • 0x08000236 E7FE      B             BusFault_Handler (0x08000236)
  •                  UsageFault_Handler:
  • 0x08000238 E7FE      B             UsageFault_Handler (0x08000238)
  •                  SVC_Handler:
  • 0x0800023A E7FE      B             SVC_Handler (0x0800023A)
  •                  DebugMon_Handler:
  • 0x0800023C E7FE      B             DebugMon_Handler (0x0800023C)
  •                  PendSV_Handler:
  • 0x0800023E E7FE      B             PendSV_Handler (0x0800023E)
  •                  SysTick_Handler:
  • 0x08000240 E7FE      B             SysTick_Handler (0x08000240)
  •                  Default_Handler:
  • 0x08000242 E7FE      B             Default_Handler (0x08000242)
  •                  __user_initial_stackheap:
  • 0x08000244 4804      LDR           r0,[pc,#16]  ; @0x08000258
  • 0x08000246 4905      LDR           r1,[pc,#20]  ; @0x0800025C
  • 0x08000248 4A05      LDR           r2,[pc,#20]  ; @0x08000260
  • 0x0800024A 4B06      LDR           r3,[pc,#24]  ; @0x08000264
  • 0x0800024C 4770      BX            lr
  • 0x0800024E 0000      DCW           0x0000
  • 0x08000250 0621      DCW           0x0621
  • 0x08000252 0800      DCW           0x0800
  • 0x08000254 0189      DCW           0x0189
  • 0x08000256 0800      DCW           0x0800
  • 0x08000258 0080      DCW           0x0080
  • 0x0800025A 2000      DCW           0x2000
  • 0x0800025C 0680      DCW           0x0680
  • 0x0800025E 2000      DCW           0x2000
  • 0x08000260 0280      DCW           0x0280
  • 0x08000262 2000      DCW           0x2000
  • 0x08000264 0280      DCW           0x0280
  • 0x08000266 2000      DCW           0x2000
  •                  __use_two_region_memory:
  • 0x08000268 4770      BX            lr
  •                  __rt_heap_escrow$2region:
  • 0x0800026A 4770      BX            lr
  •                  __rt_heap_expand$2region:
  • 0x0800026C 4770      BX            lr
  •                  __user_setup_stackheap:
  • 0x0800026E 4675      MOV           r5,lr
  • 0x08000270 F000F82C  BL.W          __user_libspace (0x080002CC)
  • 0x08000274 46AE      MOV           lr,r5
  • 0x08000276 0005      MOVS          r5,r0
  • 0x08000278 4669      MOV           r1,sp
  • 0x0800027A 4653      MOV           r3,r10
  • 0x0800027C F0200007  BIC           r0,r0,#0x07
  • 0x08000280 4685      MOV           sp,r0
  • 0x08000282 B018      ADD           sp,sp,#0x60
  • 0x08000284 B520      PUSH          {r5,lr}
  • 0x08000286 F7FFFFDD  BL.W          __user_initial_stackheap (0x08000244)
  • 0x0800028A E8BD4020  POP           {r5,lr}
  • 0x0800028E F04F0600  MOV           r6,#0x00
  • 0x08000292 F04F0700  MOV           r7,#0x00
  • 0x08000296 F04F0800  MOV           r8,#0x00
  • 0x0800029A F04F0B00  MOV           r11,#0x00
  • 0x0800029E F0210107  BIC           r1,r1,#0x07
  • 0x080002A2 46AC      MOV           r12,r5
  • 0x080002A4 E8AC09C0  STM           r12!,{r6-r8,r11}
  • 0x080002A8 E8AC09C0  STM           r12!,{r6-r8,r11}
  • 0x080002AC E8AC09C0  STM           r12!,{r6-r8,r11}
  • 0x080002B0 E8AC09C0  STM           r12!,{r6-r8,r11}
  • 0x080002B4 468D      MOV           sp,r1
  • 0x080002B6 4770      BX            lr
  •                  exit:
  • 0x080002B8 B510      PUSH          {r4,lr}
  • 0x080002BA 4604      MOV           r4,r0
  • 0x080002BC F3AF8000  NOP.W
  • 0x080002C0 4620      MOV           r0,r4
  • 0x080002C2 E8BD4010  POP           {r4,lr}
  • 0x080002C6 F7FFBFA8  B.W           __rt_exit (0x0800021A)
  • 0x080002CA 0000      MOVS          r0,r0
  •                  __user_libspace:
  • 0x080002CC 4800      LDR           r0,[pc,#0]  ; @0x080002D0
  • 0x080002CE 4770      BX            lr
  • 0x080002D0 0020      DCW           0x0020
  • 0x080002D2 2000      DCW           0x2000
  •                  _sys_exit:
  • 0x080002D4 4901      LDR           r1,[pc,#4]  ; @0x080002DC
  • 0x080002D6 2018      MOVS          r0,#0x18
  • 0x080002D8 BEAB      BKPT          0xAB
  • 0x080002DA E7FE      B             0x080002DA
  • 0x080002DC 0026      DCW           0x0026
  • 0x080002DE 0002      DCW           0x0002
    - w7 z, F3 y2 L5 D& @) N! L

- Z# U2 ]" k: L& [' k' V
/ X# Z' B9 c' _8 k
7 M5 D( S8 b1 |' y; t
' l7 o; Y& L# ?( u, ~6 T- f
! {0 V5 ^& E( G6 {9 r' T

该用户从未签到

2#
发表于 2020-11-23 13:14 | 只看该作者
Cortex-M/R 内核启动过程 / 程序启动流程之启动实例分析
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

EDA365公众号

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

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

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

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

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