关于cortex-m内核非对齐访问0x1fffffff出错问题

8 篇文章 1 订阅
4 篇文章 1 订阅

关于cortex-m内核非对齐访问0x1fffffff出错问题

1.问题发现

通常在类似STM32这种MCU平台开发程序时,因为内存资源有限, 在遇到一些结构体的size不对齐到4字节时,编译器会强制4字节对齐,从而浪费了内存空间,因此常常会有对结构体使用__packed的语法来强制修改对齐方式,这种优化方式可以使非4字节对齐size的结构体占用更小的ram空间,但会导致结构体数据存放地址为非4字节对齐的地址,譬如:0x1FFB0001开始处的1个word为一个32位的数据或指针。

在这个背景下有时候会产生一些莫名奇妙的bug,经过仔细的分析后,最终确认了一个问题cortex-m内核非对齐访问0x1fffffff出错问题。

2.调试定位

一个错误实例就是使用__packed限制结构体对齐方式后,程序中产生了一个异常结果,而使用默认的4字节对齐方式则不会产生错误结果。通过在c代码中产生异常结果值进行断言跟踪,逐步缩小出错范围,对改汇编代码单步调试并检查cpu的通用寄存器,最终发现一处汇编语句出现错误,如下:

ldr r0, [r6]

执行该语句前 r6值为0x1fffffff,执行该语句即从内存中0x1fffffff地址加载一个word数据到r0寄存器内,r0中的数据与内存中0x1fffffff-0x20000003数据不相符合,遂产生异常输出

3.仿真验证

为验证该问题,编写一个测试代码如下:

int main()
{
    volatile int *data = (volatile int*)(0x1ffffffc);
    data[0] = 0x12345678;
    data[1] = 0xfdcba987;  //准备一些数据填入0x1ffffffc到0x20000004内存中
    
    __asm volatile("ldr r1, =0x1fffffff");
    __asm volatile("ldr r0,[r1]");  //使用ldr指令非对齐加载0x1fffffff
    
	while(1);
}

上述程序运行完成后期望在r0得到数据为0xcba98712,在芯片上实测结果不符。仅低8位正确为0x12,高24位为错误值。

4.资料查找

经过查找在 https://electronics.stackexchange.com/questions/224328/mcu-ram-why-accessing-ram-across-the-boundary-causes-bus-fault 找到一处描述:

Unaligned accesses that cross memory map boundaries are architecturally Unpredictable. The processor behavior is boundary dependent, as follows:

  • DCode accesses wrap within the region. For example, an unaligned halfword access to the last byte of Code space (0x1FFFFFFF) is converted by the DCode interface into a byte access to 0x1FFFFFFF followed by a byte access to 0x00000000.

即在cortex-m核内对0x1fffffff进行非对齐访问会读取到0x0地址的数据而不是0x20000000.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Quard_D

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值