问题记录:华大 HC32F460 内存边界禁止非对齐访问
文章更新(2023-11-14)
经过排查,本文所述异常现象并非由「非对齐访问」所致,而是因为 SRAM3 开启 ECC 校验时仅支持以字为单位进行访问。
现象描述
- 程序无法正常启动
- 有时会进入 hard fault 中断
- 有时候会出现以下异常:
Call Stack + Locals ✘ |
基础信息
芯片资源
- RAM 192KB/0x30000
- ROM 512KB/0x80000(其中通过分散加载给应用程序分配的空间为 416KB/0x68000)
链接数据
============================================================================== |
分散加载
LR_IROM1 0x00018000 0x00068000 { |
原因分析
由于代码量比较临界,起初我以为是 flash 的问题。但是 map 文件中显示 ROM 只占用了 411.19kB 的空间,并没有超过 416KB 的总量。那 RAM 呢?RAM 只用了 160.11KB 也没有超过 192KB 的总量,邪了门儿了真是!哎,等等!这款芯片的 RAM 我记得好像是分成了两块,怎么说的来着,瞅一眼《参考手册》:
果然,两块 RAM 间不支持非对齐访问,再一看 SRAMH 的大小:32KB!破案了!现在 RAM 的用量不正好到达 160KB(192KB - 32KB = 160KB)这个临界点了么!
超过 160KB 确实会出现异常,但不是因达到 SRAMH 所致(SRAMH 地址最小,始终会用到)而是因达到 SRAM3 且使能 ECC 校验所致。注意看红线上面的那句话:「在允许 RAM ECC 校验错误产生 NMI 中断和复位的情况下,必须对所用 RAM 空间以字(16bit)为单位进行访问」。
按照现有分散加载文件的写法,两块内存会被认为是一个整体,那么就必然存在「在内存边界处进行非对齐访问」的可能。
规避方法
非对齐访问的风险可以在分散加载文件中将两块内存断开:
LR_IROM1 0x00018000 0x00068000 { |
SRAM3 开启 ECC 后仅支持以字为单位进行访问的问题可以通过禁用 ECC 功能来解决。当然如果你一定要用 ECC 的话,那这块空间肯定不能用来让编译器自动分配内存,而是要自己来手动管理。