我想放置一个2kB的内存块,在 1024字节对齐之前对齐 16个字节。
平台:手臂,裸机,GNU工具链。无需便携性
我可以使用GCC /属性编译指示,ld
自定义链接描述文件或任何其他解决方案吗?
我想避免浪费1kB(基本上将3kB的内存块对齐为1kB&添加1024-16字节的填充)。
强制特定地址放置数据是可能的,但是ld
能够在它之前和之后放置变量(或者它只是一种放置填充的方法吗?)
上下文:缓冲区需要通过硬件设计处于1k边界,但我想在之前/之后添加一些空间,以便能够复制到此缓冲区而无需检查我的源是否最多16B宽。
编辑:添加了示例。
假设我的RAM从0x2000000开始。我需要在{* 1}}中放置一个1024 * N-16偏移量 - 即char buf[2048]
,希望不会丢失1008个填充字节。
(EDIT2) 所以我想:
答案 0 :(得分:1)
您应该在链接描述文件中定义一个具有所需对齐的特定部分。
查看the man
<强> ALIGN(EXP)强>
返回与下一个exp边界对齐的当前位置计数器(。)的结果。 exp必须是一个值为2的幂的表达式。这相当于
(. + exp - 1) & ~(exp - 1)
ALIGN
不会更改位置计数器的值 - 它只会对其进行算术运算。例如,将输出.data节对齐到前一节之后的下一个0x2000字节边界,并将节内的变量设置为输入节之后的下一个0x8000边界:
SECTIONS{ ...
.data ALIGN(0x2000): {
*(.data)
variable = ALIGN(0x8000);
}
... }
此示例中第一次使用ALIGN指定了节的位置,因为它用作节定义的可选起始属性(请参阅可选节属性一节)。第二种用法只是定义变量的值。内置的NEXT与ALIGN密切相关。
例如,您可以定义您的部分
SECTIONS
{
.myBufBlock ALIGN(16) :
{
KEEP(*(.myBufSection))
} > m_data
}
并在您的代码中
unsigned char __attribute__((section (".myBufSection"))) buf[2048];
修改强>
SECTIONS
{
.myBufBlock 0x0x7FBF0 :
{
KEEP(*(.myBufSection))
} > m_data
}
并在您的代码中
unsigned char __attribute__((section (".myBufSection"))) buf[16+2048+16];
您可以在DMA上设置1k对齐的地址&buf[16]
。
答案 1 :(得分:1)
ALIGN(exp)
相当于(. + exp - 1) & ~(exp - 1)
。当然,只有当exp
是2的幂时,该表达式才有效。所以你不能使用ALIGN()
,但你可以编写自己的表达式来产生你想要的结果。像((. + 1024 + 16 - 1) & ~(1024 - 1)) - 16
这样的东西应该可以解决问题。插入.
的各种值,您会看到它如你所愿。
您遇到的问题是链接器会将您指定的每个部分放在它之前的特殊部分之前,并指定每个部分之后的部分。它不会巧妙地命令不同文件的.data部分在之前或之后,以便产生最小量的填充。它也不会在目标文件和部分中重新排序单个变量。如果你想尽可能紧密地打包,我认为你需要做类似的事情:
.data : {
*(.about1008bytes)
. = ((. + 1024 + 16 - 1) & ~(1024 - 1)) - 16
*(.DMAbuf)
*(.data)
}
使用section属性将缓冲区放在.DMAbuf
中,并尝试查找接近但不超过1008字节的其他数据变量,并将其粘贴在.about1008bytes
部分中。
如果你想发疯,请使用gcc -fdata-sections
将每个数据对象放在自己的部分中,使用readelf提取部分大小,将其提供给您编写的程序以对其进行排序以获得最佳打包然后吐出一大块链接器脚本以最佳顺序列出它们。