0%

Hardfault 调试实例

ARM hardfault 调试的一些例子。

非对齐的访问

rf_pin_sleep 函数,在按键长按回调中调用没有异常,但是在 TIM_SLP 定时器回调中就会挂掉,调试发现是触发了 Hardfault。

1
2
3
4
5
6
7
void rf_pin_sleep(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_LineCmd = DISABLE;
EXTI_Init(&EXTI_InitStructure);
}

其实按键长按回调也是定时器的回调,有什么区别呢。

用 Ozone 跟进看可能的异常是 UNALIGN_TRA,也就是非对齐的访问。

image-20201122230410929

EXTI_Init 对于 DISABLE 的处理如下:

1
2
3
4
5
6
7
8
9
10
void EXTI_Init(EXTI_InitTypeDef *EXTI_InitStruct)
{
uint32_t tmp = (uint32_t)EXTI_BASE;
...
tmp = (uint32_t)EXTI_BASE;
tmp += EXTI_InitStruct->EXTI_Mode;
/* Disable the selected external lines */
*(__IO uint32_t *)tmp &= ~EXTI_InitStruct->EXTI_Line;
...
}

注意,这里有个 EXTI_Mode 并没有在 EXTI_InitStructure 变量中赋值,EXTI_InitStructure 是个局部变量,位于栈上,那么 EXTI_Mode 也就是个不确定的值。

故而在不同的函数中调用此函数表现不一,若 EXTI_Mode 的值刚好不对齐 word,那么就会导致 Hardfault。

坚持原创技术分享,您的支持将鼓励我继续创作!