C99中如何指定functions/vars的内存位置(fast/slow)?
How to specify the memory location (fast/slow) of functions/vars in C99?
在许多嵌入式架构中,可以 运行 将代码或数据存储到内部 RAM(快速访问)或外部 SDRAM(慢速访问)中。
在像 SHARC 处理器这样的架构上,可以定义函数链接到的内存区域。
segment("seg_ext_dm32") void foo( void ); // External memory 32-bit location
不幸的是,说明符 segment("seg_ext_dm32")
并不是真正的 ANSI,我不能在我的通用库中省略它,因为它可以在不同的体系结构(例如 x86)上进行单元测试。
所以我正在寻找一种更通用的解决方案来将我的 functions/variables 分类为存储在慢速或快速内存段中。这是一个例子:
___slow void fft_configure( int parameter );
___fast void fft_tick();
最常用的方法是什么?
当然,一种简单的方法是将通用头文件添加到我的特定编译器中,以定义 __slow 或 __fast 的内容:
在我的主文件中:
#ifndef __slow
#define __slow /* nothing */
#endif
#ifndef __fast
#define __fast /* nothing */
#endif
在我的编译器中:
cc -D__slow=segment("seg_ext_dm32") -D__fast=segment("seg_dm32")
但我认为这不是最佳解决方案。
有很多方法可以给这只猫剥皮,有些方法比其他方法更便携。
可能最便携的方法是将您的函数隔离到单独的源文件中,这些文件是 'fast' 或 'slow'(或者通过为每个文件放置一个函数组来实现更精细的粒度),并且然后让链接器描述符文件处理将段粘贴到您想要的位置。这会将所有非标准内容排除在源文件之外并将其放在一个位置。
链接器描述符文件必须由使用该库的人管理,但无论如何他们都必须这样做才能将任何段正确定位到 'fast' 和 'slow' 内存。使用这种方法,他们只需在他们在正确位置定义的加载段中指定正确的 .o 文件,而不是依赖编译器发出您选择的包罗万象的名称。
这就是我所做的。
我创建了一个可以根据编译器更改的属性。
对于我的嵌入式应用程序,我使用以下
#ifdef IS_EMBEDDED
#define FAST_DATA __attribute__ ((section ("fast_data")))
#else
#define FAST_DATA /* DO NOTHING */
#endif
然后当我创建需要在快速数据部分内的全局数据时,我按如下方式应用部分位置。
char fastStack[1024*5] FAST_DATA;
终于在我的链接描述文件中了。
MEMORY
{
fastMemory : ORIGIN = 0x00000050, LENGTH = 0x0000ffff
DDR3 : ORIGIN = 0x60000000, LENGTH = 0x8000000
FLASH : ORIGIN = 0xC0000000, LENGTH = 0x02000000
}
...
.fast_data : {
__fast_data_start = .;
. = ALIGN(8);
*(fast_data)
. = ALIGN(8);
__fast_data_end = .;
} > fastMemory
...
在许多嵌入式架构中,可以 运行 将代码或数据存储到内部 RAM(快速访问)或外部 SDRAM(慢速访问)中。
在像 SHARC 处理器这样的架构上,可以定义函数链接到的内存区域。
segment("seg_ext_dm32") void foo( void ); // External memory 32-bit location
不幸的是,说明符 segment("seg_ext_dm32")
并不是真正的 ANSI,我不能在我的通用库中省略它,因为它可以在不同的体系结构(例如 x86)上进行单元测试。
所以我正在寻找一种更通用的解决方案来将我的 functions/variables 分类为存储在慢速或快速内存段中。这是一个例子:
___slow void fft_configure( int parameter );
___fast void fft_tick();
最常用的方法是什么?
当然,一种简单的方法是将通用头文件添加到我的特定编译器中,以定义 __slow 或 __fast 的内容:
在我的主文件中:
#ifndef __slow
#define __slow /* nothing */
#endif
#ifndef __fast
#define __fast /* nothing */
#endif
在我的编译器中:
cc -D__slow=segment("seg_ext_dm32") -D__fast=segment("seg_dm32")
但我认为这不是最佳解决方案。
有很多方法可以给这只猫剥皮,有些方法比其他方法更便携。
可能最便携的方法是将您的函数隔离到单独的源文件中,这些文件是 'fast' 或 'slow'(或者通过为每个文件放置一个函数组来实现更精细的粒度),并且然后让链接器描述符文件处理将段粘贴到您想要的位置。这会将所有非标准内容排除在源文件之外并将其放在一个位置。
链接器描述符文件必须由使用该库的人管理,但无论如何他们都必须这样做才能将任何段正确定位到 'fast' 和 'slow' 内存。使用这种方法,他们只需在他们在正确位置定义的加载段中指定正确的 .o 文件,而不是依赖编译器发出您选择的包罗万象的名称。
这就是我所做的。 我创建了一个可以根据编译器更改的属性。 对于我的嵌入式应用程序,我使用以下
#ifdef IS_EMBEDDED
#define FAST_DATA __attribute__ ((section ("fast_data")))
#else
#define FAST_DATA /* DO NOTHING */
#endif
然后当我创建需要在快速数据部分内的全局数据时,我按如下方式应用部分位置。
char fastStack[1024*5] FAST_DATA;
终于在我的链接描述文件中了。
MEMORY
{
fastMemory : ORIGIN = 0x00000050, LENGTH = 0x0000ffff
DDR3 : ORIGIN = 0x60000000, LENGTH = 0x8000000
FLASH : ORIGIN = 0xC0000000, LENGTH = 0x02000000
}
...
.fast_data : {
__fast_data_start = .;
. = ALIGN(8);
*(fast_data)
. = ALIGN(8);
__fast_data_end = .;
} > fastMemory
...