在文本段中创建具有给定大小的C函数

Jen*_*ens 13 c gcc powerpc memory-alignment

我正在编写一个带有32kbyte 8路组关联L2指令高速缓存的嵌入式 32系统.为了避免高速缓存抖动,我们以一种方式对齐函数,使得以高频率调用的一组函数的文本(想想中断代码)最终在单独的高速缓存集中.我们通过根据需要插入虚函数来实现这一点,例如

void high_freq1(void)
{
   ...
}

void dummy(void)
{
   __asm__(/* Silly opcodes to fill ~100 to ~1000 bytes of text segment */);
}

void high_freq2(void)
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

这让我感到丑陋和不理想.我想做的是

  • __asm__完全避免使用纯C89(可能是C99)
  • 找到一种方法来创建dummy()GCC优化器不接触的所需间隔
  • dummy()spacer 的大小应该可以配置为4个字节的倍数.典型的间隔物为260至1000个字节.
  • 对于总共500个函数中的约50个函数,应该是可行的

我也愿意探索以一种方式放置一组选定函数的全新技术,这样它们就不会映射到相同的缓存行.链接器脚本可以执行此操作吗?

Jim*_*mbo 3

也许链接描述文件是正确的选择。我认为 GNU 链接器可以使用这些...我已经在 AVR 和 MQX 上使用了 LD 文件,我们使用基于 GCC 的编译器...可能会有所帮助...

\n\n

你可以定义你的记忆部分等,以及什么放在哪里......每次我来写一个,距离上次写已经很长时间了,我必须再次阅读......

\n\n

搜索 SVR3 风格的命令文件来进行 gem up。

\n\n

免责声明:以下示例适用于非常具体的编译器...但是类似 SVR3 的格式非常通用...您必须针对您的系统进行阅读

\n\n

例如,您可以使用以下命令...

\n\n
ApplicationStart = 0x...;\nMemoryBlockSize = 0x...;\nApplicationDataSize  = 0x...;\nApplicationLength    = MemoryBlockSize - ApplicationDataSize;\n\nMEMORY {\n    RAM: ORIGIN = 0x...                LENGTH = 1M\n    ROM: ORIGIN = ApplicationStart     LENGTH = ApplicationLength   \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这为链接器定义了三个内存部分。然后你可以说类似的话

\n\n
SECTIONS\n{\n    GROUP :\n    {       \n        .text :\n        {\n            * (.text)\n            * (.init , \'.init$*\')\n            * (.fini , \'.fini$*\')\n        }\n\n        .my_special_text ALIGN(32): \n        {\n            * (.my_special_text)\n        } \n\n        .initdat ALIGN(4):\n        // Blah blah\n    } > ROM\n    // SNIP\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

SECTIONS命令告诉链接器如何将输入节映射到输出节,以及如何将输出节放入内存中......这里我们说的是 ROM 输出节的内容,我们在MEMORY上面的定义中定义了它。您可能感兴趣的一点是.my_special_text。在您的代码中,您可以执行以下操作:

\n\n
__attribute__ ((section(".my_special_text")))\nvoid MySpecialFunction(...)\n{\n    ....\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

链接器会将__attribute__语句前面的任何函数放入该my_special_text节中。在上面的示例中,它被放置到 ROM 中该text部分之后的下一个 4 字节对齐边界上,但您可以按照您喜欢的方式放置它。因此,您可以创建几个部分,每个部分对应您描述的每个功能,并确保地址不会导致冲突......

\n\n

您可以使用链接器定义的形式的变量来确定该节的大小和内存位置

\n\n
extern char_fsection_name[]; // Set to the address of the start of section_name\nextern char_esection_name[]; // Set to the \xef\xac\x81rst byte following section_name\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以对于这个例子...

\n\n
extern char _fmy_special_text[]; // Set to the address of the start of section_name\nextern char _emy_special_text[]; // Set to the \xef\xac\x81rst byte following section_name\n
Run Code Online (Sandbox Code Playgroud)\n