STM32H7+FreeRTOS下指针强制转换引发HardFault问题咨询
STM32H7 FreeRTOS线程中指针强制转换触发HardFault的原因分析
我在Atollic TrueSTUDIO for STM32环境下开发STM32H7项目,采用C语言结合FreeRTOS开发。
常规运行正常的代码
Ui08 *pointerSomething; Ui64 localVariable; pointerSomething=&addressOfSomething; localVariable = *(Ui64*)(pointerSomething);
这段代码在常规场景下能正常执行。
出问题的FreeRTOS线程代码
// thread begin Ui08 *pointerSomething; Ui64 localVariable; case 3: pointerSomething=&addressOfSomething; localVariable = *(Ui64*)(pointerSomething); break; // thread end
首次进入case 3时运行正常,但第二次执行到localVariable = *(Ui64*)(pointerSomething);时触发HardFault。
解决方法:改用memcpy
// thread begin Ui08 *pointerSomething; Ui64 localVariable; case 3: pointerSomething=&addressOfSomething; memcpy( &localVariable, pointerSomething, sizeof(localVariable) ); break; // thread end
改用memcpy后,HardFault问题消失。
问题原因解析
核心原因是STM32H7搭载的ARM Cortex-M7内核对内存访问有严格的对齐要求,指针强制转换的写法直接违反了这一规则:
- Cortex-M7要求64位数据(Ui64类型)的访问地址必须是8字节对齐的。当你把
Ui08*强制转换成Ui64*并直接解引用时,如果addressOfSomething的实际地址不满足8字节对齐,就会触发内核的对齐错误陷阱,进而引发HardFault。 - 常规代码和首次进入case时正常,是巧合导致的:要么是常规场景下
addressOfSomething的地址刚好符合对齐要求,要么是编译器优化时自动调整了内存布局;而FreeRTOS线程的栈调度机制或编译器对线程代码的优化策略不同,第二次执行时addressOfSomething的地址处于非对齐状态,触发了问题。 memcpy能解决问题,是因为它是按字节逐位拷贝数据,不涉及内核要求的对齐访问规则,无论地址是否对齐,都能安全完成数据传输,避开了对齐检查。
额外注意:
- 这种指针强制转换的写法本身属于C语言的未定义行为,编译器不会帮你检查对齐合法性,在不同环境、不同优化级别下可能出现各种不可预期的问题。
- 虽然可以通过配置SCB->CCR寄存器的UNALIGN_TRP位关闭非对齐访问陷阱,但这会降低系统性能,且不是通用解决方案,更推荐使用
memcpy这种符合C标准的写法处理非对齐数据。
内容的提问来源于stack exchange,提问作者mryldz
相关产品推荐
相关产品推荐

