·25 分钟
ARM Cortex-M 架构深入解析:中断、低功耗与系统启动
ARMCortex-M中断低功耗启动流程嵌入式
ARM Cortex-M 架构概述
ARM Cortex-M 是 ARM 公司专门为微控制器设计的处理器内核,具有低功耗、高性能、低成本的特点。
1. Cortex-M 系列对比
| 系列 | 流水线 | 性能 | 特点 | 典型应用 |
|---|---|---|---|---|
| Cortex-M0 | 2级 | 0.9 DMIPS/MHz | 最小、最低功耗 | 传感器、简单控制 |
| Cortex-M0+ | 2级 | 0.93 DMIPS/MHz | M0 增强版 | IoT、可穿戴 |
| Cortex-M3 | 3级 | 1.25 DMIPS/MHz | 性能平衡 | 通用 MCU |
| Cortex-M4 | 3级 | 1.25 DMIPS/MHz | DSP + FPU | 信号处理、电机控制 |
| Cortex-M7 | 6级 | 2.14 DMIPS/MHz | 高性能 | 图像处理、音频 |
| Cortex-M33 | 3级 | 1.5 DMIPS/MHz | TrustZone | 安全应用 |
2. 处理器模式
code
┌─────────────────────────────────────┐
│ Cortex-M 处理器 │
├─────────────────────────────────────┤
│ 线程模式 (Thread Mode) │
│ ├── 特权级别 (Privileged) │
│ └── 非特权级别 (Unprivileged) │
├─────────────────────────────────────┤
│ 处理模式 (Handler Mode) │
│ └── 始终为特权级别 │
└─────────────────────────────────────┘
3. 寄存器组
c
// Cortex-M 寄存器
// 通用寄存器
R0-R12 // 通用数据寄存器
SP (R13) // 栈指针 (MSP/PSP)
LR (R14) // 链接寄存器
PC (R15) // 程序计数器
// 特殊寄存器
xPSR // 程序状态寄存器
PRIMASK // 中断屏蔽寄存器
FAULTMASK // 故障屏蔽寄存器
BASEPRI // 基本优先级寄存器
CONTROL // 控制寄存器
中断系统
1. NVIC 嵌套向量中断控制器
c
// NVIC 核心特性
// - 支持 240 个中断
// - 可配置优先级(0-255)
// - 支持中断嵌套
// - 自动保存/恢复上下文
// NVIC 寄存器
#define NVIC_ISER0 *((volatile uint32_t *)0xE000E100) // 中断使能
#define NVIC_ICER0 *((volatile uint32_t *)0xE000E180) // 中断清除
#define NVIC_ISPR0 *((volatile uint32_t *)0xE000E200) // 中断挂起
#define NVIC_ICPR0 *((volatile uint32_t *)0xE000E280) // 中断清除挂起
#define NVIC_IABR0 *((volatile uint32_t *)0xE000E300) // 中断活动
#define NVIC_IPR0 *((volatile uint32_t *)0xE000E400) // 中断优先级
2. 优先级配置
c
// 优先级分组
// STM32 使用 4 位优先级,分为抢占优先级和子优先级
typedef enum {
NVIC_PriorityGroup_0 = 0x700, // 0 位抢占,4 位子优先级
NVIC_PriorityGroup_1 = 0x600, // 1 位抢占,3 位子优先级
NVIC_PriorityGroup_2 = 0x500, // 2 位抢占,2 位子优先级
NVIC_PriorityGroup_3 = 0x400, // 3 位抢占,1 位子优先级
NVIC_PriorityGroup_4 = 0x300 // 4 位抢占,0 位子优先级
} NVIC_PriorityGroupConfig;
// 配置优先级分组
void NVIC_Configuration(void) {
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
}
// 配置中断优先级
void EXTI0_NVIC_Config(void) {
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
3. 中断处理流程
code
中断发生
↓
处理器自动保存寄存器
(R0-R3, R12, LR, PC, xPSR)
↓
读取中断向量表
↓
跳转到中断服务函数
↓
执行中断处理
↓
执行 BX LR 指令
↓
处理器自动恢复寄存器
↓
返回被中断的程序
4. 中断向量表
c
// 中断向量表定义
__attribute__((section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
// Cortex-M3 核心异常
(void (*)(void))(&_estack), // 初始栈指针
Reset_Handler, // 复位
NMI_Handler, // NMI
HardFault_Handler, // 硬件故障
MemManage_Handler, // 内存管理故障
BusFault_Handler, // 总线故障
UsageFault_Handler, // 使用故障
0, 0, 0, 0, // 保留
SVC_Handler, // SVCall
DebugMon_Handler, // 调试监视器
0, // 保留
PendSV_Handler, // PendSV
SysTick_Handler, // SysTick
// STM32 外部中断
WWDG_IRQHandler, // 窗口看门狗
PVD_IRQHandler, // PVD
TAMPER_IRQHandler, // 侵入检测
RTC_IRQHandler, // RTC
FLASH_IRQHandler, // FLASH
RCC_IRQHandler, // RCC
EXTI0_IRQHandler, // EXTI0
EXTI1_IRQHandler, // EXTI1
EXTI2_IRQHandler, // EXTI2
EXTI3_IRQHandler, // EXTI3
EXTI4_IRQHandler, // EXTI4
// ... 更多中断
};
低功耗模式
1. 低功耗模式对比
| 模式 | 唤醒源 | 功耗 | 唤醒时间 | 典型应用 |
|---|---|---|---|---|
| Sleep | 任意中断 | 最低 | 无延迟 | 等待事件 |
| Stop | 外部中断 | 很低 | 几μs | 长时间待机 |
| Standby | WKUP引脚 | 最低 | 几ms | 电池供电 |
2. Sleep 模式
c
// 进入 Sleep 模式
void enter_sleep_mode(void) {
// 配置 SysTick 定时唤醒
SysTick_Config(SystemCoreClock / 1000); // 1ms 唤醒
// 进入 Sleep 模式
__WFI(); // Wait For Interrupt
}
// SysTick 中断唤醒
void SysTick_Handler(void) {
// 唤醒后执行
static uint32_t count = 0;
count++;
if(count >= 1000) { // 1 秒
count = 0;
// 执行周期任务
}
}
3. Stop 模式
c
// 进入 Stop 模式
void enter_stop_mode(void) {
// 配置唤醒源(外部中断)
EXTI_InitTypeDef EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line0;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
// 配置电压调节器
PWR_VoltageRegulatorConfig(PWR_VoltageRegulator_LowPower);
// 进入 Stop 模式
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
// 唤醒后需要重新配置时钟
SystemClock_Config();
}
4. Standby 模式
c
// 进入 Standby 模式
void enter_standby_mode(void) {
// 使能 WKUP 引脚
PWR_WakeUpPinCmd(ENABLE);
// 清除唤醒标志
PWR_ClearFlag(PWR_FLAG_WU);
// 进入 Standby 模式
PWR_EnterSTANDBYMode();
// 唤醒后相当于复位
}
系统启动流程
1. 启动流程图
code
上电/复位
↓
读取 MSP (主栈指针)
↓
读取 PC (复位向量)
↓
执行 Reset_Handler
↓
SystemInit()
├── 配置时钟
├── 配置 Flash
└── 配置电源
↓
__main()
├── 初始化栈
├── 初始化堆
└── 复制初始化数据
↓
跳转到 main()
2. 启动文件分析
c
; 启动文件 (startup_stm32f10x_md.s)
; 栈和堆定义
Stack_Size EQU 0x00000400 ; 1KB
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
Heap_Size EQU 0x00000200 ; 512B
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
; 复位处理函数
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
; 中断处理函数
NMI_Handler PROC
EXPORT NMI_Handler [WEAK]
B .
ENDP
HardFault_Handler PROC
EXPORT HardFault_Handler [WEAK]
B .
ENDP
3. SystemInit 函数
c
// SystemInit 函数实现
void SystemInit(void) {
// 复位 RCC 寄存器
RCC->CR |= (uint32_t)0x00000001;
RCC->CFGR &= (uint32_t)0xF0FF0000;
RCC->CR &= (uint32_t)0xFEF6FFFF;
RCC->CR &= (uint32_t)0xFFFBFFFF;
RCC->CFGR &= (uint32_t)0xFF80FFFF;
RCC->CIR = 0x009F0000;
// 配置向量表
SCB->VTOR = FLASH_BASE | 0x0;
// 配置时钟
SetSysClock();
}
调试接口
1. SWD 调试接口
c
// SWD 引脚配置
// SWDIO - PA13
// SWCLK - PA14
// SWD 优势
// - 只需 2 根线
// - 支持全功能调试
// - 速度可达 50MHz
2. 调试寄存器
c
// CoreSight 调试组件
#define DBGMCU_CR *((volatile uint32_t *)0xE0042004)
#define DBGMCU_IDCODE *((volatile uint32_t *)0xE0042000)
// 调试功能
void debug_init(void) {
// 使能调试时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_DBGMCU, ENABLE);
// 配置调试选项
DBGMCU_CR |= DBGMCU_CR_DBG_SLEEP;
DBGMCU_CR |= DBGMCU_CR_DBG_STOP;
DBGMCU_CR |= DBGMCU_CR_DBG_STANDBY;
}
3. 断点和观察点
c
// 硬件断点
// Cortex-M3 支持最多 8 个硬件断点
// 数据观察点
// 观察变量变化
// 例如:观察变量 count 的变化
// 在调试器中设置观察点:&count
故障处理
1. 故障类型
c
// 故障类型
typedef enum {
HARD_FAULT = 0,
MEM_MANAGE_FAULT,
BUS_FAULT,
USAGE_FAULT
} FaultType_t;
// 故障状态寄存器
#define SCB_HFSR *((volatile uint32_t *)0xE000ED2C)
#define SCB_CFSR *((volatile uint32_t *)0xE000ED28)
#define SCB_MMAR *((volatile uint32_t *)0xE000ED34)
#define SCB_BFAR *((volatile uint32_t *)0xE000ED38)
2. 故障处理函数
c
// 硬件故障处理
void HardFault_Handler(void) {
// 读取故障状态
uint32_t hfsr = SCB_HFSR;
uint32_t cfsr = SCB_CFSR;
// 分析故障原因
if(hfsr & (1 << 30)) {
// 调试事件
// ...
}
if(hfsr & (1 << 1)) {
// 向量表读取错误
// ...
}
// 进入无限循环
while(1);
}
// 内存管理故障处理
void MemManage_Handler(void) {
// 读取故障地址
uint32_t mmfar = SCB_MMAR;
// 分析故障原因
// ...
while(1);
}
下一篇
接下来我们将深入探讨嵌入式通信协议,包括 I2C、SPI、UART 等常用协议的原理和实现。