> 技术文档 > ARM单片机启动流程(一)(详细解析)

ARM单片机启动流程(一)(详细解析)


文章目录

  • 一、ARM单片机启动流程
    • 1.1 地址的映射
    • 1.2内存分布
    • 1.3 单片机复位以后主要的启动流程
      • 1.3.2 单片机的几种启动模式
      • 1.3.3 以Main Flash启动方式进行代码分析
        • 1.3.3.1 初始化向量表
        • 1.3.3.2 汇编指令的运行

一、ARM单片机启动流程

1.1 地址的映射

在学习启动流程之前需要明确地址之间的映射关系

逻辑地址​:程序直接使用的地址,依赖分段机制(如x86架构);

线性地址/虚拟地址​:分段后的连续地址,作为分页输入;

物理地址​:最终硬件执行访问的位置;

逻辑地址=虚拟地址?”​

  • ​:现代系统中因分段退化,二者常等价。
  • ​:传统分段架构(如实模式DOS)中,逻辑地址需经段转换才生成线性地址(虚拟地址)

    逻辑地址是程序视角的起点,​线性地址/虚拟地址是操作系统的连续抽象,​物理地址是硬件的终点。

转换过程由CPU和MMU(​内存管理单元)硬件协作完成,对应用程序透明

对于我们的理解启动流程来说,我们只关心逻辑地址和最终的物理地址,逻辑地址到物理地址有一个映射关系,这个映射关系是由硬件自动完成的,对于我们写程序来说不需要深入追究,如果必须追究可以通过微机原理深入理解。

ARM单片机启动流程(一)(详细解析)

ARM单片机启动流程(一)(详细解析)

1.2内存分布

单片机通过地址来访问寄存器、RAM、FLASH,ARM寻址范围4GB,分为多个块:
ARM单片机启动流程(一)(详细解析)
一共4G个字节

CODE范围是:0x0000 0000~0x1FFF FFFF,共计512M,​非易失、掉电保存。

ARM单片机启动流程(一)(详细解析)
ARM单片机启动流程(一)(详细解析)
SRAM:范围是0x2000 0000~0x3FFF FFFF,共计512M。

ARM单片机启动流程(一)(详细解析)

片上外设范围是0x4000 0000~0x5FFF FFFF,共计512M,包含定时器、串口、IO口一些寄存器。

EXMC范围是0x6000 0000~0x9FFF FFFF共计1GB,外挂的一些设备。

Coretex-M4内核寄存器范围是0xE000 0000~0xFFFF FFFF共计512M,如:NVIC、中断控制、滴答定时器。

ARM单片机启动流程(一)(详细解析)

截止到这里我们只需要粗浅的认识,在单片机内部存储器映射分为了以上几个部分。

1.3 单片机复位以后主要的启动流程

复位以后主要先执行的就是这段程序,

Reset_Handler PROC EXPORT Reset_Handler  [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP

“_ _ main”:是Keil库函数里面的一个封装好的,看不到源代码,最主要的是在这个函数里面会调用我们自己写的main函数,因此我们的主函数只能是main函数,如果是改个名字就会编译报错。

ARM单片机启动流程(一)(详细解析)

整体的框架是以上这个流程思路,整理出来就是以下这几句话。

从Reset_Handler开始

然后执行到_ _ main ,接着进行一些初始化堆栈的(如全局变量初始化等),

最后执行程序到main(我们写的),然后在进行相关执行。

1.3.2 单片机的几种启动模式

经过整体框架的分析,我们还不知道具体的细节,也就是访问地址的操作是什么,或者说是从地址层面单片机先干什么,在干什么,这都是有严格的要求的。

ARM单片机启动流程(一)(详细解析)

ARM单片机启动流程(一)(详细解析)

通过上图可以看出,主要是根据Boot管脚的配置,来确定是那种方式,主FLASH存储器(开始于0x0800 0000的原始存储空间)或系统存储器(MCU厂商预置的bootloader开始于0x1FFF F000的原始存储空间)被映射到引导存储空间(起始于0x0000 0000)。

通俗一点将就是通过配置Boot1和Boot0的引脚,来确定Aliased to Main Flash or Boot loader将0x0000 0000映射到哪里(可能是Bootloader模式内置SRAM启动(调试模式)​主闪存启动(正常工作模式)​)。

直接结果就是:
CPU都是从0地址开始访问的,根据被引导到的地方,有可能直接跳转到Main Flash 0x0800 0000的原始存储空间;也有可能跳转到MCU厂商预置的bootloader开始于0x1FFF F000的原始存储空间。

在这里多描述一点,就是为了和前面1.1章节所引入产生联系。

在嵌入式系统中,CPU 上电后从逻辑地址 0x00000000 开始执行指令,但该地址实际映射的物理地址取决于芯片的启动模式配置,机制本质上是存储器重映射(Memory Remapping)​的结果。

  1. 地址映射的本质
    • CPU 上电后固定从逻辑地址 0x00000000 取第一条指令(栈指针和复位向量)。
    • 物理存储介质​(如 Flash、SRAM 或 BootROM)的原始地址被硬件映射到 0x00000000,形成“别名区”(Alias Region)。
    • 例如:
      • 主闪存(Main Flash)​​:物理地址 0x08000000 → 映射到 0x00000000
      • 系统存储器(BootROM)​​:物理地址 0x1FFF0000 → 映射到 0x00000000(STM32 中为 System Memory)。
  2. CPU 视角的执行过程
    • CPU 始终认为自己从 0x00000000 执行代码,但实际访问的是映射后的物理存储单元。
    • 关键区别​:
      • 若从主闪存启动 → 0x00000000等同于0x08000000(访问 Flash 的起始位置)。
      • 若从 BootROM 启动 → 0x00000000等同于0x1FFF0000(执行厂商预置的 Bootloader)。
  3. 逻辑地址与物理地址的辩证关系
    • 逻辑地址的抽象性
      • 0x00000000 是 CPU 的固定入口地址,属于逻辑地址空间,由硬件自动重定向到物理存储设备。
      • 物理地址​(如 0x08000000)是存储介质在总线上的实际位置,两者通过重映射建立关联
    • ​**是否“等同于”物理地址?
      • ​:在启动阶段,访问 0x00000000 即访问映射后的物理地址(如 0x08000000),​效果相同
      • ​:逻辑地址本身无存储能力,仅作为访问物理介质的桥梁;物理地址是存储介质的真实位置。
  4. 重映射的硬件实现原理
    • ​别名区的设计
      • 芯片内部将 0x00000000~0x000FFFFF(本文以STM32为例)定义为启动空间别名区,通过总线开关动态连接到目标存储区。
      • 例如:
        • 当 BOOT0=0 时,别名区指向 Flash (0x08000000);
        • 当 BOOT0=1 时,别名区指向 BootROM (0x1FFF0000)
    • 地址转换的透明性
      • CPU 无需感知重映射过程,由内存控制器(如 ARM 的 AHB 总线)自动完成地址转换。

总的来说:

  1. ​“执行 0x00000000 等于执行 0x08000000”​
    • 仅在主闪存启动模式下成立​(此时两者指向同一物理存储单元)。
  2. 逻辑地址与物理地址的关系
    • 0x00000000 是逻辑入口地址,其内容由映射的物理存储介质提供
    • 物理地址(如 0x08000000)是存储介质的真实位置,两者通过重映射绑定。

通过上图可以看出,在引导存储空间有多重启动方式,那我们在这里不妨多深入一下,为什么会有几种启动模式呐,原因如下

单片机需要不同的启动模式,主要是为了满足开发调试、程序更新、系统恢复以及资源适配等多场景需求。这些模式通过硬件引脚配置实现,核心原理是将不同物理存储区域映射到固定的启动地址(0x00000000)​,使CPU能按需选择执行入口。

1. 功能隔离与系统恢复

  • 系统存储器启动(Bootloader模式)​
    • 作用​:当用户程序损坏或需更新时,通过内置的只读Bootloader​(存储在系统存储器,地址 0x1FFF0000~0x1FFF7A0F)实现程序恢复。
    • 典型场景​:
      • 串口下载程序(ISP):通过Bootloader将新代码烧录至主闪存。
      • 修复锁死的Flash:当调试接口被误配置为普通IO时,通过此模式解锁并重烧程序。
    • 硬件配置​:BOOT0=1, BOOT1=0

2. 开发调试优化

  • 内置SRAM启动(调试模式)​
    • 作用​:将程序加载到SRAM(地址 0x20000000)运行,避免频繁擦写Flash,​延长Flash寿命并加速调试
    • 优势​:
      • 修改代码后无需全盘擦除Flash,缩短编译-调试周期。
      • 避免Flash写入延迟,实时测试代码逻辑。
    • 硬件配置​:BOOT0=1, BOOT1=1
      注意​:SRAM掉电后数据丢失,仅用于临时调试 。

3. 适配不同硬件资源

  • 主闪存启动(正常工作模式)​
    • 作用​:将用户程序存储在主闪存(地址 0x08000000),映射至 0x00000000,作为默认执行入口
    • 优势​:
      • 非易失性存储:程序掉电不丢失。
      • 支持大容量代码:Flash空间通常远大于SRAM(如STM32F1主闪存可达1MB)。
    • 硬件配置​:BOOT0=0, BOOT1=X

进一步理解设计思想
1、地址重映射的统一性
CPU始终从 0x00000000 取指令,通过硬件动态映射不同存储区,​简化CPU设计并提升灵活性。

2、分层容错体系

  • 主闪存(Main Flash) → 用户程序层;
  • 系统存储器 → 安全恢复层;
  • SRAM → 临时调试层。
    各层隔离,增强系统鲁棒性

3、资源优化

  • 利用SRAM减少Flash损耗(擦写寿命约1万次);
  • 通过Bootloader省去外部烧录器成本

1.3.3 以Main Flash启动方式进行代码分析

在复位后,单片机首先会做两件事:
1、从地址 0x0000,0000 处取出 MSP 的初始值(栈顶地址),用于函数分配内存栈空间。

2、从地址 0x0000,0004 处取出 PC 的初始值,这个值是Reset Handler复位函数的地址,然后从这
个地址开始执行程序。

ARM单片机启动流程(一)(详细解析)

既然我们要详细分析ARM的启动流程,我们就以编译后的汇编代码为基础去分析最底层的执行逻辑。针对汇编的一些指令在使用过程中会进行一些简单说明,我们其实只需要知道是怎么个意义就行,不需要深入的细究,只是让我们从微观层面知道到底是怎么执行,毕竟这些涉及到微机原理。想搞的特别明白还是需要微机原理知识为蓝本进行分析。

为了说明清楚,我将我其中一个工程的汇编语言全部粘贴出来,后面我会逐段的分析。
这里就不过多赘述了。

 __Vectors 0x08000000: 20000428 (.. DCD 536871976 0x08000004: 08000145 E... DCD 134218053 0x08000008: 0800014d M... DCD 134218061 0x0800000c: 0800014f O... DCD 134218063 0x08000010: 08000151 Q... DCD 134218065 0x08000014: 08000153 S... DCD 134218067 0x08000018: 08000155 U... DCD 134218069 0x0800001c: 00000000 .... DCD 0 0x08000020: 00000000 .... DCD 0 0x08000024: 00000000 .... DCD 0 0x08000028: 00000000 .... DCD 0 0x0800002c: 08000157 W... DCD 134218071 0x08000030: 08000159 Y... DCD 134218073 0x08000034: 00000000 .... DCD 0 0x08000038: 0800015b [... DCD 134218075 0x0800003c: 0800015d ]... DCD 134218077 0x08000040: 0800015f _... DCD 134218079 0x08000044: 0800015f _... DCD 134218079 0x08000048: 0800015f _... DCD 134218079 0x0800004c: 0800015f _... DCD 134218079 0x08000050: 0800015f _... DCD 134218079 0x08000054: 0800015f _... DCD 134218079 0x08000058: 0800015f _... DCD 134218079 0x0800005c: 0800015f _... DCD 134218079 0x08000060: 0800015f _... DCD 134218079 0x08000064: 0800015f _... DCD 134218079 0x08000068: 0800015f _... DCD 134218079 0x0800006c: 0800015f _... DCD 134218079 0x08000070: 0800015f _... DCD 134218079 0x08000074: 0800015f _... DCD 134218079 0x08000078: 0800015f _... DCD 134218079 0x0800007c: 0800015f _... DCD 134218079 0x08000080: 0800015f _... DCD 134218079 0x08000084: 0800015f _... DCD 134218079 0x08000088: 0800015f _... DCD 134218079 0x0800008c: 0800015f _... DCD 134218079 0x08000090: 0800015f _... DCD 134218079 0x08000094: 0800015f _... DCD 134218079 0x08000098: 0800015f _... DCD 134218079 0x0800009c: 0800015f _... DCD 134218079 0x080000a0: 0800015f _... DCD 134218079 0x080000a4: 0800015f _... DCD 134218079 0x080000a8: 0800015f _... DCD 134218079 0x080000ac: 0800015f _... DCD 134218079 0x080000b0: 0800015f _... DCD 134218079 0x080000b4: 0800015f _... DCD 134218079 0x080000b8: 0800015f _... DCD 134218079 0x080000bc: 0800015f _... DCD 134218079 0x080000c0: 0800015f _... DCD 134218079 0x080000c4: 0800015f _... DCD 134218079 0x080000c8: 0800015f _... DCD 134218079 0x080000cc: 0800015f _... DCD 134218079 0x080000d0: 0800015f _... DCD 134218079 0x080000d4: 0800015f _... DCD 134218079 0x080000d8: 0800015f _... DCD 134218079 0x080000dc: 0800015f _... DCD 134218079 0x080000e0: 0800015f _... DCD 134218079 0x080000e4: 0800015f _... DCD 134218079 0x080000e8: 0800015f _... DCD 134218079 0x080000ec: 0800015f _... DCD 134218079 0x080000f0: 0800015f _... DCD 134218079 0x080000f4: 0800015f _... DCD 134218079 0x080000f8: 0800015f _... DCD 134218079 0x080000fc: 0800015f _... DCD 134218079 0x08000100: 0800015f _... DCD 134218079 0x08000104: 0800015f _... DCD 134218079 0x08000108: 0800015f _... DCD 134218079 0x0800010c: 0800015f _... DCD 134218079 0x08000110: 0800015f _... DCD 134218079 0x08000114: 0800015f _... DCD 134218079 0x08000118: 0800015f _... DCD 134218079 0x0800011c: 0800015f _... DCD 134218079 0x08000120: 0800015f _... DCD 134218079 0x08000124: 0800015f _... DCD 134218079 0x08000128: 0800015f _... DCD 134218079 0x0800012c: 0800015f _... DCD 134218079 $t .ARM.Collect$$$$00000000 .ARM.Collect$$$$00000001 __Vectors_End __main _main_stk 0x08000130: f8dfd00c .... LDR sp,__lit__00000000 ; [0x8000140] = 0x20000428 .ARM.Collect$$$$00000004 _main_scatterload 0x08000134: f000f818 .... BL __scatterload ; 0x8000168 .ARM.Collect$$$$00000008 .ARM.Collect$$$$0000000A .ARM.Collect$$$$0000000B __main_after_scatterload _main_clock _main_cpp_init _main_init 0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x800044b 0x0800013a: 4700 .G BX r0 $d 0x0800013c: 0800044b K... DCD 134218827 .ARM.Collect$$$$00002712 __lit__00000000 .ARM.Collect$$$$0000000D .ARM.Collect$$$$0000000F __rt_final_cpp __rt_final_exit 0x08000140: 20000428 (.. DCD 536871976 $t .text $v0 Reset_Handler 0x08000144: 4806 .H LDR r0,[pc,#24] ; [0x8000160] = 0x8000269 0x08000146: 4780 .G BLX r0 0x08000148: 4806 .H LDR r0,[pc,#24] ; [0x8000164] = 0x8000131 0x0800014a: 4700 .G BX r0 NMI_Handler 0x0800014c: e7fe .. B NMI_Handler ; 0x800014c HardFault_Handler 0x0800014e: e7fe .. B HardFault_Handler ; 0x800014e MemManage_Handler 0x08000150: e7fe .. B MemManage_Handler ; 0x8000150 BusFault_Handler 0x08000152: e7fe .. B BusFault_Handler ; 0x8000152 UsageFault_Handler 0x08000154: e7fe .. B UsageFault_Handler ; 0x8000154 SVC_Handler 0x08000156: e7fe .. B SVC_Handler ; 0x8000156 DebugMon_Handler 0x08000158: e7fe .. B DebugMon_Handler ; 0x8000158 PendSV_Handler 0x0800015a: e7fe .. B PendSV_Handler ; 0x800015a SysTick_Handler 0x0800015c: e7fe .. B SysTick_Handler ; 0x800015c ADC0_1_IRQHandler ADC2_IRQHandler CAN0_EWMC_IRQHandler CAN0_RX1_IRQHandler DMA0_Channel0_IRQHandler DMA0_Channel1_IRQHandler DMA0_Channel2_IRQHandler DMA0_Channel3_IRQHandler DMA0_Channel4_IRQHandler DMA0_Channel5_IRQHandler DMA0_Channel6_IRQHandler DMA1_Channel0_IRQHandler DMA1_Channel1_IRQHandler DMA1_Channel2_IRQHandler DMA1_Channel3_4_IRQHandler EXMC_IRQHandler EXTI0_IRQHandler EXTI10_15_IRQHandler EXTI1_IRQHandler EXTI2_IRQHandler EXTI3_IRQHandler EXTI4_IRQHandler EXTI5_9_IRQHandler FMC_IRQHandler I2C0_ER_IRQHandler I2C0_EV_IRQHandler I2C1_ER_IRQHandler I2C1_EV_IRQHandler LVD_IRQHandler RCU_CTC_IRQHandler RTC_Alarm_IRQHandler RTC_IRQHandler SDIO_IRQHandler SPI0_IRQHandler SPI1_IRQHandler SPI2_IRQHandler TAMPER_IRQHandler TIMER0_BRK_IRQHandler TIMER0_Channel_IRQHandler TIMER0_TRG_CMT_IRQHandler TIMER0_UP_IRQHandler TIMER1_IRQHandler TIMER2_IRQHandler TIMER3_IRQHandler TIMER4_IRQHandler TIMER5_IRQHandler TIMER6_IRQHandler TIMER7_BRK_IRQHandler TIMER7_Channel_IRQHandler TIMER7_TRG_CMT_IRQHandler TIMER7_UP_IRQHandler UART3_IRQHandler UART4_IRQHandler USART0_IRQHandler USART1_IRQHandler USART2_IRQHandler USBD_HP_CAN0_TX_IRQHandler USBD_LP_CAN0_RX0_IRQHandler USBD_WKUP_IRQHandler WWDGT_IRQHandler 0x0800015e: e7fe .. B ADC0_1_IRQHandler ; 0x800015e $d 0x08000160: 08000269 i... DCD 134218345 0x08000164: 08000131 1... DCD 134218033 $t .text __scatterload __scatterload_rt2 0x08000168: 4c06 .L LDR r4,[pc,#24] ; [0x8000184] = 0x8000730 0x0800016a: 4d07 .M LDR r5,[pc,#28] ; [0x8000188] = 0x8000750 0x0800016c: e006 .. B 0x800017c ; __scatterload + 20 0x0800016e: 68e0 .h LDR r0,[r4,#0xc] 0x08000170: f0400301 @... ORR r3,r0,#1 0x08000174: e8940007 .... LDM r4,{r0-r2} 0x08000178: 4798 .G BLX r3 0x0800017a: 3410 .4 ADDS r4,r4,#0x10 0x0800017c: 42ac .B CMP r4,r5 0x0800017e: d3f6 .. BCC 0x800016e ; __scatterload + 6 0x08000180: f7ffffda .... BL __main_after_scatterload ; 0x8000138 $d 0x08000184: 08000730 0... DCD 134219568 0x08000188: 08000750 P... DCD 134219600 $t i.DelayInit DelayInit 0x0800018c: 480c .H LDR r0,[pc,#48] ; [0x80001c0] = 0xe000edfc 0x0800018e: 6800 .h LDR r0,[r0,#0] 0x08000190: f0207080 ..p BIC r0,r0,#0x1000000 0x08000194: 490a .I LDR r1,[pc,#40] ; [0x80001c0] = 0xe000edfc 0x08000196: 6008 .` STR r0,[r1,#0] 0x08000198: 4608 .F MOV r0,r1 0x0800019a: 6800 .h LDR r0,[r0,#0] 0x0800019c: f0407080 @..p ORR r0,r0,#0x1000000 0x080001a0: 6008 .` STR r0,[r1,#0] 0x080001a2: 4808 .H LDR r0,[pc,#32] ; [0x80001c4] = 0xe0001000 0x080001a4: 6800 .h LDR r0,[r0,#0] 0x080001a6: f0200001 ... BIC r0,r0,#1 0x080001aa: 4906 .I LDR r1,[pc,#24] ; [0x80001c4] = 0xe0001000 0x080001ac: 6008 .` STR r0,[r1,#0] 0x080001ae: 4608 .F MOV r0,r1 0x080001b0: 6800 .h LDR r0,[r0,#0] 0x080001b2: f0400001 @... ORR r0,r0,#1 0x080001b6: 6008 .` STR r0,[r1,#0] 0x080001b8: 2000 . MOVS r0,#0 0x080001ba: 6048 H` STR r0,[r1,#4] 0x080001bc: 4770 pG BX lr $d 0x080001be: 0000 .. DCW 0 0x080001c0: e000edfc .... DCD 3758157308 0x080001c4: e0001000 .... DCD 3758100480 $t i.DelayNms DelayNms 0x080001c8: b570 p. PUSH {r4-r6,lr} 0x080001ca: 4604 .F MOV r4,r0 0x080001cc: 2500 .% MOVS r5,#0 0x080001ce: e004 .. B 0x80001da ; DelayNms + 18 0x080001d0: f44f707a O.zp MOV r0,#0x3e8 0x080001d4: f000f804 .... BL DelayNus ; 0x80001e0 0x080001d8: 1c6d m. ADDS r5,r5,#1 0x080001da: 42a5 .B CMP r5,r4 0x080001dc: d3f8 .. BCC 0x80001d0 ; DelayNms + 8 0x080001de: bd70 p. POP {r4-r6,pc} i.DelayNus DelayNus 0x080001e0: b570 p. PUSH {r4-r6,lr} 0x080001e2: 4604 .F MOV r4,r0 0x080001e4: 4807 .H LDR r0,[pc,#28] ; [0x8000204] = 0xe0001000 0x080001e6: 6845 Eh LDR r5,[r0,#4] 0x080001e8: 2001 . MOVS r0,#1 0x080001ea: f000f957 ..W. BL rcu_clock_freq_get ; 0x800049c 0x080001ee: 4906 .I LDR r1,[pc,#24] ; [0x8000208] = 0xf4240 0x080001f0: fbb0f0f1 .... UDIV r0,r0,r1 0x080001f4: 4344 DC MULS r4,r0,r4 0x080001f6: bf00 .. NOP  0x080001f8: 4802 .H LDR r0,[pc,#8] ; [0x8000204] = 0xe0001000 0x080001fa: 6840 @h LDR r0,[r0,#4] 0x080001fc: 1b40 @. SUBS r0,r0,r5 0x080001fe: 42a0 .B CMP r0,r4 0x08000200: d3fa .. BCC 0x80001f8 ; DelayNus + 24 0x08000202: bd70 p. POP {r4-r6,pc} $d 0x08000204: e0001000 .... DCD 3758100480 0x08000208: 000f4240 @B.. DCD 1000000 $t i.LedDrvInit LedDrvInit 0x0800020c: b510 .. PUSH {r4,lr} 0x0800020e: 2400 .$ MOVS r4,#0 0x08000210: e024 $. B 0x800025c ; LedDrvInit + 80 0x08000212: eb040144 ..D. ADD r1,r4,r4,LSL #1 0x08000216: 4a13 .J LDR r2,[pc,#76] ; [0x8000264] = 0x20000000 0x08000218: f8320021 2.!. LDRH r0,[r2,r1,LSL #2] 0x0800021c: f000f9ea .... BL rcu_periph_clock_enable ; 0x80005f4 0x08000220: eb040144 ..D. ADD r1,r4,r4,LSL #1 0x08000224: 4a0f .J LDR r2,[pc,#60] ; [0x8000264] = 0x20000000 0x08000226: eb020181 .... ADD r1,r2,r1,LSL #2 0x0800022a: 688b .h LDR r3,[r1,#8] 0x0800022c: eb040144 ..D. ADD r1,r4,r4,LSL #1 0x08000230: eb020181 .... ADD r1,r2,r1,LSL #2 0x08000234: 2202 .\" MOVS r2,#2 0x08000236: 6848 Hh LDR r0,[r1,#4] 0x08000238: 2110 .! MOVS r1,#0x10 0x0800023a: f000f8a8 .... BL gpio_init ; 0x800038e 0x0800023e: eb040244 ..D. ADD r2,r4,r4,LSL #1 0x08000242: 4b08 .K LDR r3,[pc,#32] ; [0x8000264] = 0x20000000 0x08000244: eb030282 .... ADD r2,r3,r2,LSL #2 0x08000248: 6891 .h LDR r1,[r2,#8] 0x0800024a: eb040244 ..D. ADD r2,r4,r4,LSL #1 0x0800024e: eb030282 .... ADD r2,r3,r2,LSL #2 0x08000252: 6850 Ph LDR r0,[r2,#4] 0x08000254: f000f897 .... BL gpio_bit_reset ; 0x8000386 0x08000258: 1c60 `. ADDS r0,r4,#1 0x0800025a: b2c4 .. UXTB r4,r0 0x0800025c: 2c03 ., CMP r4,#3 0x0800025e: d3d8 .. BCC 0x8000212 ; LedDrvInit + 6 0x08000260: bd10 .. POP {r4,pc} $d 0x08000262: 0000 .. DCW 0 0x08000264: 20000000 ... DCD 536870912 $t i.SystemInit SystemInit 0x08000268: b508 .. PUSH {r3,lr} 0x0800026a: 4826 &H LDR r0,[pc,#152] ; [0x8000304] = 0xe000ed88 0x0800026c: 6800 .h LDR r0,[r0,#0] 0x0800026e: f4400070 @.p. ORR r0,r0,#0xf00000 0x08000272: 4924 $I LDR r1,[pc,#144] ; [0x8000304] = 0xe000ed88 0x08000274: 6008 .` STR r0,[r1,#0] 0x08000276: 4824 $H LDR r0,[pc,#144] ; [0x8000308] = 0x40021000 0x08000278: 6800 .h LDR r0,[r0,#0] 0x0800027a: f0400001 @... ORR r0,r0,#1 0x0800027e: 4922 \"I LDR r1,[pc,#136] ; [0x8000308] = 0x40021000 0x08000280: 6008 .` STR r0,[r1,#0] 0x08000282: bf00 .. NOP  0x08000284: 4820 H LDR r0,[pc,#128] ; [0x8000308] = 0x40021000 0x08000286: 6800 .h LDR r0,[r0,#0] 0x08000288: f0000002 .... AND r0,r0,#2 0x0800028c: 2800 .( CMP r0,#0 0x0800028e: d0f9 .. BEQ 0x8000284 ; SystemInit + 28 0x08000290: bf00 .. NOP  0x08000292: 481d .H LDR r0,[pc,#116] ; [0x8000308] = 0x40021000 0x08000294: 6840 @h LDR r0,[r0,#4] 0x08000296: f0400080 @... ORR r0,r0,#0x80 0x0800029a: 491b .I LDR r1,[pc,#108] ; [0x8000308] = 0x40021000 0x0800029c: 6048 H` STR r0,[r1,#4] 0x0800029e: 2000 . MOVS r0,#0 0x080002a0: 9000 .. STR r0,[sp,#0] 0x080002a2: e002 .. B 0x80002aa ; SystemInit + 66 0x080002a4: 9800 .. LDR r0,[sp,#0] 0x080002a6: 1c40 @. ADDS r0,r0,#1 0x080002a8: 9000 .. STR r0,[sp,#0] 0x080002aa: 9800 .. LDR r0,[sp,#0] 0x080002ac: 2850 P( CMP r0,#0x50 0x080002ae: d3f9 .. BCC 0x80002a4 ; SystemInit + 60 0x080002b0: 4815 .H LDR r0,[pc,#84] ; [0x8000308] = 0x40021000 0x080002b2: 6840 @h LDR r0,[r0,#4] 0x080002b4: f0400090 @... ORR r0,r0,#0x90 0x080002b8: 4913 .I LDR r1,[pc,#76] ; [0x8000308] = 0x40021000 0x080002ba: 6048 H` STR r0,[r1,#4] 0x080002bc: 2000 . MOVS r0,#0 0x080002be: 9000 .. STR r0,[sp,#0] 0x080002c0: e002 .. B 0x80002c8 ; SystemInit + 96 0x080002c2: 9800 .. LDR r0,[sp,#0] 0x080002c4: 1c40 @. ADDS r0,r0,#1 0x080002c6: 9000 .. STR r0,[sp,#0] 0x080002c8: 9800 .. LDR r0,[sp,#0] 0x080002ca: 2850 P( CMP r0,#0x50 0x080002cc: d3f9 .. BCC 0x80002c2 ; SystemInit + 90 0x080002ce: bf00 .. NOP  0x080002d0: 480d .H LDR r0,[pc,#52] ; [0x8000308] = 0x40021000 0x080002d2: 6840 @h LDR r0,[r0,#4] 0x080002d4: f0200003 ... BIC r0,r0,#3 0x080002d8: 490b .I LDR r1,[pc,#44] ; [0x8000308] = 0x40021000 0x080002da: 6048 H` STR r0,[r1,#4] 0x080002dc: 4608 .F MOV r0,r1 0x080002de: 6800 .h LDR r0,[r0,#0] 0x080002e0: 490a .I LDR r1,[pc,#40] ; [0x800030c] = 0xfef6ffff 0x080002e2: 4008 .@ ANDS r0,r0,r1 0x080002e4: 4908 .I LDR r1,[pc,#32] ; [0x8000308] = 0x40021000 0x080002e6: 6008 .` STR r0,[r1,#0] 0x080002e8: f44f001f O... MOV r0,#0x9f0000 0x080002ec: 6088 .` STR r0,[r1,#8] 0x080002ee: 4608 .F MOV r0,r1 0x080002f0: 6800 .h LDR r0,[r0,#0] 0x080002f2: f4202080 .. BIC r0,r0,#0x40000 0x080002f6: 6008 .` STR r0,[r1,#0] 0x080002f8: 2000 . MOVS r0,#0 0x080002fa: 6048 H` STR r0,[r1,#4] 0x080002fc: 62c8 .b STR r0,[r1,#0x2c] 0x080002fe: f000fa13 .... BL system_clock_config ; 0x8000728 0x08000302: bd08 .. POP {r3,pc} $d 0x08000304: e000ed88 .... DCD 3758157192 0x08000308: 40021000 ...@ DCD 1073876992 0x0800030c: fef6ffff .... DCD 4277600255 $t i.TurnOffLed TurnOffLed 0x08000310: b510 .. PUSH {r4,lr} 0x08000312: 4604 .F MOV r4,r0 0x08000314: 2c03 ., CMP r4,#3 0x08000316: d300 .. BCC 0x800031a ; TurnOffLed + 10 0x08000318: bd10 .. POP {r4,pc} 0x0800031a: eb040244 ..D. ADD r2,r4,r4,LSL #1 0x0800031e: 4b06 .K LDR r3,[pc,#24] ; [0x8000338] = 0x20000000 0x08000320: eb030282 .... ADD r2,r3,r2,LSL #2 0x08000324: 6891 .h LDR r1,[r2,#8] 0x08000326: eb040244 ..D. ADD r2,r4,r4,LSL #1 0x0800032a: eb030282 .... ADD r2,r3,r2,LSL #2 0x0800032e: 6850 Ph LDR r0,[r2,#4] 0x08000330: f000f829 ..). BL gpio_bit_reset ; 0x8000386 0x08000334: bf00 .. NOP  0x08000336: e7ef .. B 0x8000318 ; TurnOffLed + 8 $d 0x08000338: 20000000 ... DCD 536870912 $t i.TurnOnLed TurnOnLed 0x0800033c: b510 .. PUSH {r4,lr} 0x0800033e: 4604 .F MOV r4,r0 0x08000340: 2c03 ., CMP r4,#3 0x08000342: d300 .. BCC 0x8000346 ; TurnOnLed + 10 0x08000344: bd10 .. POP {r4,pc} 0x08000346: eb040244 ..D. ADD r2,r4,r4,LSL #1 0x0800034a: 4b06 .K LDR r3,[pc,#24] ; [0x8000364] = 0x20000000 0x0800034c: eb030282 .... ADD r2,r3,r2,LSL #2 0x08000350: 6891 .h LDR r1,[r2,#8] 0x08000352: eb040244 ..D. ADD r2,r4,r4,LSL #1 0x08000356: eb030282 .... ADD r2,r3,r2,LSL #2 0x0800035a: 6850 Ph LDR r0,[r2,#4] 0x0800035c: f000f815 .... BL gpio_bit_set ; 0x800038a 0x08000360: bf00 .. NOP  0x08000362: e7ef .. B 0x8000344 ; TurnOnLed + 8 $d 0x08000364: 20000000 ... DCD 536870912 $t i.__scatterload_copy __scatterload_copy 0x08000368: e002 .. B 0x8000370 ; __scatterload_copy + 8 0x0800036a: c808 .. LDM r0!,{r3} 0x0800036c: 1f12 .. SUBS r2,r2,#4 0x0800036e: c108 .. STM r1!,{r3} 0x08000370: 2a00 .* CMP r2,#0 0x08000372: d1fa .. BNE 0x800036a ; __scatterload_copy + 2 0x08000374: 4770 pG BX lr i.__scatterload_null __scatterload_null 0x08000376: 4770 pG BX lr i.__scatterload_zeroinit __scatterload_zeroinit 0x08000378: 2000 . MOVS r0,#0 0x0800037a: e001 .. B 0x8000380 ; __scatterload_zeroinit + 8 0x0800037c: c101 .. STM r1!,{r0} 0x0800037e: 1f12 .. SUBS r2,r2,#4 0x08000380: 2a00 .* CMP r2,#0 0x08000382: d1fb .. BNE 0x800037c ; __scatterload_zeroinit + 4 0x08000384: 4770 pG BX lr i.gpio_bit_reset gpio_bit_reset 0x08000386: 6141 Aa STR r1,[r0,#0x14] 0x08000388: 4770 pG BX lr i.gpio_bit_set gpio_bit_set 0x0800038a: 6101 .a STR r1,[r0,#0x10] 0x0800038c: 4770 pG BX lr i.gpio_init gpio_init 0x0800038e: b5f0 .. PUSH {r4-r7,lr} 0x08000390: 4604 .F MOV r4,r0 0x08000392: 4616 .F MOV r6,r2 0x08000394: 2500 .% MOVS r5,#0 0x08000396: 2200 .\" MOVS r2,#0 0x08000398: f001050f .... AND r5,r1,#0xf 0x0800039c: f0010710 .... AND r7,r1,#0x10 0x080003a0: b147 G. CBZ r7,0x80003b4 ; gpio_init + 38 0x080003a2: 2e04 .. CMP r6,#4 0x080003a4: d105 .. BNE 0x80003b2 ; gpio_init + 36 0x080003a6: f0450503 E... ORR r5,r5,#3 0x080003aa: 6be7 .k LDR r7,[r4,#0x3c] 0x080003ac: 431f .C ORRS r7,r7,r3 0x080003ae: 63e7 .c STR r7,[r4,#0x3c] 0x080003b0: e000 .. B 0x80003b4 ; gpio_init + 38 0x080003b2: 4335 5C ORRS r5,r5,r6 0x080003b4: 2000 . MOVS r0,#0 0x080003b6: e01e .. B 0x80003f6 ; gpio_init + 104 0x080003b8: 2701 .\' MOVS r7,#1 0x080003ba: 4087 .@ LSLS r7,r7,r0 0x080003bc: 401f .@ ANDS r7,r7,r3 0x080003be: b1c7 .. CBZ r7,0x80003f2 ; gpio_init + 100 0x080003c0: 6822 \"h LDR r2,[r4,#0] 0x080003c2: ea4f0c80 O... LSL r12,r0,#2 0x080003c6: 270f .\' MOVS r7,#0xf 0x080003c8: fa07f70c .... LSL r7,r7,r12 0x080003cc: 43ba .C BICS r2,r2,r7 0x080003ce: 0087 .. LSLS r7,r0,#2 0x080003d0: fa05f707 .... LSL r7,r5,r7 0x080003d4: 433a :C ORRS r2,r2,r7 0x080003d6: 2928 () CMP r1,#0x28 0x080003d8: d104 .. BNE 0x80003e4 ; gpio_init + 86 0x080003da: 2701 .\' MOVS r7,#1 0x080003dc: 4087 .@ LSLS r7,r7,r0 0x080003de: 401f .@ ANDS r7,r7,r3 0x080003e0: 6167 ga STR r7,[r4,#0x14] 0x080003e2: e005 .. B 0x80003f0 ; gpio_init + 98 0x080003e4: 2948 H) CMP r1,#0x48 0x080003e6: d103 .. BNE 0x80003f0 ; gpio_init + 98 0x080003e8: 2701 .\' MOVS r7,#1 0x080003ea: 4087 .@ LSLS r7,r7,r0 0x080003ec: 401f .@ ANDS r7,r7,r3 0x080003ee: 6127 \'a STR r7,[r4,#0x10] 0x080003f0: 6022 \"` STR r2,[r4,#0] 0x080003f2: 1c47 G. ADDS r7,r0,#1 0x080003f4: b2b8 .. UXTH r0,r7 0x080003f6: 2808 .( CMP r0,#8 0x080003f8: d3de .. BCC 0x80003b8 ; gpio_init + 42 0x080003fa: 2008 . MOVS r0,#8 0x080003fc: e022 \". B 0x8000444 ; gpio_init + 182 0x080003fe: 2701 .\' MOVS r7,#1 0x08000400: 4087 .@ LSLS r7,r7,r0 0x08000402: 401f .@ ANDS r7,r7,r3 0x08000404: b1e7 .. CBZ r7,0x8000440 ; gpio_init + 178 0x08000406: 6862 bh LDR r2,[r4,#4] 0x08000408: f1a00708 .... SUB r7,r0,#8 0x0800040c: ea4f0c87 O... LSL r12,r7,#2 0x08000410: 270f .\' MOVS r7,#0xf 0x08000412: fa07f70c .... LSL r7,r7,r12 0x08000416: 43ba .C BICS r2,r2,r7 0x08000418: f1a00708 .... SUB r7,r0,#8 0x0800041c: 00bf .. LSLS r7,r7,#2 0x0800041e: fa05f707 .... LSL r7,r5,r7 0x08000422: 433a :C ORRS r2,r2,r7 0x08000424: 2928 () CMP r1,#0x28 0x08000426: d104 .. BNE 0x8000432 ; gpio_init + 164 0x08000428: 2701 .\' MOVS r7,#1 0x0800042a: 4087 .@ LSLS r7,r7,r0 0x0800042c: 401f .@ ANDS r7,r7,r3 0x0800042e: 6167 ga STR r7,[r4,#0x14] 0x08000430: e005 .. B 0x800043e ; gpio_init + 176 0x08000432: 2948 H) CMP r1,#0x48 0x08000434: d103 .. BNE 0x800043e ; gpio_init + 176 0x08000436: 2701 .\' MOVS r7,#1 0x08000438: 4087 .@ LSLS r7,r7,r0 0x0800043a: 401f .@ ANDS r7,r7,r3 0x0800043c: 6127 \'a STR r7,[r4,#0x10] 0x0800043e: 6062 b` STR r2,[r4,#4] 0x08000440: 1c47 G. ADDS r7,r0,#1 0x08000442: b2b8 .. UXTH r0,r7 0x08000444: 2810 .( CMP r0,#0x10 0x08000446: d3da .. BCC 0x80003fe ; gpio_init + 112 0x08000448: bdf0 .. POP {r4-r7,pc} i.main main 0x0800044a: f7fffe9f .... BL DelayInit ; 0x800018c 0x0800044e: f7fffedd .... BL LedDrvInit ; 0x800020c 0x08000452: e021 !. B 0x8000498 ; main + 78 0x08000454: 2000 . MOVS r0,#0 0x08000456: f7ffff71 ..q. BL TurnOnLed ; 0x800033c 0x0800045a: f44f707a O.zp MOV r0,#0x3e8 0x0800045e: f7fffeb3 .... BL DelayNms ; 0x80001c8 0x08000462: 2001 . MOVS r0,#1 0x08000464: f7ffff6a ..j. BL TurnOnLed ; 0x800033c 0x08000468: f44f707a O.zp MOV r0,#0x3e8 0x0800046c: f7fffeac .... BL DelayNms ; 0x80001c8 0x08000470: 2002 . MOVS r0,#2 0x08000472: f7ffff63 ..c. BL TurnOnLed ; 0x800033c 0x08000476: f44f707a O.zp MOV r0,#0x3e8 0x0800047a: f7fffea5 .... BL DelayNms ; 0x80001c8 0x0800047e: 2000 . MOVS r0,#0 0x08000480: f7ffff46 ..F. BL TurnOffLed ; 0x8000310 0x08000484: 2001 . MOVS r0,#1 0x08000486: f7ffff43 ..C. BL TurnOffLed ; 0x8000310 0x0800048a: 2002 . MOVS r0,#2 0x0800048c: f7ffff40 ..@. BL TurnOffLed ; 0x8000310 0x08000490: f44f707a O.zp MOV r0,#0x3e8 0x08000494: f7fffe98 .... BL DelayNms ; 0x80001c8 0x08000498: e7dc .. B 0x8000454 ; main + 10 0x0800049a: 0000 .. MOVS r0,r0 i.rcu_clock_freq_get rcu_clock_freq_get 0x0800049c: e92d4ff0 -..O PUSH {r4-r11,lr} 0x080004a0: b08c .. SUB sp,sp,#0x30 0x080004a2: 4607 .F MOV r7,r0 0x080004a4: 2000 . MOVS r0,#0 0x080004a6: 900a .. STR r0,[sp,#0x28] 0x080004a8: a04a J. ADR r0,{pc}+0x12c ; 0x80005d4 0x080004aa: e8904c00 ...L LDM r0,{r10,r11,lr} 0x080004ae: 68c0 .h LDR r0,[r0,#0xc] 0x080004b0: e9cdbe05 .... STRD r11,lr,[sp,#0x14] 0x080004b4: f8cda010 .... STR r10,[sp,#0x10] 0x080004b8: 9007 .. STR r0,[sp,#0x1c] 0x080004ba: f20f1a1c .... ADR.W r10,{pc}+0x11e ; 0x80005d8 0x080004be: e9da0a00 .... LDRD r0,r10,[r10,#0] 0x080004c2: e9cd0a02 .... STRD r0,r10,[sp,#8] 0x080004c6: f20f1a10 .... ADR.W r10,{pc}+0x112 ; 0x80005d8 0x080004ca: e9da0a00 .... LDRD r0,r10,[r10,#0] 0x080004ce: e9cd0a00 .... STRD r0,r10,[sp,#0] 0x080004d2: 4844 DH LDR r0,[pc,#272] ; [0x80005e4] = 0x40021000 0x080004d4: 6840 @h LDR r0,[r0,#4] 0x080004d6: f3c00081 .... UBFX r0,r0,#2,#2 0x080004da: 900b .. STR r0,[sp,#0x2c] 0x080004dc: 980b .. LDR r0,[sp,#0x2c] 0x080004de: b120 . CBZ r0,0x80004ea ; rcu_clock_freq_get + 78 0x080004e0: 2801 .( CMP r0,#1 0x080004e2: d004 .. BEQ 0x80004ee ; rcu_clock_freq_get + 82 0x080004e4: 2802 .( CMP r0,#2 0x080004e6: d13f ?. BNE 0x8000568 ; rcu_clock_freq_get + 204 0x080004e8: e003 .. B 0x80004f2 ; rcu_clock_freq_get + 86 0x080004ea: 4a3f ?J LDR r2,[pc,#252] ; [0x80005e8] = 0x7a1200 0x080004ec: e03e >. B 0x800056c ; rcu_clock_freq_get + 208 0x080004ee: 4a3e >J LDR r2,[pc,#248] ; [0x80005e8] = 0x7a1200 0x080004f0: e03c <. B 0x800056c ; rcu_clock_freq_get + 208 0x080004f2: 483c <H LDR r0,[pc,#240] ; [0x80005e4] = 0x40021000 0x080004f4: 6840 @h LDR r0,[r0,#4] 0x080004f6: f4003c80 ...< AND r12,r0,#0x10000 0x080004fa: f5bc3f80 ...? CMP r12,#0x10000 0x080004fe: d112 .. BNE 0x8000526 ; rcu_clock_freq_get + 138 0x08000500: 4838 8H LDR r0,[pc,#224] ; [0x80005e4] = 0x40021000 0x08000502: 6ac0 .j LDR r0,[r0,#0x2c] 0x08000504: f0004880 ...H AND r8,r0,#0x40000000 0x08000508: f1b80f00 .... CMP r8,#0 0x0800050c: d101 .. BNE 0x8000512 ; rcu_clock_freq_get + 118 0x0800050e: 4b36 6K LDR r3,[pc,#216] ; [0x80005e8] = 0x7a1200 0x08000510: e000 .. B 0x8000514 ; rcu_clock_freq_get + 120 0x08000512: 4b36 6K LDR r3,[pc,#216] ; [0x80005ec] = 0x2dc6c00 0x08000514: 4833 3H LDR r0,[pc,#204] ; [0x80005e4] = 0x40021000 0x08000516: 6840 @h LDR r0,[r0,#4] 0x08000518: f4003900 ...9 AND r9,r0,#0x20000 0x0800051c: f5b93f00 ...? CMP r9,#0x20000 0x08000520: d102 .. BNE 0x8000528 ; rcu_clock_freq_get + 140 0x08000522: 085b [. LSRS r3,r3,#1 0x08000524: e000 .. B 0x8000528 ; rcu_clock_freq_get + 140 0x08000526: 4b32 2K LDR r3,[pc,#200] ; [0x80005f0] = 0x3d0900 0x08000528: 482e .H LDR r0,[pc,#184] ; [0x80005e4] = 0x40021000 0x0800052a: 6840 @h LDR r0,[r0,#4] 0x0800052c: f3c04183 ...A UBFX r1,r0,#18,#4 0x08000530: 482c ,H LDR r0,[pc,#176] ; [0x80005e4] = 0x40021000 0x08000532: 6840 @h LDR r0,[r0,#4] 0x08000534: f0006000 ...` AND r0,r0,#0x8000000 0x08000538: b108 .. CBZ r0,0x800053e ; rcu_clock_freq_get + 162 0x0800053a: f0410110 A... ORR r1,r1,#0x10 0x0800053e: 4829 )H LDR r0,[pc,#164] ; [0x80005e4] = 0x40021000 0x08000540: 6840 @h LDR r0,[r0,#4] 0x08000542: f0004080 ...@ AND r0,r0,#0x40000000 0x08000546: b108 .. CBZ r0,0x800054c ; rcu_clock_freq_get + 176 0x08000548: f0410120 A. . ORR r1,r1,#0x20 0x0800054c: 290f .) CMP r1,#0xf 0x0800054e: d201 .. BCS 0x8000554 ; rcu_clock_freq_get + 184 0x08000550: 1c89 .. ADDS r1,r1,#2 0x08000552: e006 .. B 0x8000562 ; rcu_clock_freq_get + 198 0x08000554: 290f .) CMP r1,#0xf 0x08000556: d303 .. BCC 0x8000560 ; rcu_clock_freq_get + 196 0x08000558: 293e >) CMP r1,#0x3e 0x0800055a: d801 .. BHI 0x8000560 ; rcu_clock_freq_get + 196 0x0800055c: 1c49 I. ADDS r1,r1,#1 0x0800055e: e000 .. B 0x8000562 ; rcu_clock_freq_get + 198 0x08000560: 213f ?! MOVS r1,#0x3f 0x08000562: fb03f201 .... MUL r2,r3,r1 0x08000566: e001 .. B 0x800056c ; rcu_clock_freq_get + 208 0x08000568: 4a1f .J LDR r2,[pc,#124] ; [0x80005e8] = 0x7a1200 0x0800056a: bf00 .. NOP  0x0800056c: bf00 .. NOP  0x0800056e: 481d .H LDR r0,[pc,#116] ; [0x80005e4] = 0x40021000 0x08000570: 6840 @h LDR r0,[r0,#4] 0x08000572: f3c01503 .... UBFX r5,r0,#4,#4 0x08000576: a804 .. ADD r0,sp,#0x10 0x08000578: 5d46 F] LDRB r6,[r0,r5] 0x0800057a: fa22f406 \"... LSR r4,r2,r6 0x0800057e: 4819 .H LDR r0,[pc,#100] ; [0x80005e4] = 0x40021000 0x08000580: 6840 @h LDR r0,[r0,#4] 0x08000582: f3c02502 ...% UBFX r5,r0,#8,#3 0x08000586: a802 .. ADD r0,sp,#8 0x08000588: 5d46 F] LDRB r6,[r0,r5] 0x0800058a: fa24f006 $... LSR r0,r4,r6 0x0800058e: 9009 .. STR r0,[sp,#0x24] 0x08000590: 4814 .H LDR r0,[pc,#80] ; [0x80005e4] = 0x40021000 0x08000592: 6840 @h LDR r0,[r0,#4] 0x08000594: f3c025c2 ...% UBFX r5,r0,#11,#3 0x08000598: f81d6005 ...` LDRB r6,[sp,r5] 0x0800059c: fa24f006 $... LSR r0,r4,r6 0x080005a0: 9008 .. STR r0,[sp,#0x20] 0x080005a2: b137 7. CBZ r7,0x80005b2 ; rcu_clock_freq_get + 278 0x080005a4: 2f01 ./ CMP r7,#1 0x080005a6: d006 .. BEQ 0x80005b6 ; rcu_clock_freq_get + 282 0x080005a8: 2f02 ./ CMP r7,#2 0x080005aa: d006 .. BEQ 0x80005ba ; rcu_clock_freq_get + 286 0x080005ac: 2f03 ./ CMP r7,#3 0x080005ae: d10a .. BNE 0x80005c6 ; rcu_clock_freq_get + 298 0x080005b0: e006 .. B 0x80005c0 ; rcu_clock_freq_get + 292 0x080005b2: 920a .. STR r2,[sp,#0x28] 0x080005b4: e008 .. B 0x80005c8 ; rcu_clock_freq_get + 300 0x080005b6: 940a .. STR r4,[sp,#0x28] 0x080005b8: e006 .. B 0x80005c8 ; rcu_clock_freq_get + 300 0x080005ba: 9809 .. LDR r0,[sp,#0x24] 0x080005bc: 900a .. STR r0,[sp,#0x28] 0x080005be: e003 .. B 0x80005c8 ; rcu_clock_freq_get + 300 0x080005c0: 9808 .. LDR r0,[sp,#0x20] 0x080005c2: 900a .. STR r0,[sp,#0x28] 0x080005c4: e000 .. B 0x80005c8 ; rcu_clock_freq_get + 300 0x080005c6: bf00 .. NOP  0x080005c8: bf00 .. NOP  0x080005ca: 980a .. LDR r0,[sp,#0x28] 0x080005cc: b00c .. ADD sp,sp,#0x30 0x080005ce: e8bd8ff0 .... POP {r4-r11,pc} $d 0x080005d2: 0000 .. DCW 0 0x080005d4: 00000000 .... DCD 0 0x080005d8: 00000000 .... DCD 0 0x080005dc: 04030201 .... DCD 67305985 0x080005e0: 09080706 .... DCD 151521030 0x080005e4: 40021000 ...@ DCD 1073876992 0x080005e8: 007a1200 ..z. DCD 8000000 0x080005ec: 02dc6c00 .l.. DCD 48000000 0x080005f0: 003d0900 ..=. DCD 4000000 $t i.rcu_periph_clock_enable rcu_periph_clock_enable 0x080005f4: 4a06 .J LDR r2,[pc,#24] ; [0x8000610] = 0x40021000 0x080005f6: eb021190 .... ADD r1,r2,r0,LSR #6 0x080005fa: 6809 .h LDR r1,[r1,#0] 0x080005fc: f000031f .... AND r3,r0,#0x1f 0x08000600: 2201 .\" MOVS r2,#1 0x08000602: 409a .@ LSLS r2,r2,r3 0x08000604: 4311 .C ORRS r1,r1,r2 0x08000606: 4b02 .K LDR r3,[pc,#8] ; [0x8000610] = 0x40021000 0x08000608: eb031290 .... ADD r2,r3,r0,LSR #6 0x0800060c: 6011 .` STR r1,[r2,#0] 0x0800060e: 4770 pG BX lr $d 0x08000610: 40021000 ...@ DCD 1073876992 $t i.system_clock_120m_hxtal system_clock_120m_hxtal 0x08000614: 2000 . MOVS r0,#0 0x08000616: 2100 .! MOVS r1,#0 0x08000618: 4a3f ?J LDR r2,[pc,#252] ; [0x8000718] = 0x40021000 0x0800061a: 6812 .h LDR r2,[r2,#0] 0x0800061c: f4423280 B..2 ORR r2,r2,#0x10000 0x08000620: 4b3d =K LDR r3,[pc,#244] ; [0x8000718] = 0x40021000 0x08000622: 601a .` STR r2,[r3,#0] 0x08000624: bf00 .. NOP  0x08000626: 1c40 @. ADDS r0,r0,#1 0x08000628: 4a3b ;J LDR r2,[pc,#236] ; [0x8000718] = 0x40021000 0x0800062a: 6812 .h LDR r2,[r2,#0] 0x0800062c: f4023100 ...1 AND r1,r2,#0x20000 0x08000630: b919 .. CBNZ r1,0x800063a ; system_clock_120m_hxtal + 38 0x08000632: f64f72ff O..r MOV r2,#0xffff 0x08000636: 4290 .B CMP r0,r2 0x08000638: d1f5 .. BNE 0x8000626 ; system_clock_120m_hxtal + 18 0x0800063a: 4a37 7J LDR r2,[pc,#220] ; [0x8000718] = 0x40021000 0x0800063c: 6812 .h LDR r2,[r2,#0] 0x0800063e: f4023200 ...2 AND r2,r2,#0x20000 0x08000642: b90a .. CBNZ r2,0x8000648 ; system_clock_120m_hxtal + 52 0x08000644: bf00 .. NOP  0x08000646: e7fe .. B 0x8000646 ; system_clock_120m_hxtal + 50 0x08000648: 4a33 3J LDR r2,[pc,#204] ; [0x8000718] = 0x40021000 0x0800064a: 69d2 .i LDR r2,[r2,#0x1c] 0x0800064c: f0425280 B..R ORR r2,r2,#0x10000000 0x08000650: 4b31 1K LDR r3,[pc,#196] ; [0x8000718] = 0x40021000 0x08000652: 61da .a STR r2,[r3,#0x1c] 0x08000654: 4a31 1J LDR r2,[pc,#196] ; [0x800071c] = 0x40007000 0x08000656: 6812 .h LDR r2,[r2,#0] 0x08000658: f4424240 B.@B ORR r2,r2,#0xc000 0x0800065c: 4b2f /K LDR r3,[pc,#188] ; [0x800071c] = 0x40007000 0x0800065e: 601a .` STR r2,[r3,#0] 0x08000660: 4a2d -J LDR r2,[pc,#180] ; [0x8000718] = 0x40021000 0x08000662: 6852 Rh LDR r2,[r2,#4] 0x08000664: 4b2c ,K LDR r3,[pc,#176] ; [0x8000718] = 0x40021000 0x08000666: 605a Z` STR r2,[r3,#4] 0x08000668: 461a .F MOV r2,r3 0x0800066a: 6852 Rh LDR r2,[r2,#4] 0x0800066c: 605a Z` STR r2,[r3,#4] 0x0800066e: 461a .F MOV r2,r3 0x08000670: 6852 Rh LDR r2,[r2,#4] 0x08000672: f4426280 B..b ORR r2,r2,#0x400 0x08000676: 605a Z` STR r2,[r3,#4] 0x08000678: 461a .F MOV r2,r3 0x0800067a: 6852 Rh LDR r2,[r2,#4] 0x0800067c: f4223240 \".@2 BIC r2,r2,#0x30000 0x08000680: 605a Z` STR r2,[r3,#4] 0x08000682: 461a .F MOV r2,r3 0x08000684: 6852 Rh LDR r2,[r2,#4] 0x08000686: f4423240 B.@2 ORR r2,r2,#0x30000 0x0800068a: 605a Z` STR r2,[r3,#4] 0x0800068c: 461a .F MOV r2,r3 0x0800068e: 6852 Rh LDR r2,[r2,#4] 0x08000690: 4b23 #K LDR r3,[pc,#140] ; [0x8000720] = 0xb7c3ffff 0x08000692: 401a .@ ANDS r2,r2,r3 0x08000694: 4b20 K LDR r3,[pc,#128] ; [0x8000718] = 0x40021000 0x08000696: 605a Z` STR r2,[r3,#4] 0x08000698: 461a .F MOV r2,r3 0x0800069a: 6852 Rh LDR r2,[r2,#4] 0x0800069c: 4b21 !K LDR r3,[pc,#132] ; [0x8000724] = 0x8340000 0x0800069e: 431a .C ORRS r2,r2,r3 0x080006a0: 4b1d .K LDR r3,[pc,#116] ; [0x8000718] = 0x40021000 0x080006a2: 605a Z` STR r2,[r3,#4] 0x080006a4: 461a .F MOV r2,r3 0x080006a6: 6812 .h LDR r2,[r2,#0] 0x080006a8: f0427280 B..r ORR r2,r2,#0x1000000 0x080006ac: 601a .` STR r2,[r3,#0] 0x080006ae: bf00 .. NOP  0x080006b0: 4a19 .J LDR r2,[pc,#100] ; [0x8000718] = 0x40021000 0x080006b2: 6812 .h LDR r2,[r2,#0] 0x080006b4: f0027200 ...r AND r2,r2,#0x2000000 0x080006b8: 2a00 .* CMP r2,#0 0x080006ba: d0f9 .. BEQ 0x80006b0 ; system_clock_120m_hxtal + 156 0x080006bc: 4a17 .J LDR r2,[pc,#92] ; [0x800071c] = 0x40007000 0x080006be: 6812 .h LDR r2,[r2,#0] 0x080006c0: f4423280 B..2 ORR r2,r2,#0x10000 0x080006c4: 4b15 .K LDR r3,[pc,#84] ; [0x800071c] = 0x40007000 0x080006c6: 601a .` STR r2,[r3,#0] 0x080006c8: bf00 .. NOP  0x080006ca: 4a14 .J LDR r2,[pc,#80] ; [0x800071c] = 0x40007000 0x080006cc: 6852 Rh LDR r2,[r2,#4] 0x080006ce: f4023280 ...2 AND r2,r2,#0x10000 0x080006d2: 2a00 .* CMP r2,#0 0x080006d4: d0f9 .. BEQ 0x80006ca ; system_clock_120m_hxtal + 182 0x080006d6: 4a11 .J LDR r2,[pc,#68] ; [0x800071c] = 0x40007000 0x080006d8: 6812 .h LDR r2,[r2,#0] 0x080006da: f4423200 B..2 ORR r2,r2,#0x20000 0x080006de: 4b0f .K LDR r3,[pc,#60] ; [0x800071c] = 0x40007000 0x080006e0: 601a .` STR r2,[r3,#0] 0x080006e2: bf00 .. NOP  0x080006e4: 4a0d .J LDR r2,[pc,#52] ; [0x800071c] = 0x40007000 0x080006e6: 6852 Rh LDR r2,[r2,#4] 0x080006e8: f4023200 ...2 AND r2,r2,#0x20000 0x080006ec: 2a00 .* CMP r2,#0 0x080006ee: d0f9 .. BEQ 0x80006e4 ; system_clock_120m_hxtal + 208 0x080006f0: 4a09 .J LDR r2,[pc,#36] ; [0x8000718] = 0x40021000 0x080006f2: 6852 Rh LDR r2,[r2,#4] 0x080006f4: f0220203 \"... BIC r2,r2,#3 0x080006f8: 4b07 .K LDR r3,[pc,#28] ; [0x8000718] = 0x40021000 0x080006fa: 605a Z` STR r2,[r3,#4] 0x080006fc: 461a .F MOV r2,r3 0x080006fe: 6852 Rh LDR r2,[r2,#4] 0x08000700: f0420202 B... ORR r2,r2,#2 0x08000704: 605a Z` STR r2,[r3,#4] 0x08000706: bf00 .. NOP  0x08000708: 4a03 .J LDR r2,[pc,#12] ; [0x8000718] = 0x40021000 0x0800070a: 6852 Rh LDR r2,[r2,#4] 0x0800070c: f0020208 .... AND r2,r2,#8 0x08000710: 2a00 .* CMP r2,#0 0x08000712: d0f9 .. BEQ 0x8000708 ; system_clock_120m_hxtal + 244 0x08000714: 4770 pG BX lr $d 0x08000716: 0000 .. DCW 0 0x08000718: 40021000 ...@ DCD 1073876992 0x0800071c: 40007000 .p.@ DCD 1073770496 0x08000720: b7c3ffff .... DCD 3083075583 0x08000724: 08340000 ..4. DCD 137625600 $t i.system_clock_config system_clock_config 0x08000728: b510 .. PUSH {r4,lr} 0x0800072a: f7ffff73 ..s. BL system_clock_120m_hxtal ; 0x8000614 0x0800072e: bd10 .. POP {r4,pc} $d.realdata Region$$Table$$Base 0x08000730: 08000750 P... DCD 134219600 0x08000734: 20000000 ... DCD 536870912 0x08000738: 00000024 $... DCD 36 0x0800073c: 08000368 h... DCD 134218600 0x08000740: 08000774 t... DCD 134219636 0x08000744: 20000024 $.. DCD 536870948 0x08000748: 00000404 .... DCD 1028 0x0800074c: 08000378 x... DCD 134218616 Region$$Table$$Limit

从现在开始,开始逐段汇编代码分析。

在看到过程中前面的是作为入口地址,相当于是一种提示,我们主要是关心的是汇编语言。

1.3.3.1 初始化向量表
__Vectors 0x08000000: 20000428 (.. DCD 536871976 0x08000004: 08000145 E... DCD 134218053 0x08000004:: 0800014d M... DCD 134218061 0x0800000c: 0800014f O... DCD 134218063.... 0x0800011c: 0800015f _... DCD 134218079 0x08000120: 0800015f _... DCD 134218079 0x08000124: 0800015f _... DCD 134218079 0x08000128: 0800015f _... DCD 134218079 0x0800012c: 0800015f _... DCD 134218079

DCD:ARM汇编中的一种伪指令,用于数据定义,主要用于在内存中分配连续的32位字(4字节)存储单元,并初始化为指定的数值或地址。也就是我们将我们常用的中断放到前面的地址中,

最前面这一列0x0800 0000、0x08000004、0x08000004以及后续的,全部是用来存储的,就是我们房间,这些数字就是房间的门牌号,是实实在在的物理空间,紧挨着的就是表示存的内容,例如:第一行:地址0x08000000存储的数据是: 20000428;
第二行:地址0x08000004存储的数据是: 08000145;
第三行:地址0x08000004存储的数据是: 0800014d; 这些数据在这里可以认为是我们自己写的中断函数的函数的入口,例如我写了一个中断函数,我们就需要再内存中找到一个空间存放这个中断函数,那么存的地方需要一个入口地址,这样我们才能找到他,而DCD在这里的作用就在这里。例如从其他工程中拿到的

DCD TIMER4_IRQHandler  ; 66:TIMER4DCD SPI2_IRQHandler  ; 67:SPI2DCD UART3_IRQHandler  ; 68:UART3DCD UART4_IRQHandler  ; 69:UART4DCD TIMER5_IRQHandler  ; 70:TIMER5 DCD TIMER6_IRQHandler  ; 71:TIMER6DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel40x08000108: 08000f95 .... DCD 1342217170x0800010c: 0800015f _... DCD 1342180790x08000110: 0800015f _... DCD 1342180790x08000114: 0800015f _... DCD 1342180790x08000118: 0800015f _... DCD 1342180790x0800011c: 0800015f _... DCD 1342180790x08000120: 0800015f _... DCD 1342180790x08000124: 0800015f _... DCD 1342180790x08000128: 0800015f _... DCD 1342180790x0800012c: 0800015f _... DCD 134218079

可以看出第一行表示的是TIMER4中断,而下面的这一段表示的就是ARM执行DCD的结果,可以看出
地址0x08000108,存储的就是我们写的TIMER4函数的入口地址:08000f95

ARM单片机启动流程(一)(详细解析)
通过这个截图可以明显的看出函数的入口地址就是08000f95,接着就对里面进行操作。

额外在说一句:为什么我们编译的时候是0x08000f95,而实际的物理地址是0x08000f94?
地址差异的核心原因:Thumb 状态标志位​
在 ARM Cortex-M 架构中:

  • 向量表存储的是入口地址值,而非指令本身。
  • 地址的最低有效位(LSB)作为状态标志​:
    • LSB=1​:表示目标代码为 ​Thumb 指令集​(Cortex-M 全系仅支持 Thumb)。
    • LSB=0​:表示 ARM 指令集(Cortex-M 不支持)。
  • 硬件自动处理​:当 CPU 从向量表加载地址到 PC 时,会自动清除 LSB,确保跳转到对齐的指令地址
存储值(向量表)​​ ​实际跳转地址(PC)​​ ​LSB 作用0x08000145 0x08000144 标志 Thumb 状态 0x08000101 0x08000100 同上 表面差异是 ​Thumb 状态标志的编码结果,硬件和编译器已完美协调此机制,只需确保(这一部分可以认为是芯片工程师在使用):
  1. 向量表项存储的值 = 函数地址 ​​+1​(由编译器自动处理)。
  2. 函数代码按 ​4 字节对齐存放(链接脚本控制)​。

结论​:0x08000145 是逻辑值,实际执行地址为 0x08000144,硬件自动完成转换。

在说明一下最后的POP和PUSH语句:

在之前的文章我们讲到过中断函数的跳转,也就是说假如正在执行某一个函数,突然中断来了,我们就需要执行这个中断,就如本例子的TIMER4中断,但是我们执行以后还需要返回到原来程序的位置,因此是不是就需要一个保存现场的功能和恢复现场的功能。
因此可以通过上述TIMER4的例子,可以看出进来的第一个指令就是PUSH指令保存现场

0x08000f94: b510 .. PUSH {r4,lr}PUSH {r4, lr} @ 保存r4和返回地址(lr)

最后一个指令

POP {r4, pc} @ 恢复r4和pc,跳转回调用地址

至于r4、lr是什么,暂时就不要深究了,这是微机原理的内容,如果过于深究那么需要的知识就体系就很庞杂,建议后续有精力在研究。
我们只需要记住PUSH是保存现场指令,POP是恢复现场指令,我们看到了汇编程序是这样执行的,在我们脑子里面具象化了,就可以了,已经足够我们理解一些东西了,不在是纸上谈兵。

那在说一下PC又是什么意思:
至于PC是什么,我也在这里简单说一句,

PC始终存储当前正在执行的指令的下一条指令地址,是CPU从内存中读取指令的起点。例如,若当前指令地址为0x1000,执行后PC会自动更新为0x1004(假设指令长度为4字节),指向下一指令。

只是知道他是核心就行了,还是不需要深究这些汇编指令,怎么说呐,对于这些汇编指令如果我们深入理解了,对这些元器件可以深入理解包括看数据手册,但是对实际工程或者项目感觉意义不是太大,或者是一些难搞的Bug有帮助。但是对于我们编写代码或者是理解某一个芯片肯定是有很大的帮助的,因为我们会看的更深层,会对这些有深入理解。啰嗦了一堆,也是对我自己说的,是对自己此时此刻的理解的记录。

以上就是初始化的内容,并且对中断这一块进行了拓展,对我个人而言,是有深刻的理解,因为我对中断有了具象化的理解。

1.3.3.2 汇编指令的运行
 __main _main_stk 0x08000130: f8dfd00c .... LDR sp,__lit__00000000 ; [0x8000140] = 0x20000428 .ARM.Collect$$$$00000004 _main_scatterload 0x08000134: f000f818 .... BL __scatterload ; 0x8000168 .ARM.Collect$$$$00000008 .ARM.Collect$$$$0000000A .ARM.Collect$$$$0000000B __main_after_scatterload _main_clock _main_cpp_init _main_init 0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x800044b 0x0800013a: 4700 .G BX r0 $d 0x0800013c: 0800044b K... DCD 134218827 .ARM.Collect$$$$00002712 __lit__00000000 .ARM.Collect$$$$0000000D .ARM.Collect$$$$0000000F __rt_final_cpp __rt_final_exit 0x08000140: 20000428 (.. DCD 536871976 $t .text $v0 Reset_Handler 0x08000144: 4806 .H LDR r0,[pc,#24] ; [0x8000160] = 0x8000269 0x08000146: 4780 .G BLX r0 0x08000148: 4806 .H LDR r0,[pc,#24] ; [0x8000164] = 0x8000131 0x0800014a: 4700 .G BX r0 NMI_Handler 0x0800014c: e7fe .. B NMI_Handler ; 0x800014c HardFault_Handler 0x0800014e: e7fe .. B HardFault_Handler ; 0x800014e MemManage_Handler 0x08000150: e7fe .. B MemManage_Handler ; 0x8000150 BusFault_Handler 0x08000152: e7fe .. B BusFault_Handler ; 0x8000152 UsageFault_Handler 0x08000154: e7fe .. B UsageFault_Handler ; 0x8000154 SVC_Handler 0x08000156: e7fe .. B SVC_Handler ; 0x8000156 DebugMon_Handler 0x08000158: e7fe .. B DebugMon_Handler ; 0x8000158 PendSV_Handler 0x0800015a: e7fe .. B PendSV_Handler ; 0x800015a SysTick_Handler 0x0800015c: e7fe .. B SysTick_Handler ; 0x800015c

首先映入眼帘的是_ _ main函数,注意这个main函数不是我们编写代码的main函数呐。

需要注意的是:
这些代码在地址空间上是连续排列的,但执行流程并非完全顺序执行。关键点在于其中包含跳转指令(BLBX)和硬件复位机制,导致执行路径发生分支。

启动入口:硬件强制跳转(非顺序起点)​

  • 硬件复位后,CPU 直接从中断向量表中加载 Reset_Handler 的地址(位于 0x08000004),并跳转到该地址(0x08000144)。

  • 因此,代码的第一条执行指令是 Reset_Handler0x08000144),而非地址最低的 0x08000130

  • 物理地址连续​:代码在 Flash 中按地址顺序存储(0x08000130 → 0x0800014A)。

  • 执行流非线性​:

    • 硬件强制跳转至 Reset_Handler0x08000144)。
    • Reset_Handler__main 中的跳转指令(BLX/BX)​主动切换执行路径

那么我们就直接看下面这两段段代码

这段代码存在于我们的工程启动文件:Reset_Handler PROC EXPORT Reset_Handler  [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
这段代码存在我们编译后的汇编语言。Reset_Handler0x08000144: 4806 .H LDR r0,[pc,#24] ; [0x8000160] = 0x80002690x08000146: 4780 .G BLX r00x08000148: 4806 .H LDR r0,[pc,#24] ; [0x8000164] = 0x80001310x0800014a: 4700 .G BX r0

我们直接就从汇编语言开始分析:

从上面的启动入口可以知道,硬件会直接跳转到0x08000144,这就是单片机复位后的第二件事
至于第一件事,现在暂时按下不表,估计要到下一篇文章在详细说了,因为第一件事包含的内容较多。如果您看到这里,还请点点赞,您的点赞是我长久分享知识的动力,言归正传!。

由于是硬件自动跳转,那么这个时候执行的就是:

0x08000144: 4806 .H LDR r0,[pc,#24] ; [0x8000160] = 0x8000269

这段代码的作用就是取出:SystemInit地址(0x0800269)

0x08000146: 4780 .G BLX r0 @调用SystemInit()

我们此时看一下SystemInit()函数的入口地址以及怎么执行的,我们先不看代码自己可以猜一下第一行和最后一行语句是什么?

第一行是PUSH
最后一行是POP

至于为什么我相信你现在已经有答案了。

 SystemInit 0x08000268: b508 .. PUSH {r3,lr} 0x0800026a: 4826 &H LDR r0,[pc,#152] ; [0x8000304] = 0xe000ed88 0x0800026c: 6800 .h LDR r0,[r0,#0] 0x0800026e: f4400070 @.p. ORR r0,r0,#0xf00000 0x08000272: 4924 $I LDR r1,[pc,#144] ; [0x8000304] = 0xe000ed88 0x08000274: 6008 .` STR r0,[r1,#0] 0x08000276: 4824 $H LDR r0,[pc,#144] ; [0x8000308] = 0x40021000 0x08000278: 6800 .h LDR r0,[r0,#0] 0x0800027a: f0400001 @... ORR r0,r0,#1 0x0800027e: 4922 \"I LDR r1,[pc,#136] ; [0x8000308] = 0x40021000 0x08000280: 6008 .` STR r0,[r1,#0] 0x08000282: bf00 .. NOP  0x08000284: 4820 H LDR r0,[pc,#128] ; [0x8000308] = 0x40021000 0x08000286: 6800 .h LDR r0,[r0,#0] 0x08000288: f0000002 .... AND r0,r0,#2 0x0800028c: 2800 .( CMP r0,#0 0x0800028e: d0f9 .. BEQ 0x8000284 ; SystemInit + 28 0x08000290: bf00 .. NOP  0x08000292: 481d .H LDR r0,[pc,#116] ; [0x8000308] = 0x40021000 0x08000294: 6840 @h LDR r0,[r0,#4] 0x08000296: f0400080 @... ORR r0,r0,#0x80 0x0800029a: 491b .I LDR r1,[pc,#108] ; [0x8000308] = 0x40021000 0x0800029c: 6048 H` STR r0,[r1,#4] 0x0800029e: 2000 . MOVS r0,#0 0x080002a0: 9000 .. STR r0,[sp,#0] 0x080002a2: e002 .. B 0x80002aa ; SystemInit + 66 0x080002a4: 9800 .. LDR r0,[sp,#0] 0x080002a6: 1c40 @. ADDS r0,r0,#1 0x080002a8: 9000 .. STR r0,[sp,#0] 0x080002aa: 9800 .. LDR r0,[sp,#0] 0x080002ac: 2850 P( CMP r0,#0x50 0x080002ae: d3f9 .. BCC 0x80002a4 ; SystemInit + 60 0x080002b0: 4815 .H LDR r0,[pc,#84] ; [0x8000308] = 0x40021000 0x080002b2: 6840 @h LDR r0,[r0,#4] 0x080002b4: f0400090 @... ORR r0,r0,#0x90 0x080002b8: 4913 .I LDR r1,[pc,#76] ; [0x8000308] = 0x40021000 0x080002ba: 6048 H` STR r0,[r1,#4] 0x080002bc: 2000 . MOVS r0,#0 0x080002be: 9000 .. STR r0,[sp,#0] 0x080002c0: e002 .. B 0x80002c8 ; SystemInit + 96 0x080002c2: 9800 .. LDR r0,[sp,#0] 0x080002c4: 1c40 @. ADDS r0,r0,#1 0x080002c6: 9000 .. STR r0,[sp,#0] 0x080002c8: 9800 .. LDR r0,[sp,#0] 0x080002ca: 2850 P( CMP r0,#0x50 0x080002cc: d3f9 .. BCC 0x80002c2 ; SystemInit + 90 0x080002ce: bf00 .. NOP  0x080002d0: 480d .H LDR r0,[pc,#52] ; [0x8000308] = 0x40021000 0x080002d2: 6840 @h LDR r0,[r0,#4] 0x080002d4: f0200003 ... BIC r0,r0,#3 0x080002d8: 490b .I LDR r1,[pc,#44] ; [0x8000308] = 0x40021000 0x080002da: 6048 H` STR r0,[r1,#4] 0x080002dc: 4608 .F MOV r0,r1 0x080002de: 6800 .h LDR r0,[r0,#0] 0x080002e0: 490a .I LDR r1,[pc,#40] ; [0x800030c] = 0xfef6ffff 0x080002e2: 4008 .@ ANDS r0,r0,r1 0x080002e4: 4908 .I LDR r1,[pc,#32] ; [0x8000308] = 0x40021000 0x080002e6: 6008 .` STR r0,[r1,#0] 0x080002e8: f44f001f O... MOV r0,#0x9f0000 0x080002ec: 6088 .` STR r0,[r1,#8] 0x080002ee: 4608 .F MOV r0,r1 0x080002f0: 6800 .h LDR r0,[r0,#0] 0x080002f2: f4202080 .. BIC r0,r0,#0x40000 0x080002f6: 6008 .` STR r0,[r1,#0] 0x080002f8: 2000 . MOVS r0,#0 0x080002fa: 6048 H` STR r0,[r1,#4] 0x080002fc: 62c8 .b STR r0,[r1,#0x2c] 0x080002fe: f000fa13 .... BL system_clock_config ; 0x8000728 0x08000302: bd08 .. POP {r3,pc}

可以看出我们的代码确实如此。

SystemInit()作用​:

  • 配置系统时钟(HSI/HSE/PLL)。
  • 初始化FPU(若启用)。
  • 设置中断向量表偏移(SCB->VTOR = 0x08000000

这样我们就有理由相信,初始化以后,还会回到Reset_Handler函数。

0x08000148: 4806 .H LDR r0,[pc,#24] ; [0x8000164] = 0x8000131

那么接下来就是找到地址0x8000131,这个地址就是我们这一章节开篇提到的_ _ main函数,也是我们最开始从宏观架构理解的ARM启动流程中的内容。

接着就是吓一跳指令

0x0800014a: 4700 .G BX r0

使用BX而非BLX跳转到__main,因为无需返回(用户代码永不退出)

跳转到我们心心想念的_ _ main函数,此时距离我们最终的目标,找到main函数已经接近了。

  • __main的作用​:
    • 完成C库初始化(堆、标准IO等)。
    • 调用全局构造函数(C++)。
    • 最终跳转至用户main()函数,永不返回。

通过分析我们可以知道这段代码就是跳到我们自己写的main函数的指令

_main_init0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x800044b0x0800013a: 4700 .G BX r0
 main 0x0800044a: f7fffe9f .... BL DelayInit ; 0x800018c 0x0800044e: f7fffedd .... BL LedDrvInit ; 0x800020c 0x08000452: e021 !. B 0x8000498 ; main + 78 0x08000454: 2000 . MOVS r0,#0 0x08000456: f7ffff71 ..q. BL TurnOnLed ; 0x800033c 0x0800045a: f44f707a O.zp MOV r0,#0x3e8 0x0800045e: f7fffeb3 .... BL DelayNms ; 0x80001c8 0x08000462: 2001 . MOVS r0,#1 0x08000464: f7ffff6a ..j. BL TurnOnLed ; 0x800033c 0x08000468: f44f707a O.zp MOV r0,#0x3e8 0x0800046c: f7fffeac .... BL DelayNms ; 0x80001c8 0x08000470: 2002 . MOVS r0,#2 0x08000472: f7ffff63 ..c. BL TurnOnLed ; 0x800033c 0x08000476: f44f707a O.zp MOV r0,#0x3e8 0x0800047a: f7fffea5 .... BL DelayNms ; 0x80001c8 0x0800047e: 2000 . MOVS r0,#0 0x08000480: f7ffff46 ..F. BL TurnOffLed ; 0x8000310 0x08000484: 2001 . MOVS r0,#1 0x08000486: f7ffff43 ..C. BL TurnOffLed ; 0x8000310 0x0800048a: 2002 . MOVS r0,#2 0x0800048c: f7ffff40 ..@. BL TurnOffLed ; 0x8000310 0x08000490: f44f707a O.zp MOV r0,#0x3e8 0x08000494: f7fffe98 .... BL DelayNms ; 0x80001c8 0x08000498: e7dc .. B 0x8000454 ; main + 10 0x0800049a: 0000 .. MOVS r0,r0

可以看出我们main 函数入口地址确实是0x0800044a。

在看另外一个工程

_main_init0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x8001f5b0x0800013a: 4700 .G BX r0
 main 0x08001f5a: f7fefdcf .... BL DrvInit ; 0x8000afc 0x08001f5e: f7fefcf5 .... BL AppInit ; 0x800094c 0x08001f62: e001 .. B 0x8001f68 ; main + 14 0x08001f64: f7fff844 ..D. BL TaskHandler ; 0x8000ff0 0x08001f68: e7fc .. B 0x8001f64 ; main + 10 0x08001f6a: 0000 .. MOVS r0,r0

可以看出我们main 函数入口地址确实是0x08001f5a。

以上就是ARM核启动流程的汇编代码分析。



文章源码获取方式:
如果您对本文的源码感兴趣,欢迎在评论区留下您的邮箱地址。我会在空闲时间整理相关代码,并通过邮件发送给您。由于个人时间有限,发送可能会有一定延迟,请您耐心等待。同时,建议您在评论时注明具体的需求或问题,以便我更好地为您提供针对性的帮助。

【版权声明】
本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议。这意味着您可以自由地共享(复制、分发)和改编(修改、转换)本文内容,但必须遵守以下条件:
署名:您必须注明原作者(即本文博主)的姓名,并提供指向原文的链接。
相同方式共享:如果您基于本文创作了新的内容,必须使用相同的 CC 4.0 BY-SA 协议进行发布。

感谢您的理解与支持!如果您有任何疑问或需要进一步协助,请随时在评论区留言。