5

我正在尝试实现一个与其大小对齐的内存缓冲区,这样我就可以使用 DMA 控制器的模特性来实现一个环形缓冲区。我知道我可以用 memalign 做到这一点,但我想知道是否可以在堆栈上这样做,因为到目前为止我已经能够避免 dynamic memory。我使用的是 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 在浪费空间方面会相对有效吗?

有任何想法吗?

4

4 回答 4

5

您不需要将存储空间的大小增加一倍,您只需要添加它 - 基本上与幕后所做(alignment - 1)的相同。memalign对于两个对齐的幂:

char buf[size + (alignment -1)];
char *aligned = (char*)((intptr_t)buf + (alignment - 1) & ~intptr_t(alignment - 1));
于 2012-12-01T21:33:04.233 回答
1

自从我使用链接器命令文件以来已经有很长时间了,但我认为它会像这样。

创建文件 buffer.cpp

char buffer[ BUFFER_SIZE ];

目标文件具有名为 .bss(用于未初始化数据)、.data(用于初始化数据)和 .text(用于可执行代码)的部分。buffer[] 将进入 .bss,因为它没有被初始化。

所以像这样的(gnu)链接器文件应该可以解决问题

SECTIONS {
   .bss 0x0  : {
        buffer.o(.bss)
        *(.bss)
    }
   .data : {
        *(.data)
    }
   .text : {
        *(.text)
    }
}

0x0 告诉链接器在地址 0x0 加载缓冲区 []。

于 2012-12-01T23:51:01.933 回答
0

您能否创建一个大于 的缓冲区buffer_size,然后计算其中的偏移量?

于 2012-12-01T21:33:46.243 回答
0

如果您的嵌入式系统具有内存管理单元,则无需担心明智地使用动态内存,尤其是在每次运行只分配一次的情况下。

如果它没有 MMU,您可以考虑使用链接器映射文件分配一个固定位置。

在具有实际操作系统的系统上,与 DMA 兼容的缓冲区可能必须由内核专门分配。

于 2012-12-01T21:38:33.503 回答