【问题标题】:how to initialize a const array at specific address in memory?如何在内存中的特定地址初始化 const 数组?
【发布时间】:2015-01-05 05:18:59
【问题描述】:

这个问题是关于嵌入式控制器的。 我想在内存中初始化一个 const 数组。但是在将这个数组存储在内存中时,我想将它存储在特定的位置,比如 0x8000。这样我想占用一些代码内存,以便在运行时我可以擦除它部分并将其用于我自己的其他目的。 基本上我想这样做:

const unsigned char dummy_string[] = "This is dummy string";

但是dummy_string 的地址应该在我手中。就像我可以分配任何我想要的地址。

【问题讨论】:

  • C 还是 C++?每个人的答案都不一样。
  • " 并将其用于我自己的其他目的" - 代码注入?
  • 可以使用mmap() 指定您的地址。虽然地址是虚拟的。
  • @cdhowie - 我想在 C 中执行此操作,但 C++ 也可以
  • 我建议您将过程分成两个阶段:(1)使用闪存编程器在闪存中编程所需的初始值; (2) 在运行时使用简单转换访问值:(volatile unsigned char *)0x8000。 msp430 flash 地址可以作为 RAM 地址读取。写入需要擦除 + 写入。

标签: c arrays embedded constants


【解决方案1】:

使用 pragma 语句将变量放入命名的内存部分。然后使用链接器命令脚本将命名的内存段定位到所需的地址。

我浏览了一些 MSP430 文档,我认为它可能会像这样工作......

在源代码中使用#pragma DATA_SECTION。

#pragma DATA_SECTION(dummy_string, ".my_section")
const unsigned char dummy_string[] = "This is dummy string";

然后在链接器 .cmd 文件中执行类似的操作。

MEMORY
{
    ...
    FLASH    : origin = 0x8000, length = 0x3FE0
    ...
}

SECTIONS
{
    ...
    .my_section    : {} > FLASH
    ...
}

如果 FLASH 中有多个部分,那么首先列出 .my_section 可能会保证它位于 FLASH 的开头。或者,也许您应该定义一个专门命名的 MEMORY 区域,例如 MYFLASH,它只包含 .my_section。阅读链接器命令手册,了解有关如何在特定地址定位节的更多想法。

【讨论】:

  • 我也应该修改FLASH部分吗?
  • 非常感谢。我还发现了这个:const unsigned char flash_mem[1024] __attribute__((location(0x8000)));
  • 我的回答中的FLASH来源和长度只是例子。我不知道这些值是否适合您的董事会。链接器 .cmd 文件中的 MEMORY{} 块定义了有效的内存区域。内存区域不应重叠。如果您将原始 FLASH 区域分为两个区域,分别名为 MYFLASH 和 FLASH,那么是的,您应该更改 FLASH 区域以删除您分配给 MYFLASH 的部分,以免它们重叠。
  • 如果__attribute__ 语句对您有用,那就太好了。我怀疑这可能是 GCC 编译器特有的功能,我想知道它是否适用于 TI 的编译器。使用 TI 的编译器,您可能需要像我的回答一样使用 #pragma 语句。 (但我真的不确定。)
【解决方案2】:

便携方式是使用指针设置地址

  const unsigned char dummy_string[] = "This is dummy string";
  unsigned char* p = (unsigned char*)0x1234;

  strcpy(p, dummy_string);

不可移植的方式是使用编译器/平台特定的指令来设置地址。例如,对于 AVR 上的 GCC,可以使用类似

  int data __attribute__((address (0x1234)));

【讨论】:

  • P 是指向 unsigned char 的指针,它正在初始化为 RAM 地址。我只是想这样做,但 P 应该指向闪存地址。& 如何在不进行类型转换的情况下将 0x1234 分配给 p?
  • @GujaratiLION 那你知道flash地址吗?你能读出来吗?你能做类似char* p = (char*)FLASH_ADDRESS; cout << *p;
  • 是的,闪存地址是 0x8000。我是从控制器的数据表中得到的。我可以按照你说的做。但关键是我可以在闪存中而不是 RAM 中拥有位置 0x8000 并放入任何需要的数据。
  • @GujaratiLION 如果它在您的程序地址空间内,并且您不会遇到访问冲突,那么是的,您可以这样做。同样,首先要检查您是否可以阅读。另一个问题是,是否有一些类似系统的数据可以从闪存中生成一些结构——比如文件系统或类似的。如果这里有文件系统,你最好通过驱动访问它
  • 嗨,您的第二个选项实际上只需要在 CCS 中使用“位置”而不是“地址”。但我仍然怀疑您的第一个选项如果 0x1024 是闪存地址怎么办? strcpy 需要运行时 CPU control.btw 感谢您的回答
【解决方案3】:

来自 C 和/或 C++,就像您在问题中所写的那样。可能添加 extern 来覆盖 C++ 的 const-is-static-by-default 规则。

然后您将需要使用链接器指令(可能是.ld 文件)将该符号强制到代码闪存/ROM 中的特定地址。

或者,您可以假设构建过程之外的某些东西对内存进行编程,而您的代码只是访问它。然后您可以执行以下操作:

inline const unsigned char* dummy_string() { return (const unsigned char*)0x8000; }

【讨论】:

  • 但这只会将地址 0x8000 提供给 dummy_string。如果我想在 0x8000 和之后的位置写入一些数据怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 2011-04-26
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2014-08-08
相关资源
最近更新 更多