一、项目概况:
基于STM32F103,使用HAL库进行开发,自己开发设计的boot加app。使用freertos操作系统。
二、问题描述:
app程序中中断向量、程序起始地址等均已经做了正确配置。但是跳转到APP后,程序反复复位重启。
三、具体分析:
调试发现程序卡死在调用HAL_Delay的时候。 uwTick 一直没有更新,所有导致超时后,看门狗复位重启。
SysTick中断无法更新uwTick计数器的根本原因在于ARM Cortex-M内核的中断屏蔽机制(PRIMASK/FAULTMASK)未解除,导致SysTick中断请求(IRQ)或其关联的异常(如SysTick_Handler)无法被内核响应。以下是详细分析:
1. PRIMASK屏蔽全局中断(CPSIE I的作用)
ARM Cortex-M内核通过 PRIMASK 寄存器控制全局中断的使能状态:
PRIMASK=1:屏蔽所有可配置优先级的中断(包括SysTick、外部中断等)。
PRIMASK=0:允许中断请求被响应。
__ASM("CPSIE I") 是一条ARM汇编指令,用于清除PRIMASK寄存器的I位(即关闭全局中断屏蔽)。若未执行此指令:
SysTick定时器产生的中断请求(IRQ)会被屏蔽,无法触发中断服务程序(SysTick_Handler)。
HAL_IncTick()(通常在SysTick_Handler中调用)不会被执行,导致全局变量 uwTick 停滞 。
2. FAULTMASK屏蔽系统异常
ARM Cortex-M内核的 FAULTMASK 寄存器用于屏蔽所有异常(包括SysTick异常):
FAULTMASK=1:屏蔽所有异常(如MemManage、BusFault、SysTick等)。
FAULTMASK=0:允许异常被响应。
__set_FAULTMASK(0) 通过CMSIS函数将FAULTMASK寄存器清零,确保异常(包括SysTick)可以被处理。若未清除FAULTMASK:
即使SysTick中断请求未被PRIMASK屏蔽,其对应的异常处理流程仍会被阻止。
SysTick_Handler无法执行,uwTick 不会递增 。
3. SysTick中断的工作机制依赖中断使能
SysTick定时器的工作流程如下:
定时器计数到0 → 触发SysTick异常(属于系统异常,编号为15)。
内核检查PRIMASK和FAULTMASK:
若其中任意一个被置位,异常处理流程(调用SysTick_Handler)将被阻断。
执行SysTick_Handler → 调用 HAL_IncTick() →uwTick 递增。
如果未显式开启全局中断(PRIMASK=1)或FAULTMASK=1,则步骤2会失败,导致流程中断 。
4. Bootloader跳转到APP时的上下文残留
在从Bootloader跳转到APP的过程中,若未显式重置中断屏蔽状态,可能继承Bootloader的配置:
- Bootloader可能关闭了全局中断(例如在跳转前通过
__ASM("CPSID I")关中断)。 - Bootloader可能设置了FAULTMASK=1(例如在关键代码段中屏蔽异常)。
若APP未重新开启中断和异常,上述状态会残留至APP执行阶段,导致SysTick中断无法响应
5. HAL_Delay()的实现依赖uwTick
HAL_Delay(uint32_t Delay) 的实现依赖全局变量 uwTick:
uint32_t tickstart = HAL_GetTick();
while ((HAL_GetTick() - tickstart) < Delay)
{
if (Timeout != HAL_MAX_DELAY)
{
// 超时检测逻辑
}
}
若SysTick中断未触发(导致 uwTick 不递增),循环条件 (HAL_GetTick() - tickstart) < Delay 永远为真,程序卡死在此处 。
6. 验证与解决方法
验证步骤
- 在APP启动代码中插入调试代码,读取
PRIMASK和FAULTMASK的值:uint32_t primask = __get_PRIMASK(); // 读取PRIMASK uint32_t faultmask = __get_FAULTMASK(); // 读取FAULTMASK - 若
primask != 0或faultmask != 0,则中断或异常仍被屏蔽。
解决方案
在调用 HAL_Init() 和 HAL_InitTick() 之后,显式开启全局中断和异常:
HAL_Init();
HAL_InitTick(); // 确保SysTick已初始化
__ASM("CPSIE I"); // 清除PRIMASK,开启全局中断
__set_FAULTMASK(0); //

9930

被折叠的 条评论
为什么被折叠?



