Cortex-M系列:可以不自己写汇编启动代码,因为芯片厂商提供了完整的启动文件,但理解汇编对调试和优化很重要。
**Cortex-A系列:**通常需要懂汇编启动原理,但实际开发中常使用现成的bootloader(如U-Boot),学习时必须自己写才能理解启动过程。
| 特性 | ARM Cortex-M系列(如STM32) | ARM Cortex-A系列 (如i.MX** 6ULL)** |
|---|---|---|
| 典型应用 | 单片机、实时控制 | 应用处理器、Linux系统 |
| 启动复杂度 | 相对简单 | 非常复杂 |
| 是否需要汇编 | 通常需要一点 | 通常需要 |
| 为什么需要汇编启动文件 | 设置堆栈、向量表 | 设置异常向量、MMU、Cache等 |
1. Cortex-M系列(如STM32)
通常的启动流程:
/* startup_stm32fxxx.s (STM32标准启动文件) */
.section .isr_vector /* 中断向量表 */
.word _estack /* 栈顶地址 */
.word Reset_Handler /* 复位处理函数 */
.word NMI_Handler /* NMI处理函数 */
.word HardFault_Handler
/* ... 其他中断向量 */
.section .text
Reset_Handler:
/* 1. 设置堆栈指针 */
ldr sp, =_estack
/* 2. 初始化.data段 */
bl SystemInit /* 跳到C语言的SystemInit() */
/* 3. 跳转到main */
bl main
如STM32,为什么觉得"不用写":
-
芯片厂商提供现成的启动文件(如
startup_stm32f103xe.s) -
IDE自动包含这个文件
-
你可以不用修改直接使用
-
但本质上还是有汇编文件
2. Cortex-A系列(如i.MX 6ULL)
需要更多汇编,
因为 更复杂的启动任务:
/* start.S (U-Boot或裸机程序) */
.globl _start
_start:
/* 1. 设置异常向量表 */
b reset /* 复位异常 */
b undefined_instruction
b software_interrupt
b prefetch_abort
b data_abort
b not_used
b irq
b fiq
reset:
/* 2. 设置处理器模式 */
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x13 /* 进入SVC模式 */
msr cpsr, r0
/* 3. 设置堆栈 */
ldr sp, =0x87800000
/* 4. 清除BSS段 */
bl clear_bss
/* 5. 跳转到C代码 */
bl main
Cortex-A系列 需要汇编启动文件的原因:
-
异常向量表必须由汇编设置(固定地址)
-
处理器模式切换(SVC、IRQ等)
-
MMU/Cache初始化(Linux需要)
-
多核启动(A系列常有多核)
Cortex-M启动(厂商提供 汇编启动文件):
// main.c可以直接写:
#include "stm32f1xx.h"
int main(void) {
HAL_Init(); // 厂商库初始化
SystemClock_Config(); // 时钟配置
// 用户的代码...
while(1);
}
// ↑ 看起来没有汇编,其实在链接时包含了startup_stm32f1xx.s
Cortex-A启动(自己编写 汇编启动文件):
// 必须先写start.S,然后才能写:
int main(void) {
// 这里才能正常用C语言
uart_init();
printf("Hello i.MX6ULL\n");
return 0;
}
Cortex-M 与 Cortex-A 技术根源差异:
Cortex-M的设计理念:
-
简化,让单片机开发更简单
-
硬件自动完成更多(如向量表重定位)
-
统一的存储映射(代码、数据都在同一地址空间)
Cortex-A的设计理念:
-
灵活,适应复杂应用
-
需要软件控制更多(如MMU虚拟内存)
-
复杂的存储层次(L1/L2 Cache、DDR、Flash)
现代开发的实际状况:
对于Cortex-M:
1. 使用CubeMX生成代码 → 包含startup.s
2. 或者使用Arduino/PlatformIO → 隐藏了底层
3. 大多数情况下不用碰汇编
# 但高级应用(RTOS、性能优化)仍需懂汇编
对于Cortex-A:
1. 使用Bootloader(U-Boot)→ 已有完整的start.S
2. 运行Linux → 内核有自己的head.S
3. 裸机开发 → 必须自己写或借鉴启动代码