Chenyj Space
返回博客
·25 分钟

ARM Cortex-M 架构深入解析:中断、低功耗与系统启动

ARMCortex-M中断低功耗启动流程嵌入式

ARM Cortex-M 架构概述

ARM Cortex-M 是 ARM 公司专门为微控制器设计的处理器内核,具有低功耗、高性能、低成本的特点。

1. Cortex-M 系列对比

系列流水线性能特点典型应用
Cortex-M02级0.9 DMIPS/MHz最小、最低功耗传感器、简单控制
Cortex-M0+2级0.93 DMIPS/MHzM0 增强版IoT、可穿戴
Cortex-M33级1.25 DMIPS/MHz性能平衡通用 MCU
Cortex-M43级1.25 DMIPS/MHzDSP + FPU信号处理、电机控制
Cortex-M76级2.14 DMIPS/MHz高性能图像处理、音频
Cortex-M333级1.5 DMIPS/MHzTrustZone安全应用

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长时间待机
StandbyWKUP引脚最低几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 等常用协议的原理和实现。