GCC 为 ARMv8 生成未对齐的访问

问题描述 投票:0回答:1

我正在设置 ARMv8 嵌入式系统,并在尝试编译以下代码时偶然发现了一个硬故障:

void test_ram()
{
    const uint8_t goldendata[16] = { 0xde, 0xad, 0xba, 0xbe, 0, 0x55, 0x55, 0xaa, 0xaa, 0, 0xff, 0xff };
    (void) goldendata;
}

有趣的是,当数组初始化时,我遇到了硬故障(未对齐访问)。 GCC 显然甚至知道访问是未对齐的,正如在 godbolt:

上可以看到的那样

使用 GCC 13.2 ARM 编译,选项

-std=c11 -ggdb -ffunction-sections -O0 -ggdb -ffunction-sections -O0 -Wall  -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16  -mfloat-abi=hard

问题

为什么 GCC 会生成导致硬故障的数组初始化?

我不确定未对齐的访问是否需要硬故障,因为我发现了冲突的arm文档(未对齐的访问总是错误与错误,如果设置了

UNALIGN_TRP
位):

Arm® v8-M 架构参考手册 DDI0553B.l B6.4 对齐行为

以下是未对齐的数据访问,总是会生成 对齐错误: • 非半字对齐 LDAH、LDREXH、LDAEXH、STLH、 STLEXH 和 STREXH。 • 非字对齐 LDREX、LDAEX、STLEX、STREX、 LDRD、LDMIA、LDMDB、POP(多个寄存器)、LDC、VLDR、VLDM、VPOP、 LDA、STL、STMIA、STMDB、PUSH(多寄存器)、STC、VSTR、VSTM、 VPUSG、VLLDM 和 VLSTM。适用于实施 Armv8.0-M 以后的架构

https://developer.arm.com/documentation/100235/0002/jds1485977091086

未对齐的访问通常比对齐的访问慢。在 此外,某些内存区域可能不支持未对齐访问。 因此,Arm 建议程序员确保访问是 对齐。要捕获意外生成的未对齐访问,请使用 配置和控制寄存器中的 UNALIGN_TRP 位。

我检查了 UNALIGN_TRP 位(位 3),它没有设置,但最终还是出现了错误。 (

gdb x/x 0xE000ED14
=>
0xe000ed14:    0x00000201
)

如果有什么区别的话,使用的 CPU 是 STM32U5 中的 CortexM33。

脚注:我发现可以通过将变量设置为静态(也称为不在堆栈上分配未对齐的数组)或通过向 gcc 传递

-mno-unaligned-access
选项

来抑制该问题
gcc arm memory-alignment
1个回答
0
投票

事实证明@Nate Eldredge 是对的:

生成了使用CubeMX代码来启用MPU,出于某种原因,Cube选择将内部闪存和内部存储器标记为

Device
。修改手动初始化代码以将内存设置为普通内存修复了该问题。复制意大利面 CubeMX 代码的片段。只需添加属性的宏
INNER_OUTER
即可解决该问题。 (申请Flash和RAM)

    HAL_MPU_Disable();
    
    MPU_AttributesInit.Number = MPU_REGION_NUMBER1; // pretty sure this should be MPU_ATTRIBUTES_NUMBER1 but since attributes and region number are defined to the same values, we stick with ST's initialisation here...
    MPU_AttributesInit.Attributes = INNER_OUTER( MPU_WRITE_BACK | MPU_TRANSIENT | MPU_RW_ALLOCATE );

    HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
© www.soinside.com 2019 - 2024. All rights reserved.