【问题标题】:Auto-Allocate to a specific RAM Area in GCC/C自动分配到 GCC/C 中的特定 RAM 区域
【发布时间】:2021-09-07 12:20:07
【问题描述】:

对不起我的英语,我很难解释我到底需要什么。 我正在使用 GCC 编译器在现有的二进制文件中添加一些额外的代码。 在这种情况下,它的 PowerPC,但它应该不重要。

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

// #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; 
}

但这真的很无聊,如果我想将我的代码修补到另一个现有的二进制文件中,其中可用/空闲/未使用的 ram 的位置可能完全不同,或者如果我替换/删除中间的一些值。我使用的是 8、16 和 32 位变量。

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

【问题讨论】:

  • 好的,抱歉,我会编辑它,这样更容易显示。
  • 问题不是很清楚。你在运行嵌入式系统吗?什么是操作系统?对于多进程操作系统,地址是虚拟的,而不是物理/内存。所以不清楚这些地址真正代表什么以及它们如何映射到内存。
  • 到目前为止还没有操作系统,我正在处理的代码是用 C 编写的,并用类似于 GCC 的东西编译,我这里唯一的东西是原始二进制文件和一些解释,这就是为什么我知道我在哪里需要工作。我将新代码添加到这个二进制文件中(它是一个 ECU - 发动机控制单元),在这种情况下是它的 PowerPC 架构。像在我的代码示例中那样做可以正常工作,我知道我在哪里有可用的 RAM,并且我可以像上面的示例中那样读/写它。但是我有一个项目现在使用了 200 个自定义 RAM 地址,如果我必须在中间更改一些东西,那就一团糟了。
  • 我直接访问,所以它是一个物理内存地址,我已经确认它们在原始代码中是免费且未使用的,但是随着我的代码变得越来越大,它变得混乱并且我失去了很多可用的 RAM,因为我什至不记得实际使用了什么,如果我更改代码又是什么。
  • 我不是这方面的专家,但我认为阅读 linker scripts 可能会对您有所帮助。

标签: c gcc ram allocation


【解决方案1】:

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

此外,我想说您可能应该将“不是 RAM 的设备”隐藏在抽象层后面,有点像设备驱动程序;部分是为了确保编译器符合由它是 IO 而不是 RAM 引起的任何约束(例如,被视为volatile,可能遵守任何访问大小限制,可能负责任何缓存一致性管理);部分是为了让您/程序员知道什么是正常/快速/缓存的 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;
}

但是;根据这些设备的实际情况,您可能需要/想要一些更高级别的代码。例如,xx1 可能是一个温度传感器,尝试设置它没有任何意义,您希望它缩放原始值,使其为“摄氏度”,原始值的最高位是用于指示错误情况(实际温度只有 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;
}

【讨论】:

    猜你喜欢
    • 2021-08-08
    • 2015-08-22
    • 2013-02-05
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    相关资源
    最近更新 更多