【问题标题】:Elegant way to define an automatic variable with specific alignment定义具有特定对齐方式的自动变量的优雅方式
【发布时间】:2019-05-01 17:17:00
【问题描述】:

我正在使用 ARM 编译器并且有一个硬件外设(具有直接内存访问),它需要对传递给它的内存缓冲区进行特定对齐(32 字节对齐)。当缓冲区是全局/静态的并且可以使用编译器支持的aligned 属性定义时,这不是问题。只要需要在本地传递某个函数中定义的缓冲区,即具有自动存储类,就会出现问题。我试图做类似以下的事情:

typedef struct  __attribute__((aligned(32)))
{
    char bytes[32];
} aligned_t;

_Static_assert(sizeof(aligned_t)==32, "Bad size");

void foo(void)
{
    aligned_t alignedArray[NEEDED_SIZE/sizeof(aligned_t)];
    //.... use alignedArray
}

这很愉快地编译并在 x86 编译器上工作。但在抱怨的armcc中却没有:

警告:#1041-D:自动对象的对齐方式不得大于 8

所以这种方法行不通。还有一个,我觉得很丑:

void foo(void)
{
    char unalignedBuffer[NEEDED_SIZE + 32 - 1];
    char pAlignedBuffer = ALIGN_UP_32(unalignedBuffer);
    //.... use pAlignedBuffer
}

ALIGN_UP_32 是一个宏,用于返回unalignedBuffer 内的第一个对齐地址(我猜这里的实现细节并不重要)。

正如我所说,我不喜欢这种方法,并且想知道是否有更优雅的方法来实现同样的效果?

【问题讨论】:

  • 动态分配是一种选择吗?
  • @dbush 不是真的。我想我应该提到这一点。
  • 你能解释一下为什么首先需要自动存储类(你需要重入)吗?
  • @user694733 我正在尝试为我正在开发的特定 HAL 提供一种限制最少的使用方式。最后(一些)缓冲区将由调用者提供,我正在尝试提出通用约定,这将是透明的(理想情况下)或有据可查的。
  • 您可以使用静态缓冲区进行硬件访问,并根据需要复制到/从未对齐的自动缓冲区中复制

标签: c arm memory-alignment armcc


【解决方案1】:

我正在使用 ARM 编译器

您是否也尝试过最近 GCC(可能配置为交叉编译器),例如2018 年 11 月的 GCC 8?

ARM ABI 不保证堆栈指针(可能)与 32 字节对齐。

因此,任何自动变量都不会按照您的意愿对齐。

您可以避免使用它们(并系统地使用适当对齐的堆内存区域)。或者你可以分配比需要的更多的空间并对其进行指针运算。

我觉得您的char* pAlignedBuffer = ALIGN_UP_32(unalignedBuffer); 是一个很好的方法,我相信优化编译器会生成相当高效的代码。

我不喜欢这种方法,想知道是否有更优雅的方法来实现同样的效果?

我相信你的方法很好,任何其他方法都可以。

PS。另一种方法可能是修补您的 GCC 编译器(可能使用插件)以更改堆栈指针的默认对齐方式(因此有效地更改您的 ABIcalling conventions)。这将需要您数周(或数月)的努力。

【讨论】:

  • 我想我会把它作为第二意见:)
  • 堆栈指针确实不需要 ARM ABI 32 字节对齐。在不同的翻译单元中需要跨函数边界对齐 8 字节,但在其他地方没有任何特定对齐的要求,通常自动类变量可以有任何对齐。
【解决方案2】:

您的两个选项看起来是最简单的。但是(只是猜测,我对自己的答案没有太多考虑),另一种选择可能是创建另一个堆栈。当包含缓冲区的函数被执行时,上下文被切换(好吧,只是 SP - 在超级用户模式下 - ),现在 SP 指向第二个堆栈。这个堆栈分配在一个 32 位对齐的部分,它只包含 32 位对齐的对象,所以当一个本地 32 位对齐的变量被创建时,它将被分配在一个 32 位对齐的内存堆中,一旦变量超出范围,就会被释放.一旦函数被执行,SP 就会切换回主堆栈。必须将函数的执行视为关键区域,以避免在错误的堆栈中推入/弹出。 我不认为这会产生堆栈溢出,但正如我所说,我离题了,以防万一它有帮助......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-29
    • 2013-01-04
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多