自动分配到 GCC/C 中的特定 RAM 区域

Auto-Allocate to a specific RAM Area in GCC/C

抱歉我的英语不好,我有点难以解释我到底需要什么。 我正在使用 GCC 编译器将一些额外的代码添加到现有的二进制文件中。 在这种情况下,它是 PowerPC,但应该无关紧要。

我知道,在现有二进制文件的哪个位置我有可用的 RAM(我转储了完整的 RAM 以确保)但我需要手动定义每个 RAM 地址,目前我是这样做的:

// #ram.h

//8bit ram
uint8_t*        xx1     = (uint8_t*)    0x807F00;
uint8_t*        xx2     = (uint8_t*)    0x807F01;
//...and so on

// 16bit ram
uint16_t*       xxx1    = (uint16_t*)   0x807F40;
uint16_t*       xxx2    = (uint16_t*)   0x807F42;
//...and so on
    
// 32bit ram
uint32_t*       xxxx1   = (uint32_t*)   0x807FA0;
uint32_t*       xxxx2   = (uint32_t*)   0x807FA4;
//...and so on

我正在像这样访问我的变量:

void  __attribute__ ((noinline)) silly_demo_function() {
    #include "ram.h"
    
    if (*xxx2>*xx1) {
    *xxx3 = *xxx3 + *xx1; 
    }
    
return; 
}

但这真的很无聊,如果我想将我的代码修补到另一个现有的二进制文件中,其中 available/free/unused ram 的位置可以完全不同,或者如果我 replacing/removing 中的某个值中间。我正在使用 8、16 和 32 位变量。

有没有办法,我可以定义一个区域,比如0x807F00到0x00808FFF,动态分配我的变量,编译器会在我的特定位置分配它?

我怀疑这里的大问题是那些地址是内存映射 IO(设备)而不是 RAM;不应被视为 RAM。

此外,我想说您可能应该将“不是 RAM 的设备”隐藏在抽象层后面,有点像设备驱动程序;部分是为了确保编译器符合由 IO 而不是 RAM 引起的任何约束(例如,被视为 volatile,可能遵守任何访问大小限制,可能会处理任何缓存一致性管理);部分原因是 you/programmers 知道什么是 normal/fast/cached RAM,什么不是;部分原因是您可以用假代码替换“设备”以进行测试;部分是为了将其全部保存在一个明确定义的区域中。

例如;您可能有一个名为“src/devices.h”的头文件,其中包含:

#define xx1_address  0x807F00

.. 包装器代码可能是一个名为“src/devices/xx1.c”的文件,其中包含如下内容:

#include "src/devices.h"


static volatile uint8_t * xx1  = (uint8_t*) xx1_address;


uint8_t get_xx1(void) {
    return *xx1;
}

void set_xx1(uint8_t x) {
    *xx1 = x;
}

但是;根据这些设备的实际情况,您可能 need/want 一些更高级别的代码。例如,也许 xx1 是一个温度传感器,尝试设置它没有任何意义,并且您希望它缩放原始值,使其成为“摄氏度”,原始值的最高位value 用于指示错误情况(实际温度只有 7 位),因此包装器可能更像:

#include "src/devices.h"

#define xx1_offset   -12.34
#define xx1_scale    1.234

static volatile uint8_t * xx1  = (uint8_t*) xx1_address;


float get_xx1_temperature(void) {
    uint8_t raw_temp = *xx1;

    if(raw_temp * 0x80 != 0) {
        /* Error flag set */
        return NAN;
    }
    /* No error */
    return (raw_temp + xx1_offset) * xx1_scale;
}

同时,我想通了。

它就像在链接器指令中定义 .data、.bsss 和 .sbss 一样简单。 6 行代码和它的魅力。