【发布时间】:2012-12-01 21:26:59
【问题描述】:
我正在尝试实现一个与其大小对齐的内存缓冲区,这样我就可以使用 DMA 控制器的模功能来实现一个环形缓冲区。我知道我可以用 memalign 做到这一点,但我想知道它是否可以在堆栈上这样做,因为到目前为止我已经能够避免动态内存。我使用的是 GCC 4.4.1,我不关心可移植性(嵌入式系统)。
我想做这样的事情:
template<uint16_t num_channels, uint16_t buffer_size>
class sampler {
__attribute__((aligned(buffer_size * num_channels * 2)))
uint16_t buffer[buffer_size][num_channels];
};
但当然 GCC 不会接受非常量对齐(并且似乎表明对齐 > 8 可能无论如何都不会被尊重)。
我想我可以使用 C++0x alignas() 来实现这一点,但它似乎直到 4.8 版才出现在 GCC 中。
我想一个选项可能是将缓冲区的大小加倍,但这似乎会浪费大量空间(我计划尝试将大部分设备内存用于此缓冲区)。也许我应该放弃并使用动态内存。 memalign 在空间浪费方面会相对有效吗?
有什么想法吗?
【问题讨论】:
-
为什么需要这么奇怪的对齐方式(缓冲区的大小)?需要的典型对齐方式是针对某些基本类型 (int,__m128)、页面(通常为 4KB)或页面分配粒度(在 Windows 上通常为 64KB,不知道您的控制器如何或是否这样做)。
-
可能是因为它简化了 DMA 操作的包装逻辑。当您的内存也将被作为 DMA 控制器的简单硬件状态机访问时,额外的约束就会发挥作用。
-
您是否考虑过将缓冲区放在自己的翻译单元中,然后使用链接器指令强制对齐或该单元的起始地址?如果你想要它在堆栈上,我认为你需要分配两倍的缓冲区大小。 memalign() 将使用对齐浪费的空间来满足其他内存分配请求。
-
这是在没有 MMU 的 ARM Cortex M4(实际上是 teensy 3)上。
-
@brianbeuning 回复:“链接器指令”我想我必须在 .ld 文件中选择一个缓冲区大小?如果没有,您能进一步描述吗?我的长期目标之一是制作一个可供其他人使用的 Arduino 库,因此该模板非常有吸引力,因为用户可以轻松地在自己的项目中指定大小。