hyts3366 2024-09-11 17:44 采纳率: 40%
浏览 20
已结题

stm32G4u64指针非对齐访问

STM32G4芯片 u64类型指针非对齐访问时报错

先看以下我简化的触发问题的代码

uint64_t u64_data = 0;
uint32_t u32_data = 0;
uint8_t array_test[32];

void pointer_test(void)
{
    uint64_t *pu64 = (uint64_t *)(&array_test[0]);
    uint32_t *pu32 = (uint32_t *)(&array_test[0]);
    uint8_t i = 0;
    
    for(i = 0;i < 16;i++)
    {
        array_test[i] = i;
        pu32 = (uint32_t *)(&array_test[i]);
        u32_data = *pu32;
    }
    
    for(i = 0;i < 16;i++)
    {
        array_test[i] = i;
        pu64 = (uint64_t *)(&data_buff[i]);        
        u64_data = (*pu64);
    }
    
}

目前的情况是,我经过网上搜索,已经了解了与对齐相关的知识点,并且对于M4内核来说是支持非对齐访问,所以在代码u32_data = *pu32;处,不管i为几,都能正常从该地址处连续读出4个字节的数据并赋值给u32_data,这里如果是不支持非对齐访问的话,我理解的应该会报错。但是当我使用u64类型进行同样的操作时,发现在i为0时,能正常读出8个字节数据,但是当i为1时,会进入HardFault_Handler,并且查看Fault Reports时,发现报了UNALIGNED,应该是触发了非对齐访问报错。我的疑问就是为什么使用U64类型的时候,无法进行非对齐访问?与使用U32类型进行操作时,区别在哪?

  • 写回答

1条回答 默认 最新

  • 一轮明月照丘壑 2024-09-11 17:45
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    关于STM32G4的指针非对齐访问问题,让我们详细分析您的代码和疑问。

    首先,要明确一点:在许多嵌入式系统中,硬件通常对未对齐的数据访问是敏感的,可能导致错误或异常行为。尽管STM32的Cortex-M内核在某些配置下支持非对齐访问,但这并不意味着所有情况下都可以随意进行非对齐访问。特别是在使用较大数据类型(如uint64_t)时,非对齐访问的风险更高。

    在您提供的代码中,关键差异在于使用uint64_t和uint32_t指针访问数组时的地址对齐方式。当您使用uint32_t指针时,无论起始地址是否对齐,通常都可以访问数据,因为Cortex-M内核支持非对齐访问。然而,当使用uint64_t指针时,特别是在地址未正确对齐到8字节边界的情况下,会出现问题。这是因为uint64_t类型的访问需要8字节对齐。如果尝试在未对齐的地址上访问uint64_t数据,硬件可能会触发异常或错误。

    具体到您的代码:

    1. 当您使用uint32_t指针时,无论数组索引i的值如何,都可以从地址&array_test[i]处安全地读取数据,因为每次读取的大小为4字节(即一个uint32_t的大小),即使起始地址未对齐也不会出问题。
    2. 然而,当您尝试使用uint64_t指针时,情况就不同了。当i为偶数时(例如i=0),&array_test[i]的地址是8字节对齐的,所以可以安全地读取一个uint64_t的值。但当i为奇数时(例如i=1),地址就不再是8字节对齐的,此时尝试读取uint64_t值可能会触发非对齐访问错误。这是因为硬件试图从一个未对齐的地址读取8字节数据,这通常是不允许的。

    要解决此问题,您可以确保在访问uint64_t数据时地址总是8字节对齐的,或者在访问时使用更小类型(如uint32_t)来避免非对齐访问。此外,还可以检查您的编译器和链接器的设置,以确保启用了适当的内存访问特性(如ARM的M类扩展支持的非对齐访问)。请注意,即使某些处理器支持某些非对齐访问,频繁的非对齐访问仍然可能导致性能下降或增加出错的风险。因此,最佳做法是始终确保数据正确对齐。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 9月26日
  • 已采纳回答 9月18日
  • 创建了问题 9月11日