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(内存管理单元)硬件协作完成,对应用程序透明
对于我们的理解启动流程来说,我们只关心逻辑地址和最终的物理地址,逻辑地址到物理地址有一个映射关系,这个映射关系是由硬件自动完成的,对于我们写程序来说不需要深入追究,如果必须追究可以通过微机原理深入理解。
1.2内存分布
单片机通过地址来访问寄存器、RAM、FLASH,ARM寻址范围4GB,分为多个块:
一共4G个字节
CODE范围是:0x0000 0000~0x1FFF FFFF,共计512M,非易失、掉电保存。
SRAM:范围是0x2000 0000~0x3FFF FFFF,共计512M。
片上外设范围是0x4000 0000~0x5FFF FFFF,共计512M,包含定时器、串口、IO口一些寄存器。
EXMC范围是0x6000 0000~0x9FFF FFFF共计1GB,外挂的一些设备。
Coretex-M4内核寄存器范围是0xE000 0000~0xFFFF FFFF共计512M,如:NVIC、中断控制、滴答定时器。
截止到这里我们只需要粗浅的认识,在单片机内部存储器映射分为了以上几个部分。
1.3 单片机复位以后主要的启动流程
复位以后主要先执行的就是这段程序,
Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT SystemInitIMPORT __mainLDR R0, =SystemInitBLX R0LDR R0, =__mainBX R0ENDP
“_ _ main”:是Keil库函数里面的一个封装好的,看不到源代码,最主要的是在这个函数里面会调用我们自己写的main函数,因此我们的主函数只能是main函数,如果是改个名字就会编译报错。
整体的框架是以上这个流程思路,整理出来就是以下这几句话。
从Reset_Handler开始
然后执行到_ _ main ,接着进行一些初始化堆栈的(如全局变量初始化等),
最后执行程序到main(我们写的),然后在进行相关执行。
1.3.2 单片机的几种启动模式
经过整体框架的分析,我们还不知道具体的细节,也就是访问地址的操作是什么,或者说是从地址层面单片机先干什么,在干什么,这都是有严格的要求的。
通过上图可以看出,主要是根据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)的结果。
- 地址映射的本质
- CPU 上电后固定从逻辑地址
0x00000000
取第一条指令(栈指针和复位向量)。 - 物理存储介质(如 Flash、SRAM 或 BootROM)的原始地址被硬件映射到
0x00000000
,形成“别名区”(Alias Region)。 - 例如:
- 主闪存(Main Flash):物理地址
0x08000000
→ 映射到0x00000000
。 - 系统存储器(BootROM):物理地址
0x1FFF0000
→ 映射到0x00000000
(STM32 中为 System Memory)。
- 主闪存(Main Flash):物理地址
- CPU 上电后固定从逻辑地址
- CPU 视角的执行过程
- CPU 始终认为自己从
0x00000000
执行代码,但实际访问的是映射后的物理存储单元。 - 关键区别:
- 若从主闪存启动 →
0x00000000
等同于0x08000000
(访问 Flash 的起始位置)。 - 若从 BootROM 启动 →
0x00000000
等同于0x1FFF0000
(执行厂商预置的 Bootloader)。
- 若从主闪存启动 →
- CPU 始终认为自己从
- 逻辑地址与物理地址的辩证关系
- 逻辑地址的抽象性
0x00000000
是 CPU 的固定入口地址,属于逻辑地址空间,由硬件自动重定向到物理存储设备。- 物理地址(如
0x08000000
)是存储介质在总线上的实际位置,两者通过重映射建立关联
- **是否“等同于”物理地址?
- 是:在启动阶段,访问
0x00000000
即访问映射后的物理地址(如0x08000000
),效果相同。 - 否:逻辑地址本身无存储能力,仅作为访问物理介质的桥梁;物理地址是存储介质的真实位置。
- 是:在启动阶段,访问
- 逻辑地址的抽象性
- 重映射的硬件实现原理
- 别名区的设计
- 芯片内部将
0x00000000~0x000FFFFF
(本文以STM32为例)定义为启动空间别名区,通过总线开关动态连接到目标存储区。 - 例如:
- 当 BOOT0=0 时,别名区指向 Flash (
0x08000000
); - 当 BOOT0=1 时,别名区指向 BootROM (
0x1FFF0000
)
- 当 BOOT0=0 时,别名区指向 Flash (
- 芯片内部将
- 地址转换的透明性
- CPU 无需感知重映射过程,由内存控制器(如 ARM 的 AHB 总线)自动完成地址转换。
- 别名区的设计
总的来说:
- “执行
0x00000000
等于执行0x08000000
”- 仅在主闪存启动模式下成立(此时两者指向同一物理存储单元)。
- 逻辑地址与物理地址的关系
0x00000000
是逻辑入口地址,其内容由映射的物理存储介质提供。- 物理地址(如
0x08000000
)是存储介质的真实位置,两者通过重映射绑定。
通过上图可以看出,在引导存储空间有多重启动方式,那我们在这里不妨多深入一下,为什么会有几种启动模式呐,原因如下
单片机需要不同的启动模式,主要是为了满足开发调试、程序更新、系统恢复以及资源适配等多场景需求。这些模式通过硬件引脚配置实现,核心原理是将不同物理存储区域映射到固定的启动地址(0x00000000),使CPU能按需选择执行入口。
1. 功能隔离与系统恢复
- 系统存储器启动(Bootloader模式)
- 作用:当用户程序损坏或需更新时,通过内置的只读Bootloader(存储在系统存储器,地址
0x1FFF0000~0x1FFF7A0F
)实现程序恢复。 - 典型场景:
- 串口下载程序(ISP):通过Bootloader将新代码烧录至主闪存。
- 修复锁死的Flash:当调试接口被误配置为普通IO时,通过此模式解锁并重烧程序。
- 硬件配置:
BOOT0=1, BOOT1=0
。
- 作用:当用户程序损坏或需更新时,通过内置的只读Bootloader(存储在系统存储器,地址
2. 开发调试优化
- 内置SRAM启动(调试模式)
- 作用:将程序加载到SRAM(地址
0x20000000
)运行,避免频繁擦写Flash,延长Flash寿命并加速调试。 - 优势:
- 修改代码后无需全盘擦除Flash,缩短编译-调试周期。
- 避免Flash写入延迟,实时测试代码逻辑。
- 硬件配置:
BOOT0=1, BOOT1=1
。
注意:SRAM掉电后数据丢失,仅用于临时调试 。
- 作用:将程序加载到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的启动流程,我们就以编译后的汇编代码为基础去分析最底层的执行逻辑。针对汇编的一些指令在使用过程中会进行一些简单说明,我们其实只需要知道是怎么个意义就行,不需要深入的细究,只是让我们从微观层面知道到底是怎么执行,毕竟这些涉及到微机原理。想搞的特别明白还是需要微机原理知识为蓝本进行分析。
为了说明清楚,我将我其中一个工程的汇编语言全部粘贴出来,后面我会逐段的分析。
这里就不过多赘述了。
__Vectors0x08000000: 20000428 (.. DCD 5368719760x08000004: 08000145 E... DCD 1342180530x08000008: 0800014d M... DCD 1342180610x0800000c: 0800014f O... DCD 1342180630x08000010: 08000151 Q... DCD 1342180650x08000014: 08000153 S... DCD 1342180670x08000018: 08000155 U... DCD 1342180690x0800001c: 00000000 .... DCD 00x08000020: 00000000 .... DCD 00x08000024: 00000000 .... DCD 00x08000028: 00000000 .... DCD 00x0800002c: 08000157 W... DCD 1342180710x08000030: 08000159 Y... DCD 1342180730x08000034: 00000000 .... DCD 00x08000038: 0800015b [... DCD 1342180750x0800003c: 0800015d ]... DCD 1342180770x08000040: 0800015f _... DCD 1342180790x08000044: 0800015f _... DCD 1342180790x08000048: 0800015f _... DCD 1342180790x0800004c: 0800015f _... DCD 1342180790x08000050: 0800015f _... DCD 1342180790x08000054: 0800015f _... DCD 1342180790x08000058: 0800015f _... DCD 1342180790x0800005c: 0800015f _... DCD 1342180790x08000060: 0800015f _... DCD 1342180790x08000064: 0800015f _... DCD 1342180790x08000068: 0800015f _... DCD 1342180790x0800006c: 0800015f _... DCD 1342180790x08000070: 0800015f _... DCD 1342180790x08000074: 0800015f _... DCD 1342180790x08000078: 0800015f _... DCD 1342180790x0800007c: 0800015f _... DCD 1342180790x08000080: 0800015f _... DCD 1342180790x08000084: 0800015f _... DCD 1342180790x08000088: 0800015f _... DCD 1342180790x0800008c: 0800015f _... DCD 1342180790x08000090: 0800015f _... DCD 1342180790x08000094: 0800015f _... DCD 1342180790x08000098: 0800015f _... DCD 1342180790x0800009c: 0800015f _... DCD 1342180790x080000a0: 0800015f _... DCD 1342180790x080000a4: 0800015f _... DCD 1342180790x080000a8: 0800015f _... DCD 1342180790x080000ac: 0800015f _... DCD 1342180790x080000b0: 0800015f _... DCD 1342180790x080000b4: 0800015f _... DCD 1342180790x080000b8: 0800015f _... DCD 1342180790x080000bc: 0800015f _... DCD 1342180790x080000c0: 0800015f _... DCD 1342180790x080000c4: 0800015f _... DCD 1342180790x080000c8: 0800015f _... DCD 1342180790x080000cc: 0800015f _... DCD 1342180790x080000d0: 0800015f _... DCD 1342180790x080000d4: 0800015f _... DCD 1342180790x080000d8: 0800015f _... DCD 1342180790x080000dc: 0800015f _... DCD 1342180790x080000e0: 0800015f _... DCD 1342180790x080000e4: 0800015f _... DCD 1342180790x080000e8: 0800015f _... DCD 1342180790x080000ec: 0800015f _... DCD 1342180790x080000f0: 0800015f _... DCD 1342180790x080000f4: 0800015f _... DCD 1342180790x080000f8: 0800015f _... DCD 1342180790x080000fc: 0800015f _... DCD 1342180790x08000100: 0800015f _... DCD 1342180790x08000104: 0800015f _... DCD 1342180790x08000108: 0800015f _... DCD 1342180790x0800010c: 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$t.ARM.Collect$$$$00000000.ARM.Collect$$$$00000001__Vectors_End__main_main_stk0x08000130: f8dfd00c .... LDR sp,__lit__00000000 ; [0x8000140] = 0x20000428.ARM.Collect$$$$00000004_main_scatterload0x08000134: f000f818 .... BL __scatterload ; 0x8000168.ARM.Collect$$$$00000008.ARM.Collect$$$$0000000A.ARM.Collect$$$$0000000B__main_after_scatterload_main_clock_main_cpp_init_main_init0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x800044b0x0800013a: 4700 .G BX r0$d0x0800013c: 0800044b K... DCD 134218827.ARM.Collect$$$$00002712__lit__00000000.ARM.Collect$$$$0000000D.ARM.Collect$$$$0000000F__rt_final_cpp__rt_final_exit0x08000140: 20000428 (.. DCD 536871976$t.text$v0Reset_Handler0x08000144: 4806 .H LDR r0,[pc,#24] ; [0x8000160] = 0x80002690x08000146: 4780 .G BLX r00x08000148: 4806 .H LDR r0,[pc,#24] ; [0x8000164] = 0x80001310x0800014a: 4700 .G BX r0NMI_Handler0x0800014c: e7fe .. B NMI_Handler ; 0x800014cHardFault_Handler0x0800014e: e7fe .. B HardFault_Handler ; 0x800014eMemManage_Handler0x08000150: e7fe .. B MemManage_Handler ; 0x8000150BusFault_Handler0x08000152: e7fe .. B BusFault_Handler ; 0x8000152UsageFault_Handler0x08000154: e7fe .. B UsageFault_Handler ; 0x8000154SVC_Handler0x08000156: e7fe .. B SVC_Handler ; 0x8000156DebugMon_Handler0x08000158: e7fe .. B DebugMon_Handler ; 0x8000158PendSV_Handler0x0800015a: e7fe .. B PendSV_Handler ; 0x800015aSysTick_Handler0x0800015c: e7fe .. B SysTick_Handler ; 0x800015cADC0_1_IRQHandlerADC2_IRQHandlerCAN0_EWMC_IRQHandlerCAN0_RX1_IRQHandlerDMA0_Channel0_IRQHandlerDMA0_Channel1_IRQHandlerDMA0_Channel2_IRQHandlerDMA0_Channel3_IRQHandlerDMA0_Channel4_IRQHandlerDMA0_Channel5_IRQHandlerDMA0_Channel6_IRQHandlerDMA1_Channel0_IRQHandlerDMA1_Channel1_IRQHandlerDMA1_Channel2_IRQHandlerDMA1_Channel3_4_IRQHandlerEXMC_IRQHandlerEXTI0_IRQHandlerEXTI10_15_IRQHandlerEXTI1_IRQHandlerEXTI2_IRQHandlerEXTI3_IRQHandlerEXTI4_IRQHandlerEXTI5_9_IRQHandlerFMC_IRQHandlerI2C0_ER_IRQHandlerI2C0_EV_IRQHandlerI2C1_ER_IRQHandlerI2C1_EV_IRQHandlerLVD_IRQHandlerRCU_CTC_IRQHandlerRTC_Alarm_IRQHandlerRTC_IRQHandlerSDIO_IRQHandlerSPI0_IRQHandlerSPI1_IRQHandlerSPI2_IRQHandlerTAMPER_IRQHandlerTIMER0_BRK_IRQHandlerTIMER0_Channel_IRQHandlerTIMER0_TRG_CMT_IRQHandlerTIMER0_UP_IRQHandlerTIMER1_IRQHandlerTIMER2_IRQHandlerTIMER3_IRQHandlerTIMER4_IRQHandlerTIMER5_IRQHandlerTIMER6_IRQHandlerTIMER7_BRK_IRQHandlerTIMER7_Channel_IRQHandlerTIMER7_TRG_CMT_IRQHandlerTIMER7_UP_IRQHandlerUART3_IRQHandlerUART4_IRQHandlerUSART0_IRQHandlerUSART1_IRQHandlerUSART2_IRQHandlerUSBD_HP_CAN0_TX_IRQHandlerUSBD_LP_CAN0_RX0_IRQHandlerUSBD_WKUP_IRQHandlerWWDGT_IRQHandler0x0800015e: e7fe .. B ADC0_1_IRQHandler ; 0x800015e$d0x08000160: 08000269 i... DCD 1342183450x08000164: 08000131 1... DCD 134218033$t.text__scatterload__scatterload_rt20x08000168: 4c06 .L LDR r4,[pc,#24] ; [0x8000184] = 0x80007300x0800016a: 4d07 .M LDR r5,[pc,#28] ; [0x8000188] = 0x80007500x0800016c: e006 .. B 0x800017c ; __scatterload + 200x0800016e: 68e0 .h LDR r0,[r4,#0xc]0x08000170: f0400301 @... ORR r3,r0,#10x08000174: e8940007 .... LDM r4,{r0-r2}0x08000178: 4798 .G BLX r30x0800017a: 3410 .4 ADDS r4,r4,#0x100x0800017c: 42ac .B CMP r4,r50x0800017e: d3f6 .. BCC 0x800016e ; __scatterload + 60x08000180: f7ffffda .... BL __main_after_scatterload ; 0x8000138$d0x08000184: 08000730 0... DCD 1342195680x08000188: 08000750 P... DCD 134219600$ti.DelayInitDelayInit0x0800018c: 480c .H LDR r0,[pc,#48] ; [0x80001c0] = 0xe000edfc0x0800018e: 6800 .h LDR r0,[r0,#0]0x08000190: f0207080 ..p BIC r0,r0,#0x10000000x08000194: 490a .I LDR r1,[pc,#40] ; [0x80001c0] = 0xe000edfc0x08000196: 6008 .` STR r0,[r1,#0]0x08000198: 4608 .F MOV r0,r10x0800019a: 6800 .h LDR r0,[r0,#0]0x0800019c: f0407080 @..p ORR r0,r0,#0x10000000x080001a0: 6008 .` STR r0,[r1,#0]0x080001a2: 4808 .H LDR r0,[pc,#32] ; [0x80001c4] = 0xe00010000x080001a4: 6800 .h LDR r0,[r0,#0]0x080001a6: f0200001 ... BIC r0,r0,#10x080001aa: 4906 .I LDR r1,[pc,#24] ; [0x80001c4] = 0xe00010000x080001ac: 6008 .` STR r0,[r1,#0]0x080001ae: 4608 .F MOV r0,r10x080001b0: 6800 .h LDR r0,[r0,#0]0x080001b2: f0400001 @... ORR r0,r0,#10x080001b6: 6008 .` STR r0,[r1,#0]0x080001b8: 2000 . MOVS r0,#00x080001ba: 6048 H` STR r0,[r1,#4]0x080001bc: 4770 pG BX lr$d0x080001be: 0000 .. DCW 00x080001c0: e000edfc .... DCD 37581573080x080001c4: e0001000 .... DCD 3758100480$ti.DelayNmsDelayNms0x080001c8: b570 p. PUSH {r4-r6,lr}0x080001ca: 4604 .F MOV r4,r00x080001cc: 2500 .% MOVS r5,#00x080001ce: e004 .. B 0x80001da ; DelayNms + 180x080001d0: f44f707a O.zp MOV r0,#0x3e80x080001d4: f000f804 .... BL DelayNus ; 0x80001e00x080001d8: 1c6d m. ADDS r5,r5,#10x080001da: 42a5 .B CMP r5,r40x080001dc: d3f8 .. BCC 0x80001d0 ; DelayNms + 80x080001de: bd70 p. POP {r4-r6,pc}i.DelayNusDelayNus0x080001e0: b570 p. PUSH {r4-r6,lr}0x080001e2: 4604 .F MOV r4,r00x080001e4: 4807 .H LDR r0,[pc,#28] ; [0x8000204] = 0xe00010000x080001e6: 6845 Eh LDR r5,[r0,#4]0x080001e8: 2001 . MOVS r0,#10x080001ea: f000f957 ..W. BL rcu_clock_freq_get ; 0x800049c0x080001ee: 4906 .I LDR r1,[pc,#24] ; [0x8000208] = 0xf42400x080001f0: fbb0f0f1 .... UDIV r0,r0,r10x080001f4: 4344 DC MULS r4,r0,r40x080001f6: bf00 .. NOP 0x080001f8: 4802 .H LDR r0,[pc,#8] ; [0x8000204] = 0xe00010000x080001fa: 6840 @h LDR r0,[r0,#4]0x080001fc: 1b40 @. SUBS r0,r0,r50x080001fe: 42a0 .B CMP r0,r40x08000200: d3fa .. BCC 0x80001f8 ; DelayNus + 240x08000202: bd70 p. POP {r4-r6,pc}$d0x08000204: e0001000 .... DCD 37581004800x08000208: 000f4240 @B.. DCD 1000000$ti.LedDrvInitLedDrvInit0x0800020c: b510 .. PUSH {r4,lr}0x0800020e: 2400 .$ MOVS r4,#00x08000210: e024 $. B 0x800025c ; LedDrvInit + 800x08000212: eb040144 ..D. ADD r1,r4,r4,LSL #10x08000216: 4a13 .J LDR r2,[pc,#76] ; [0x8000264] = 0x200000000x08000218: f8320021 2.!. LDRH r0,[r2,r1,LSL #2]0x0800021c: f000f9ea .... BL rcu_periph_clock_enable ; 0x80005f40x08000220: eb040144 ..D. ADD r1,r4,r4,LSL #10x08000224: 4a0f .J LDR r2,[pc,#60] ; [0x8000264] = 0x200000000x08000226: eb020181 .... ADD r1,r2,r1,LSL #20x0800022a: 688b .h LDR r3,[r1,#8]0x0800022c: eb040144 ..D. ADD r1,r4,r4,LSL #10x08000230: eb020181 .... ADD r1,r2,r1,LSL #20x08000234: 2202 ." MOVS r2,#20x08000236: 6848 Hh LDR r0,[r1,#4]0x08000238: 2110 .! MOVS r1,#0x100x0800023a: f000f8a8 .... BL gpio_init ; 0x800038e0x0800023e: eb040244 ..D. ADD r2,r4,r4,LSL #10x08000242: 4b08 .K LDR r3,[pc,#32] ; [0x8000264] = 0x200000000x08000244: eb030282 .... ADD r2,r3,r2,LSL #20x08000248: 6891 .h LDR r1,[r2,#8]0x0800024a: eb040244 ..D. ADD r2,r4,r4,LSL #10x0800024e: eb030282 .... ADD r2,r3,r2,LSL #20x08000252: 6850 Ph LDR r0,[r2,#4]0x08000254: f000f897 .... BL gpio_bit_reset ; 0x80003860x08000258: 1c60 `. ADDS r0,r4,#10x0800025a: b2c4 .. UXTB r4,r00x0800025c: 2c03 ., CMP r4,#30x0800025e: d3d8 .. BCC 0x8000212 ; LedDrvInit + 60x08000260: bd10 .. POP {r4,pc}$d0x08000262: 0000 .. DCW 00x08000264: 20000000 ... DCD 536870912$ti.SystemInitSystemInit0x08000268: b508 .. PUSH {r3,lr}0x0800026a: 4826 &H LDR r0,[pc,#152] ; [0x8000304] = 0xe000ed880x0800026c: 6800 .h LDR r0,[r0,#0]0x0800026e: f4400070 @.p. ORR r0,r0,#0xf000000x08000272: 4924 $I LDR r1,[pc,#144] ; [0x8000304] = 0xe000ed880x08000274: 6008 .` STR r0,[r1,#0]0x08000276: 4824 $H LDR r0,[pc,#144] ; [0x8000308] = 0x400210000x08000278: 6800 .h LDR r0,[r0,#0]0x0800027a: f0400001 @... ORR r0,r0,#10x0800027e: 4922 "I LDR r1,[pc,#136] ; [0x8000308] = 0x400210000x08000280: 6008 .` STR r0,[r1,#0]0x08000282: bf00 .. NOP 0x08000284: 4820 H LDR r0,[pc,#128] ; [0x8000308] = 0x400210000x08000286: 6800 .h LDR r0,[r0,#0]0x08000288: f0000002 .... AND r0,r0,#20x0800028c: 2800 .( CMP r0,#00x0800028e: d0f9 .. BEQ 0x8000284 ; SystemInit + 280x08000290: bf00 .. NOP 0x08000292: 481d .H LDR r0,[pc,#116] ; [0x8000308] = 0x400210000x08000294: 6840 @h LDR r0,[r0,#4]0x08000296: f0400080 @... ORR r0,r0,#0x800x0800029a: 491b .I LDR r1,[pc,#108] ; [0x8000308] = 0x400210000x0800029c: 6048 H` STR r0,[r1,#4]0x0800029e: 2000 . MOVS r0,#00x080002a0: 9000 .. STR r0,[sp,#0]0x080002a2: e002 .. B 0x80002aa ; SystemInit + 660x080002a4: 9800 .. LDR r0,[sp,#0]0x080002a6: 1c40 @. ADDS r0,r0,#10x080002a8: 9000 .. STR r0,[sp,#0]0x080002aa: 9800 .. LDR r0,[sp,#0]0x080002ac: 2850 P( CMP r0,#0x500x080002ae: d3f9 .. BCC 0x80002a4 ; SystemInit + 600x080002b0: 4815 .H LDR r0,[pc,#84] ; [0x8000308] = 0x400210000x080002b2: 6840 @h LDR r0,[r0,#4]0x080002b4: f0400090 @... ORR r0,r0,#0x900x080002b8: 4913 .I LDR r1,[pc,#76] ; [0x8000308] = 0x400210000x080002ba: 6048 H` STR r0,[r1,#4]0x080002bc: 2000 . MOVS r0,#00x080002be: 9000 .. STR r0,[sp,#0]0x080002c0: e002 .. B 0x80002c8 ; SystemInit + 960x080002c2: 9800 .. LDR r0,[sp,#0]0x080002c4: 1c40 @. ADDS r0,r0,#10x080002c6: 9000 .. STR r0,[sp,#0]0x080002c8: 9800 .. LDR r0,[sp,#0]0x080002ca: 2850 P( CMP r0,#0x500x080002cc: d3f9 .. BCC 0x80002c2 ; SystemInit + 900x080002ce: bf00 .. NOP 0x080002d0: 480d .H LDR r0,[pc,#52] ; [0x8000308] = 0x400210000x080002d2: 6840 @h LDR r0,[r0,#4]0x080002d4: f0200003 ... BIC r0,r0,#30x080002d8: 490b .I LDR r1,[pc,#44] ; [0x8000308] = 0x400210000x080002da: 6048 H` STR r0,[r1,#4]0x080002dc: 4608 .F MOV r0,r10x080002de: 6800 .h LDR r0,[r0,#0]0x080002e0: 490a .I LDR r1,[pc,#40] ; [0x800030c] = 0xfef6ffff0x080002e2: 4008 .@ ANDS r0,r0,r10x080002e4: 4908 .I LDR r1,[pc,#32] ; [0x8000308] = 0x400210000x080002e6: 6008 .` STR r0,[r1,#0]0x080002e8: f44f001f O... MOV r0,#0x9f00000x080002ec: 6088 .` STR r0,[r1,#8]0x080002ee: 4608 .F MOV r0,r10x080002f0: 6800 .h LDR r0,[r0,#0]0x080002f2: f4202080 .. BIC r0,r0,#0x400000x080002f6: 6008 .` STR r0,[r1,#0]0x080002f8: 2000 . MOVS r0,#00x080002fa: 6048 H` STR r0,[r1,#4]0x080002fc: 62c8 .b STR r0,[r1,#0x2c]0x080002fe: f000fa13 .... BL system_clock_config ; 0x80007280x08000302: bd08 .. POP {r3,pc}$d0x08000304: e000ed88 .... DCD 37581571920x08000308: 40021000 ...@ DCD 10738769920x0800030c: fef6ffff .... DCD 4277600255$ti.TurnOffLedTurnOffLed0x08000310: b510 .. PUSH {r4,lr}0x08000312: 4604 .F MOV r4,r00x08000314: 2c03 ., CMP r4,#30x08000316: d300 .. BCC 0x800031a ; TurnOffLed + 100x08000318: bd10 .. POP {r4,pc}0x0800031a: eb040244 ..D. ADD r2,r4,r4,LSL #10x0800031e: 4b06 .K LDR r3,[pc,#24] ; [0x8000338] = 0x200000000x08000320: eb030282 .... ADD r2,r3,r2,LSL #20x08000324: 6891 .h LDR r1,[r2,#8]0x08000326: eb040244 ..D. ADD r2,r4,r4,LSL #10x0800032a: eb030282 .... ADD r2,r3,r2,LSL #20x0800032e: 6850 Ph LDR r0,[r2,#4]0x08000330: f000f829 ..). BL gpio_bit_reset ; 0x80003860x08000334: bf00 .. NOP 0x08000336: e7ef .. B 0x8000318 ; TurnOffLed + 8$d0x08000338: 20000000 ... DCD 536870912$ti.TurnOnLedTurnOnLed0x0800033c: b510 .. PUSH {r4,lr}0x0800033e: 4604 .F MOV r4,r00x08000340: 2c03 ., CMP r4,#30x08000342: d300 .. BCC 0x8000346 ; TurnOnLed + 100x08000344: bd10 .. POP {r4,pc}0x08000346: eb040244 ..D. ADD r2,r4,r4,LSL #10x0800034a: 4b06 .K LDR r3,[pc,#24] ; [0x8000364] = 0x200000000x0800034c: eb030282 .... ADD r2,r3,r2,LSL #20x08000350: 6891 .h LDR r1,[r2,#8]0x08000352: eb040244 ..D. ADD r2,r4,r4,LSL #10x08000356: eb030282 .... ADD r2,r3,r2,LSL #20x0800035a: 6850 Ph LDR r0,[r2,#4]0x0800035c: f000f815 .... BL gpio_bit_set ; 0x800038a0x08000360: bf00 .. NOP 0x08000362: e7ef .. B 0x8000344 ; TurnOnLed + 8$d0x08000364: 20000000 ... DCD 536870912$ti.__scatterload_copy__scatterload_copy0x08000368: e002 .. B 0x8000370 ; __scatterload_copy + 80x0800036a: c808 .. LDM r0!,{r3}0x0800036c: 1f12 .. SUBS r2,r2,#40x0800036e: c108 .. STM r1!,{r3}0x08000370: 2a00 .* CMP r2,#00x08000372: d1fa .. BNE 0x800036a ; __scatterload_copy + 20x08000374: 4770 pG BX lri.__scatterload_null__scatterload_null0x08000376: 4770 pG BX lri.__scatterload_zeroinit__scatterload_zeroinit0x08000378: 2000 . MOVS r0,#00x0800037a: e001 .. B 0x8000380 ; __scatterload_zeroinit + 80x0800037c: c101 .. STM r1!,{r0}0x0800037e: 1f12 .. SUBS r2,r2,#40x08000380: 2a00 .* CMP r2,#00x08000382: d1fb .. BNE 0x800037c ; __scatterload_zeroinit + 40x08000384: 4770 pG BX lri.gpio_bit_resetgpio_bit_reset0x08000386: 6141 Aa STR r1,[r0,#0x14]0x08000388: 4770 pG BX lri.gpio_bit_setgpio_bit_set0x0800038a: 6101 .a STR r1,[r0,#0x10]0x0800038c: 4770 pG BX lri.gpio_initgpio_init0x0800038e: b5f0 .. PUSH {r4-r7,lr}0x08000390: 4604 .F MOV r4,r00x08000392: 4616 .F MOV r6,r20x08000394: 2500 .% MOVS r5,#00x08000396: 2200 ." MOVS r2,#00x08000398: f001050f .... AND r5,r1,#0xf0x0800039c: f0010710 .... AND r7,r1,#0x100x080003a0: b147 G. CBZ r7,0x80003b4 ; gpio_init + 380x080003a2: 2e04 .. CMP r6,#40x080003a4: d105 .. BNE 0x80003b2 ; gpio_init + 360x080003a6: f0450503 E... ORR r5,r5,#30x080003aa: 6be7 .k LDR r7,[r4,#0x3c]0x080003ac: 431f .C ORRS r7,r7,r30x080003ae: 63e7 .c STR r7,[r4,#0x3c]0x080003b0: e000 .. B 0x80003b4 ; gpio_init + 380x080003b2: 4335 5C ORRS r5,r5,r60x080003b4: 2000 . MOVS r0,#00x080003b6: e01e .. B 0x80003f6 ; gpio_init + 1040x080003b8: 2701 .' MOVS r7,#10x080003ba: 4087 .@ LSLS r7,r7,r00x080003bc: 401f .@ ANDS r7,r7,r30x080003be: b1c7 .. CBZ r7,0x80003f2 ; gpio_init + 1000x080003c0: 6822 "h LDR r2,[r4,#0]0x080003c2: ea4f0c80 O... LSL r12,r0,#20x080003c6: 270f .' MOVS r7,#0xf0x080003c8: fa07f70c .... LSL r7,r7,r120x080003cc: 43ba .C BICS r2,r2,r70x080003ce: 0087 .. LSLS r7,r0,#20x080003d0: fa05f707 .... LSL r7,r5,r70x080003d4: 433a :C ORRS r2,r2,r70x080003d6: 2928 () CMP r1,#0x280x080003d8: d104 .. BNE 0x80003e4 ; gpio_init + 860x080003da: 2701 .' MOVS r7,#10x080003dc: 4087 .@ LSLS r7,r7,r00x080003de: 401f .@ ANDS r7,r7,r30x080003e0: 6167 ga STR r7,[r4,#0x14]0x080003e2: e005 .. B 0x80003f0 ; gpio_init + 980x080003e4: 2948 H) CMP r1,#0x480x080003e6: d103 .. BNE 0x80003f0 ; gpio_init + 980x080003e8: 2701 .' MOVS r7,#10x080003ea: 4087 .@ LSLS r7,r7,r00x080003ec: 401f .@ ANDS r7,r7,r30x080003ee: 6127 'a STR r7,[r4,#0x10]0x080003f0: 6022 "` STR r2,[r4,#0]0x080003f2: 1c47 G. ADDS r7,r0,#10x080003f4: b2b8 .. UXTH r0,r70x080003f6: 2808 .( CMP r0,#80x080003f8: d3de .. BCC 0x80003b8 ; gpio_init + 420x080003fa: 2008 . MOVS r0,#80x080003fc: e022 ". B 0x8000444 ; gpio_init + 1820x080003fe: 2701 .' MOVS r7,#10x08000400: 4087 .@ LSLS r7,r7,r00x08000402: 401f .@ ANDS r7,r7,r30x08000404: b1e7 .. CBZ r7,0x8000440 ; gpio_init + 1780x08000406: 6862 bh LDR r2,[r4,#4]0x08000408: f1a00708 .... SUB r7,r0,#80x0800040c: ea4f0c87 O... LSL r12,r7,#20x08000410: 270f .' MOVS r7,#0xf0x08000412: fa07f70c .... LSL r7,r7,r120x08000416: 43ba .C BICS r2,r2,r70x08000418: f1a00708 .... SUB r7,r0,#80x0800041c: 00bf .. LSLS r7,r7,#20x0800041e: fa05f707 .... LSL r7,r5,r70x08000422: 433a :C ORRS r2,r2,r70x08000424: 2928 () CMP r1,#0x280x08000426: d104 .. BNE 0x8000432 ; gpio_init + 1640x08000428: 2701 .' MOVS r7,#10x0800042a: 4087 .@ LSLS r7,r7,r00x0800042c: 401f .@ ANDS r7,r7,r30x0800042e: 6167 ga STR r7,[r4,#0x14]0x08000430: e005 .. B 0x800043e ; gpio_init + 1760x08000432: 2948 H) CMP r1,#0x480x08000434: d103 .. BNE 0x800043e ; gpio_init + 1760x08000436: 2701 .' MOVS r7,#10x08000438: 4087 .@ LSLS r7,r7,r00x0800043a: 401f .@ ANDS r7,r7,r30x0800043c: 6127 'a STR r7,[r4,#0x10]0x0800043e: 6062 b` STR r2,[r4,#4]0x08000440: 1c47 G. ADDS r7,r0,#10x08000442: b2b8 .. UXTH r0,r70x08000444: 2810 .( CMP r0,#0x100x08000446: d3da .. BCC 0x80003fe ; gpio_init + 1120x08000448: bdf0 .. POP {r4-r7,pc}i.mainmain0x0800044a: f7fffe9f .... BL DelayInit ; 0x800018c0x0800044e: f7fffedd .... BL LedDrvInit ; 0x800020c0x08000452: e021 !. B 0x8000498 ; main + 780x08000454: 2000 . MOVS r0,#00x08000456: f7ffff71 ..q. BL TurnOnLed ; 0x800033c0x0800045a: f44f707a O.zp MOV r0,#0x3e80x0800045e: f7fffeb3 .... BL DelayNms ; 0x80001c80x08000462: 2001 . MOVS r0,#10x08000464: f7ffff6a ..j. BL TurnOnLed ; 0x800033c0x08000468: f44f707a O.zp MOV r0,#0x3e80x0800046c: f7fffeac .... BL DelayNms ; 0x80001c80x08000470: 2002 . MOVS r0,#20x08000472: f7ffff63 ..c. BL TurnOnLed ; 0x800033c0x08000476: f44f707a O.zp MOV r0,#0x3e80x0800047a: f7fffea5 .... BL DelayNms ; 0x80001c80x0800047e: 2000 . MOVS r0,#00x08000480: f7ffff46 ..F. BL TurnOffLed ; 0x80003100x08000484: 2001 . MOVS r0,#10x08000486: f7ffff43 ..C. BL TurnOffLed ; 0x80003100x0800048a: 2002 . MOVS r0,#20x0800048c: f7ffff40 ..@. BL TurnOffLed ; 0x80003100x08000490: f44f707a O.zp MOV r0,#0x3e80x08000494: f7fffe98 .... BL DelayNms ; 0x80001c80x08000498: e7dc .. B 0x8000454 ; main + 100x0800049a: 0000 .. MOVS r0,r0i.rcu_clock_freq_getrcu_clock_freq_get0x0800049c: e92d4ff0 -..O PUSH {r4-r11,lr}0x080004a0: b08c .. SUB sp,sp,#0x300x080004a2: 4607 .F MOV r7,r00x080004a4: 2000 . MOVS r0,#00x080004a6: 900a .. STR r0,[sp,#0x28]0x080004a8: a04a J. ADR r0,{pc}+0x12c ; 0x80005d40x080004aa: 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 ; 0x80005d80x080004be: e9da0a00 .... LDRD r0,r10,[r10,#0]0x080004c2: e9cd0a02 .... STRD r0,r10,[sp,#8]0x080004c6: f20f1a10 .... ADR.W r10,{pc}+0x112 ; 0x80005d80x080004ca: e9da0a00 .... LDRD r0,r10,[r10,#0]0x080004ce: e9cd0a00 .... STRD r0,r10,[sp,#0]0x080004d2: 4844 DH LDR r0,[pc,#272] ; [0x80005e4] = 0x400210000x080004d4: 6840 @h LDR r0,[r0,#4]0x080004d6: f3c00081 .... UBFX r0,r0,#2,#20x080004da: 900b .. STR r0,[sp,#0x2c]0x080004dc: 980b .. LDR r0,[sp,#0x2c]0x080004de: b120 . CBZ r0,0x80004ea ; rcu_clock_freq_get + 780x080004e0: 2801 .( CMP r0,#10x080004e2: d004 .. BEQ 0x80004ee ; rcu_clock_freq_get + 820x080004e4: 2802 .( CMP r0,#20x080004e6: d13f ?. BNE 0x8000568 ; rcu_clock_freq_get + 2040x080004e8: e003 .. B 0x80004f2 ; rcu_clock_freq_get + 860x080004ea: 4a3f ?J LDR r2,[pc,#252] ; [0x80005e8] = 0x7a12000x080004ec: e03e >. B 0x800056c ; rcu_clock_freq_get + 2080x080004ee: 4a3e >J LDR r2,[pc,#248] ; [0x80005e8] = 0x7a12000x080004f0: e03c <. B 0x800056c ; rcu_clock_freq_get + 2080x080004f2: 483c <H LDR r0,[pc,#240] ; [0x80005e4] = 0x400210000x080004f4: 6840 @h LDR r0,[r0,#4]0x080004f6: f4003c80 ...< AND r12,r0,#0x100000x080004fa: f5bc3f80 ...? CMP r12,#0x100000x080004fe: d112 .. BNE 0x8000526 ; rcu_clock_freq_get + 1380x08000500: 4838 8H LDR r0,[pc,#224] ; [0x80005e4] = 0x400210000x08000502: 6ac0 .j LDR r0,[r0,#0x2c]0x08000504: f0004880 ...H AND r8,r0,#0x400000000x08000508: f1b80f00 .... CMP r8,#00x0800050c: d101 .. BNE 0x8000512 ; rcu_clock_freq_get + 1180x0800050e: 4b36 6K LDR r3,[pc,#216] ; [0x80005e8] = 0x7a12000x08000510: e000 .. B 0x8000514 ; rcu_clock_freq_get + 1200x08000512: 4b36 6K LDR r3,[pc,#216] ; [0x80005ec] = 0x2dc6c000x08000514: 4833 3H LDR r0,[pc,#204] ; [0x80005e4] = 0x400210000x08000516: 6840 @h LDR r0,[r0,#4]0x08000518: f4003900 ...9 AND r9,r0,#0x200000x0800051c: f5b93f00 ...? CMP r9,#0x200000x08000520: d102 .. BNE 0x8000528 ; rcu_clock_freq_get + 1400x08000522: 085b [. LSRS r3,r3,#10x08000524: e000 .. B 0x8000528 ; rcu_clock_freq_get + 1400x08000526: 4b32 2K LDR r3,[pc,#200] ; [0x80005f0] = 0x3d09000x08000528: 482e .H LDR r0,[pc,#184] ; [0x80005e4] = 0x400210000x0800052a: 6840 @h LDR r0,[r0,#4]0x0800052c: f3c04183 ...A UBFX r1,r0,#18,#40x08000530: 482c ,H LDR r0,[pc,#176] ; [0x80005e4] = 0x400210000x08000532: 6840 @h LDR r0,[r0,#4]0x08000534: f0006000 ...` AND r0,r0,#0x80000000x08000538: b108 .. CBZ r0,0x800053e ; rcu_clock_freq_get + 1620x0800053a: f0410110 A... ORR r1,r1,#0x100x0800053e: 4829 )H LDR r0,[pc,#164] ; [0x80005e4] = 0x400210000x08000540: 6840 @h LDR r0,[r0,#4]0x08000542: f0004080 ...@ AND r0,r0,#0x400000000x08000546: b108 .. CBZ r0,0x800054c ; rcu_clock_freq_get + 1760x08000548: f0410120 A. . ORR r1,r1,#0x200x0800054c: 290f .) CMP r1,#0xf0x0800054e: d201 .. BCS 0x8000554 ; rcu_clock_freq_get + 1840x08000550: 1c89 .. ADDS r1,r1,#20x08000552: e006 .. B 0x8000562 ; rcu_clock_freq_get + 1980x08000554: 290f .) CMP r1,#0xf0x08000556: d303 .. BCC 0x8000560 ; rcu_clock_freq_get + 1960x08000558: 293e >) CMP r1,#0x3e0x0800055a: d801 .. BHI 0x8000560 ; rcu_clock_freq_get + 1960x0800055c: 1c49 I. ADDS r1,r1,#10x0800055e: e000 .. B 0x8000562 ; rcu_clock_freq_get + 1980x08000560: 213f ?! MOVS r1,#0x3f0x08000562: fb03f201 .... MUL r2,r3,r10x08000566: e001 .. B 0x800056c ; rcu_clock_freq_get + 2080x08000568: 4a1f .J LDR r2,[pc,#124] ; [0x80005e8] = 0x7a12000x0800056a: bf00 .. NOP 0x0800056c: bf00 .. NOP 0x0800056e: 481d .H LDR r0,[pc,#116] ; [0x80005e4] = 0x400210000x08000570: 6840 @h LDR r0,[r0,#4]0x08000572: f3c01503 .... UBFX r5,r0,#4,#40x08000576: a804 .. ADD r0,sp,#0x100x08000578: 5d46 F] LDRB r6,[r0,r5]0x0800057a: fa22f406 "... LSR r4,r2,r60x0800057e: 4819 .H LDR r0,[pc,#100] ; [0x80005e4] = 0x400210000x08000580: 6840 @h LDR r0,[r0,#4]0x08000582: f3c02502 ...% UBFX r5,r0,#8,#30x08000586: a802 .. ADD r0,sp,#80x08000588: 5d46 F] LDRB r6,[r0,r5]0x0800058a: fa24f006 $... LSR r0,r4,r60x0800058e: 9009 .. STR r0,[sp,#0x24]0x08000590: 4814 .H LDR r0,[pc,#80] ; [0x80005e4] = 0x400210000x08000592: 6840 @h LDR r0,[r0,#4]0x08000594: f3c025c2 ...% UBFX r5,r0,#11,#30x08000598: f81d6005 ...` LDRB r6,[sp,r5]0x0800059c: fa24f006 $... LSR r0,r4,r60x080005a0: 9008 .. STR r0,[sp,#0x20]0x080005a2: b137 7. CBZ r7,0x80005b2 ; rcu_clock_freq_get + 2780x080005a4: 2f01 ./ CMP r7,#10x080005a6: d006 .. BEQ 0x80005b6 ; rcu_clock_freq_get + 2820x080005a8: 2f02 ./ CMP r7,#20x080005aa: d006 .. BEQ 0x80005ba ; rcu_clock_freq_get + 2860x080005ac: 2f03 ./ CMP r7,#30x080005ae: d10a .. BNE 0x80005c6 ; rcu_clock_freq_get + 2980x080005b0: e006 .. B 0x80005c0 ; rcu_clock_freq_get + 2920x080005b2: 920a .. STR r2,[sp,#0x28]0x080005b4: e008 .. B 0x80005c8 ; rcu_clock_freq_get + 3000x080005b6: 940a .. STR r4,[sp,#0x28]0x080005b8: e006 .. B 0x80005c8 ; rcu_clock_freq_get + 3000x080005ba: 9809 .. LDR r0,[sp,#0x24]0x080005bc: 900a .. STR r0,[sp,#0x28]0x080005be: e003 .. B 0x80005c8 ; rcu_clock_freq_get + 3000x080005c0: 9808 .. LDR r0,[sp,#0x20]0x080005c2: 900a .. STR r0,[sp,#0x28]0x080005c4: e000 .. B 0x80005c8 ; rcu_clock_freq_get + 3000x080005c6: bf00 .. NOP 0x080005c8: bf00 .. NOP 0x080005ca: 980a .. LDR r0,[sp,#0x28]0x080005cc: b00c .. ADD sp,sp,#0x300x080005ce: e8bd8ff0 .... POP {r4-r11,pc}$d0x080005d2: 0000 .. DCW 00x080005d4: 00000000 .... DCD 00x080005d8: 00000000 .... DCD 00x080005dc: 04030201 .... DCD 673059850x080005e0: 09080706 .... DCD 1515210300x080005e4: 40021000 ...@ DCD 10738769920x080005e8: 007a1200 ..z. DCD 80000000x080005ec: 02dc6c00 .l.. DCD 480000000x080005f0: 003d0900 ..=. DCD 4000000$ti.rcu_periph_clock_enablercu_periph_clock_enable0x080005f4: 4a06 .J LDR r2,[pc,#24] ; [0x8000610] = 0x400210000x080005f6: eb021190 .... ADD r1,r2,r0,LSR #60x080005fa: 6809 .h LDR r1,[r1,#0]0x080005fc: f000031f .... AND r3,r0,#0x1f0x08000600: 2201 ." MOVS r2,#10x08000602: 409a .@ LSLS r2,r2,r30x08000604: 4311 .C ORRS r1,r1,r20x08000606: 4b02 .K LDR r3,[pc,#8] ; [0x8000610] = 0x400210000x08000608: eb031290 .... ADD r2,r3,r0,LSR #60x0800060c: 6011 .` STR r1,[r2,#0]0x0800060e: 4770 pG BX lr$d0x08000610: 40021000 ...@ DCD 1073876992$ti.system_clock_120m_hxtalsystem_clock_120m_hxtal0x08000614: 2000 . MOVS r0,#00x08000616: 2100 .! MOVS r1,#00x08000618: 4a3f ?J LDR r2,[pc,#252] ; [0x8000718] = 0x400210000x0800061a: 6812 .h LDR r2,[r2,#0]0x0800061c: f4423280 B..2 ORR r2,r2,#0x100000x08000620: 4b3d =K LDR r3,[pc,#244] ; [0x8000718] = 0x400210000x08000622: 601a .` STR r2,[r3,#0]0x08000624: bf00 .. NOP 0x08000626: 1c40 @. ADDS r0,r0,#10x08000628: 4a3b ;J LDR r2,[pc,#236] ; [0x8000718] = 0x400210000x0800062a: 6812 .h LDR r2,[r2,#0]0x0800062c: f4023100 ...1 AND r1,r2,#0x200000x08000630: b919 .. CBNZ r1,0x800063a ; system_clock_120m_hxtal + 380x08000632: f64f72ff O..r MOV r2,#0xffff0x08000636: 4290 .B CMP r0,r20x08000638: d1f5 .. BNE 0x8000626 ; system_clock_120m_hxtal + 180x0800063a: 4a37 7J LDR r2,[pc,#220] ; [0x8000718] = 0x400210000x0800063c: 6812 .h LDR r2,[r2,#0]0x0800063e: f4023200 ...2 AND r2,r2,#0x200000x08000642: b90a .. CBNZ r2,0x8000648 ; system_clock_120m_hxtal + 520x08000644: bf00 .. NOP 0x08000646: e7fe .. B 0x8000646 ; system_clock_120m_hxtal + 500x08000648: 4a33 3J LDR r2,[pc,#204] ; [0x8000718] = 0x400210000x0800064a: 69d2 .i LDR r2,[r2,#0x1c]0x0800064c: f0425280 B..R ORR r2,r2,#0x100000000x08000650: 4b31 1K LDR r3,[pc,#196] ; [0x8000718] = 0x400210000x08000652: 61da .a STR r2,[r3,#0x1c]0x08000654: 4a31 1J LDR r2,[pc,#196] ; [0x800071c] = 0x400070000x08000656: 6812 .h LDR r2,[r2,#0]0x08000658: f4424240 B.@B ORR r2,r2,#0xc0000x0800065c: 4b2f /K LDR r3,[pc,#188] ; [0x800071c] = 0x400070000x0800065e: 601a .` STR r2,[r3,#0]0x08000660: 4a2d -J LDR r2,[pc,#180] ; [0x8000718] = 0x400210000x08000662: 6852 Rh LDR r2,[r2,#4]0x08000664: 4b2c ,K LDR r3,[pc,#176] ; [0x8000718] = 0x400210000x08000666: 605a Z` STR r2,[r3,#4]0x08000668: 461a .F MOV r2,r30x0800066a: 6852 Rh LDR r2,[r2,#4]0x0800066c: 605a Z` STR r2,[r3,#4]0x0800066e: 461a .F MOV r2,r30x08000670: 6852 Rh LDR r2,[r2,#4]0x08000672: f4426280 B..b ORR r2,r2,#0x4000x08000676: 605a Z` STR r2,[r3,#4]0x08000678: 461a .F MOV r2,r30x0800067a: 6852 Rh LDR r2,[r2,#4]0x0800067c: f4223240 ".@2 BIC r2,r2,#0x300000x08000680: 605a Z` STR r2,[r3,#4]0x08000682: 461a .F MOV r2,r30x08000684: 6852 Rh LDR r2,[r2,#4]0x08000686: f4423240 B.@2 ORR r2,r2,#0x300000x0800068a: 605a Z` STR r2,[r3,#4]0x0800068c: 461a .F MOV r2,r30x0800068e: 6852 Rh LDR r2,[r2,#4]0x08000690: 4b23 #K LDR r3,[pc,#140] ; [0x8000720] = 0xb7c3ffff0x08000692: 401a .@ ANDS r2,r2,r30x08000694: 4b20 K LDR r3,[pc,#128] ; [0x8000718] = 0x400210000x08000696: 605a Z` STR r2,[r3,#4]0x08000698: 461a .F MOV r2,r30x0800069a: 6852 Rh LDR r2,[r2,#4]0x0800069c: 4b21 !K LDR r3,[pc,#132] ; [0x8000724] = 0x83400000x0800069e: 431a .C ORRS r2,r2,r30x080006a0: 4b1d .K LDR r3,[pc,#116] ; [0x8000718] = 0x400210000x080006a2: 605a Z` STR r2,[r3,#4]0x080006a4: 461a .F MOV r2,r30x080006a6: 6812 .h LDR r2,[r2,#0]0x080006a8: f0427280 B..r ORR r2,r2,#0x10000000x080006ac: 601a .` STR r2,[r3,#0]0x080006ae: bf00 .. NOP 0x080006b0: 4a19 .J LDR r2,[pc,#100] ; [0x8000718] = 0x400210000x080006b2: 6812 .h LDR r2,[r2,#0]0x080006b4: f0027200 ...r AND r2,r2,#0x20000000x080006b8: 2a00 .* CMP r2,#00x080006ba: d0f9 .. BEQ 0x80006b0 ; system_clock_120m_hxtal + 1560x080006bc: 4a17 .J LDR r2,[pc,#92] ; [0x800071c] = 0x400070000x080006be: 6812 .h LDR r2,[r2,#0]0x080006c0: f4423280 B..2 ORR r2,r2,#0x100000x080006c4: 4b15 .K LDR r3,[pc,#84] ; [0x800071c] = 0x400070000x080006c6: 601a .` STR r2,[r3,#0]0x080006c8: bf00 .. NOP 0x080006ca: 4a14 .J LDR r2,[pc,#80] ; [0x800071c] = 0x400070000x080006cc: 6852 Rh LDR r2,[r2,#4]0x080006ce: f4023280 ...2 AND r2,r2,#0x100000x080006d2: 2a00 .* CMP r2,#00x080006d4: d0f9 .. BEQ 0x80006ca ; system_clock_120m_hxtal + 1820x080006d6: 4a11 .J LDR r2,[pc,#68] ; [0x800071c] = 0x400070000x080006d8: 6812 .h LDR r2,[r2,#0]0x080006da: f4423200 B..2 ORR r2,r2,#0x200000x080006de: 4b0f .K LDR r3,[pc,#60] ; [0x800071c] = 0x400070000x080006e0: 601a .` STR r2,[r3,#0]0x080006e2: bf00 .. NOP 0x080006e4: 4a0d .J LDR r2,[pc,#52] ; [0x800071c] = 0x400070000x080006e6: 6852 Rh LDR r2,[r2,#4]0x080006e8: f4023200 ...2 AND r2,r2,#0x200000x080006ec: 2a00 .* CMP r2,#00x080006ee: d0f9 .. BEQ 0x80006e4 ; system_clock_120m_hxtal + 2080x080006f0: 4a09 .J LDR r2,[pc,#36] ; [0x8000718] = 0x400210000x080006f2: 6852 Rh LDR r2,[r2,#4]0x080006f4: f0220203 "... BIC r2,r2,#30x080006f8: 4b07 .K LDR r3,[pc,#28] ; [0x8000718] = 0x400210000x080006fa: 605a Z` STR r2,[r3,#4]0x080006fc: 461a .F MOV r2,r30x080006fe: 6852 Rh LDR r2,[r2,#4]0x08000700: f0420202 B... ORR r2,r2,#20x08000704: 605a Z` STR r2,[r3,#4]0x08000706: bf00 .. NOP 0x08000708: 4a03 .J LDR r2,[pc,#12] ; [0x8000718] = 0x400210000x0800070a: 6852 Rh LDR r2,[r2,#4]0x0800070c: f0020208 .... AND r2,r2,#80x08000710: 2a00 .* CMP r2,#00x08000712: d0f9 .. BEQ 0x8000708 ; system_clock_120m_hxtal + 2440x08000714: 4770 pG BX lr$d0x08000716: 0000 .. DCW 00x08000718: 40021000 ...@ DCD 10738769920x0800071c: 40007000 .p.@ DCD 10737704960x08000720: b7c3ffff .... DCD 30830755830x08000724: 08340000 ..4. DCD 137625600$ti.system_clock_configsystem_clock_config0x08000728: b510 .. PUSH {r4,lr}0x0800072a: f7ffff73 ..s. BL system_clock_120m_hxtal ; 0x80006140x0800072e: bd10 .. POP {r4,pc}$d.realdataRegion$$Table$$Base0x08000730: 08000750 P... DCD 1342196000x08000734: 20000000 ... DCD 5368709120x08000738: 00000024 $... DCD 360x0800073c: 08000368 h... DCD 1342186000x08000740: 08000774 t... DCD 1342196360x08000744: 20000024 $.. DCD 5368709480x08000748: 00000404 .... DCD 10280x0800074c: 08000378 x... DCD 134218616Region$$Table$$Limit
从现在开始,开始逐段汇编代码分析。
在看到过程中前面的是作为入口地址,相当于是一种提示,我们主要是关心的是汇编语言。
1.3.3.1 初始化向量表
__Vectors0x08000000: 20000428 (.. DCD 5368719760x08000004: 08000145 E... DCD 1342180530x08000004:: 0800014d M... DCD 1342180610x0800000c: 0800014f O... DCD 134218063
.
.
.
.0x0800011c: 0800015f _... DCD 1342180790x08000120: 0800015f _... DCD 1342180790x08000124: 0800015f _... DCD 1342180790x08000128: 0800015f _... DCD 1342180790x0800012c: 0800015f _... DCD 134218079
DCD:ARM汇编中的一种伪指令,用于数据定义,主要用于在内存中分配连续的32位字(4字节)存储单元,并初始化为指定的数值或地址。也就是我们将我们常用的中断放到前面的地址中,
最前面这一列0x0800 0000、0x08000004、0x08000004以及后续的,全部是用来存储的,就是我们房间,这些数字就是房间的门牌号,是实实在在的物理空间,紧挨着的就是表示存的内容,例如:第一行:地址0x08000000存储的数据是: 20000428;
第二行:地址0x08000004存储的数据是: 08000145;
第三行:地址0x08000004存储的数据是: 0800014d; 这些数据在这里可以认为是我们自己写的中断函数的函数的入口,例如我写了一个中断函数,我们就需要再内存中找到一个空间存放这个中断函数,那么存的地方需要一个入口地址,这样我们才能找到他,而DCD在这里的作用就在这里。例如从其他工程中拿到的
DCD TIMER4_IRQHandler ; 66:TIMER4
DCD SPI2_IRQHandler ; 67:SPI2
DCD UART3_IRQHandler ; 68:UART3
DCD UART4_IRQHandler ; 69:UART4
DCD TIMER5_IRQHandler ; 70:TIMER5
DCD TIMER6_IRQHandler ; 71:TIMER6
DCD DMA1_Channel0_IRQHandler ; 72:DMA1 Channel0
DCD DMA1_Channel1_IRQHandler ; 73:DMA1 Channel1
DCD DMA1_Channel2_IRQHandler ; 74:DMA1 Channel2
DCD DMA1_Channel3_4_IRQHandler ; 75:DMA1 Channel3 and Channel40x08000108: 08000f95 .... DCD 134221717
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
可以看出第一行表示的是TIMER4中断,而下面的这一段表示的就是ARM执行DCD的结果,可以看出
地址0x08000108,存储的就是我们写的TIMER4函数的入口地址:08000f95
通过这个截图可以明显的看出函数的入口地址就是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(由编译器自动处理)。
- 函数代码按 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_stk0x08000130: f8dfd00c .... LDR sp,__lit__00000000 ; [0x8000140] = 0x20000428.ARM.Collect$$$$00000004_main_scatterload0x08000134: f000f818 .... BL __scatterload ; 0x8000168.ARM.Collect$$$$00000008.ARM.Collect$$$$0000000A.ARM.Collect$$$$0000000B__main_after_scatterload_main_clock_main_cpp_init_main_init0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x800044b0x0800013a: 4700 .G BX r0$d0x0800013c: 0800044b K... DCD 134218827.ARM.Collect$$$$00002712__lit__00000000.ARM.Collect$$$$0000000D.ARM.Collect$$$$0000000F__rt_final_cpp__rt_final_exit0x08000140: 20000428 (.. DCD 536871976$t.text$v0Reset_Handler0x08000144: 4806 .H LDR r0,[pc,#24] ; [0x8000160] = 0x80002690x08000146: 4780 .G BLX r00x08000148: 4806 .H LDR r0,[pc,#24] ; [0x8000164] = 0x80001310x0800014a: 4700 .G BX r0NMI_Handler0x0800014c: e7fe .. B NMI_Handler ; 0x800014cHardFault_Handler0x0800014e: e7fe .. B HardFault_Handler ; 0x800014eMemManage_Handler0x08000150: e7fe .. B MemManage_Handler ; 0x8000150BusFault_Handler0x08000152: e7fe .. B BusFault_Handler ; 0x8000152UsageFault_Handler0x08000154: e7fe .. B UsageFault_Handler ; 0x8000154SVC_Handler0x08000156: e7fe .. B SVC_Handler ; 0x8000156DebugMon_Handler0x08000158: e7fe .. B DebugMon_Handler ; 0x8000158PendSV_Handler0x0800015a: e7fe .. B PendSV_Handler ; 0x800015aSysTick_Handler0x0800015c: e7fe .. B SysTick_Handler ; 0x800015c
首先映入眼帘的是_ _ main函数,注意这个main函数不是我们编写代码的main函数呐。
需要注意的是:
这些代码在地址空间上是连续排列的,但执行流程并非完全顺序执行。关键点在于其中包含跳转指令(BL
、BX
)和硬件复位机制,导致执行路径发生分支。
启动入口:硬件强制跳转(非顺序起点)
-
硬件复位后,CPU 直接从中断向量表中加载
Reset_Handler
的地址(位于0x08000004
),并跳转到该地址(0x08000144
)。 -
因此,代码的第一条执行指令是
Reset_Handler
(0x08000144
),而非地址最低的0x08000130
。 -
物理地址连续:代码在 Flash 中按地址顺序存储(
0x08000130 → 0x0800014A
)。 -
执行流非线性:
- 硬件强制跳转至
Reset_Handler
(0x08000144
)。 Reset_Handler
和__main
中的跳转指令(BLX
/BX
)主动切换执行路径。
- 硬件强制跳转至
那么我们就直接看下面这两段段代码
这段代码存在于我们的工程启动文件:Reset_Handler PROCEXPORT Reset_Handler [WEAK]IMPORT SystemInitIMPORT __mainLDR R0, =SystemInitBLX R0LDR R0, =__mainBX R0ENDP
这段代码存在我们编译后的汇编语言。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
我们直接就从汇编语言开始分析:
从上面的启动入口可以知道,硬件会直接跳转到0x08000144,这就是单片机复位后的第二件事。
至于第一件事,现在暂时按下不表,估计要到下一篇文章在详细说了,因为第一件事包含的内容较多。如果您看到这里,还请点点赞,您的点赞是我长久分享知识的动力,言归正传!。
由于是硬件自动跳转,那么这个时候执行的就是:
0x08000144: 4806 .H LDR r0,[pc,#24] ; [0x8000160] = 0x8000269
这段代码的作用就是取出:SystemInit地址(0x0800269)
0x08000146: 4780 .G BLX r0 @调用SystemInit()
我们此时看一下SystemInit()函数的入口地址以及怎么执行的,我们先不看代码自己可以猜一下第一行和最后一行语句是什么?
第一行是PUSH
最后一行是POP
至于为什么我相信你现在已经有答案了。
SystemInit0x08000268: b508 .. PUSH {r3,lr}0x0800026a: 4826 &H LDR r0,[pc,#152] ; [0x8000304] = 0xe000ed880x0800026c: 6800 .h LDR r0,[r0,#0]0x0800026e: f4400070 @.p. ORR r0,r0,#0xf000000x08000272: 4924 $I LDR r1,[pc,#144] ; [0x8000304] = 0xe000ed880x08000274: 6008 .` STR r0,[r1,#0]0x08000276: 4824 $H LDR r0,[pc,#144] ; [0x8000308] = 0x400210000x08000278: 6800 .h LDR r0,[r0,#0]0x0800027a: f0400001 @... ORR r0,r0,#10x0800027e: 4922 "I LDR r1,[pc,#136] ; [0x8000308] = 0x400210000x08000280: 6008 .` STR r0,[r1,#0]0x08000282: bf00 .. NOP 0x08000284: 4820 H LDR r0,[pc,#128] ; [0x8000308] = 0x400210000x08000286: 6800 .h LDR r0,[r0,#0]0x08000288: f0000002 .... AND r0,r0,#20x0800028c: 2800 .( CMP r0,#00x0800028e: d0f9 .. BEQ 0x8000284 ; SystemInit + 280x08000290: bf00 .. NOP 0x08000292: 481d .H LDR r0,[pc,#116] ; [0x8000308] = 0x400210000x08000294: 6840 @h LDR r0,[r0,#4]0x08000296: f0400080 @... ORR r0,r0,#0x800x0800029a: 491b .I LDR r1,[pc,#108] ; [0x8000308] = 0x400210000x0800029c: 6048 H` STR r0,[r1,#4]0x0800029e: 2000 . MOVS r0,#00x080002a0: 9000 .. STR r0,[sp,#0]0x080002a2: e002 .. B 0x80002aa ; SystemInit + 660x080002a4: 9800 .. LDR r0,[sp,#0]0x080002a6: 1c40 @. ADDS r0,r0,#10x080002a8: 9000 .. STR r0,[sp,#0]0x080002aa: 9800 .. LDR r0,[sp,#0]0x080002ac: 2850 P( CMP r0,#0x500x080002ae: d3f9 .. BCC 0x80002a4 ; SystemInit + 600x080002b0: 4815 .H LDR r0,[pc,#84] ; [0x8000308] = 0x400210000x080002b2: 6840 @h LDR r0,[r0,#4]0x080002b4: f0400090 @... ORR r0,r0,#0x900x080002b8: 4913 .I LDR r1,[pc,#76] ; [0x8000308] = 0x400210000x080002ba: 6048 H` STR r0,[r1,#4]0x080002bc: 2000 . MOVS r0,#00x080002be: 9000 .. STR r0,[sp,#0]0x080002c0: e002 .. B 0x80002c8 ; SystemInit + 960x080002c2: 9800 .. LDR r0,[sp,#0]0x080002c4: 1c40 @. ADDS r0,r0,#10x080002c6: 9000 .. STR r0,[sp,#0]0x080002c8: 9800 .. LDR r0,[sp,#0]0x080002ca: 2850 P( CMP r0,#0x500x080002cc: d3f9 .. BCC 0x80002c2 ; SystemInit + 900x080002ce: bf00 .. NOP 0x080002d0: 480d .H LDR r0,[pc,#52] ; [0x8000308] = 0x400210000x080002d2: 6840 @h LDR r0,[r0,#4]0x080002d4: f0200003 ... BIC r0,r0,#30x080002d8: 490b .I LDR r1,[pc,#44] ; [0x8000308] = 0x400210000x080002da: 6048 H` STR r0,[r1,#4]0x080002dc: 4608 .F MOV r0,r10x080002de: 6800 .h LDR r0,[r0,#0]0x080002e0: 490a .I LDR r1,[pc,#40] ; [0x800030c] = 0xfef6ffff0x080002e2: 4008 .@ ANDS r0,r0,r10x080002e4: 4908 .I LDR r1,[pc,#32] ; [0x8000308] = 0x400210000x080002e6: 6008 .` STR r0,[r1,#0]0x080002e8: f44f001f O... MOV r0,#0x9f00000x080002ec: 6088 .` STR r0,[r1,#8]0x080002ee: 4608 .F MOV r0,r10x080002f0: 6800 .h LDR r0,[r0,#0]0x080002f2: f4202080 .. BIC r0,r0,#0x400000x080002f6: 6008 .` STR r0,[r1,#0]0x080002f8: 2000 . MOVS r0,#00x080002fa: 6048 H` STR r0,[r1,#4]0x080002fc: 62c8 .b STR r0,[r1,#0x2c]0x080002fe: f000fa13 .... BL system_clock_config ; 0x80007280x08000302: 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_init
0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x800044b
0x0800013a: 4700 .G BX r0
main0x0800044a: f7fffe9f .... BL DelayInit ; 0x800018c0x0800044e: f7fffedd .... BL LedDrvInit ; 0x800020c0x08000452: e021 !. B 0x8000498 ; main + 780x08000454: 2000 . MOVS r0,#00x08000456: f7ffff71 ..q. BL TurnOnLed ; 0x800033c0x0800045a: f44f707a O.zp MOV r0,#0x3e80x0800045e: f7fffeb3 .... BL DelayNms ; 0x80001c80x08000462: 2001 . MOVS r0,#10x08000464: f7ffff6a ..j. BL TurnOnLed ; 0x800033c0x08000468: f44f707a O.zp MOV r0,#0x3e80x0800046c: f7fffeac .... BL DelayNms ; 0x80001c80x08000470: 2002 . MOVS r0,#20x08000472: f7ffff63 ..c. BL TurnOnLed ; 0x800033c0x08000476: f44f707a O.zp MOV r0,#0x3e80x0800047a: f7fffea5 .... BL DelayNms ; 0x80001c80x0800047e: 2000 . MOVS r0,#00x08000480: f7ffff46 ..F. BL TurnOffLed ; 0x80003100x08000484: 2001 . MOVS r0,#10x08000486: f7ffff43 ..C. BL TurnOffLed ; 0x80003100x0800048a: 2002 . MOVS r0,#20x0800048c: f7ffff40 ..@. BL TurnOffLed ; 0x80003100x08000490: f44f707a O.zp MOV r0,#0x3e80x08000494: f7fffe98 .... BL DelayNms ; 0x80001c80x08000498: e7dc .. B 0x8000454 ; main + 100x0800049a: 0000 .. MOVS r0,r0
可以看出我们main 函数入口地址确实是0x0800044a。
在看另外一个工程
_main_init
0x08000138: 4800 .H LDR r0,[pc,#0] ; [0x800013c] = 0x8001f5b
0x0800013a: 4700 .G BX r0
main0x08001f5a: f7fefdcf .... BL DrvInit ; 0x8000afc0x08001f5e: f7fefcf5 .... BL AppInit ; 0x800094c0x08001f62: e001 .. B 0x8001f68 ; main + 140x08001f64: f7fff844 ..D. BL TaskHandler ; 0x8000ff00x08001f68: e7fc .. B 0x8001f64 ; main + 100x08001f6a: 0000 .. MOVS r0,r0
可以看出我们main 函数入口地址确实是0x08001f5a。
以上就是ARM核启动流程的汇编代码分析。
文章源码获取方式:
如果您对本文的源码感兴趣,欢迎在评论区留下您的邮箱地址。我会在空闲时间整理相关代码,并通过邮件发送给您。由于个人时间有限,发送可能会有一定延迟,请您耐心等待。同时,建议您在评论时注明具体的需求或问题,以便我更好地为您提供针对性的帮助。
【版权声明】
本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议。这意味着您可以自由地共享(复制、分发)和改编(修改、转换)本文内容,但必须遵守以下条件:
署名:您必须注明原作者(即本文博主)的姓名,并提供指向原文的链接。
相同方式共享:如果您基于本文创作了新的内容,必须使用相同的 CC 4.0 BY-SA 协议进行发布。
感谢您的理解与支持!如果您有任何疑问或需要进一步协助,请随时在评论区留言。