【问题标题】:How to place an array at a specific memory location that is provided from a variable?如何将数组放置在变量提供的特定内存位置?
【发布时间】:2018-11-28 17:13:47
【问题描述】:

对于嵌入式系统项目,数组应该放在 RAM 中。我已将设备的 RAM 分成两部分,一个存储全局变量和其他数据,另一部分 RAM_DATA,我希望存储两个数组(源位置和目标位置)。

有一个全局值 mem_val 设置为 RAM_DATA 地址的开头,现在想要使源数组从存储在 location 中的位置开始。

根据我从在线资源中获得的信息,他们利用stdint.h 头文件来使用uintptr_tuint32_t 值来设置数组的开始。调试程序时,数组不是从这个值开始的,正在询问如何解决这个问题。这是一些与问题相关的代码。

volatile uintptr_t mem_val = 0x0219;

 int main(void)
 {
      char cur_loc[128];
      uint32_t *cur_loc = (void *)mem_val;
      ...
      return 0;
 }

显然数组初始化并使其成为指针有问题,但除此之外,有没有一种方法可以使数组cur_loc 以赋予mem_val 的值开始?如果有帮助,我正在使用德州仪器 MSP430 嵌入式设备。谢谢

【问题讨论】:

  • 听起来像是 XY 问题。这些地址在运行之间不应更改,因此它们可以由链接描述文件固定和给出。我想你有一个?然后你在那里定义你的部分。有问题的数组是在堆栈上分配的,所以不清楚你在这里要做什么。也许将其复制到静态位置?
  • 0x0219 - 这是真实地址吗?如果是这样,它是不对齐的。在 16 位 msp430 平台上,uint32_t 需要 2 字节对齐,例如,0x0220
  • @kfx,我不知道为什么,但将其移至 0x0220 即可,谢谢您的提示。
  • @EugeneSh。我已修改链接描述文件以包含 RAM_DATA 部分并包含一些 #pragma 语句,这些语句指定将数组存储在 RAM_DATA 部分中
  • 您需要使用链接器命令文件。在该文件中,您可以指定所有内容所在位置的所有详细信息。在链接器命令文件中为每个数组创建一个特定的内存段,然后在源代码中引用内存段的名称。

标签: c arrays memory memory-management msp430


【解决方案1】:

有一些关于 MSP430 的宝贵意见。在这里,关于指定内存位置的数组,我的两分钱:

  1. volatile uintptr_t mem_val = 0x0219;: 如果我猜对了,地址应该被“烧”成二进制。因此volatile 没有意义,但const 会:

    const uintptr_t mem_val = 0x0219;`

    相反,(假设修复地址在映射到地址空间的 I/O 范围内)将数组/指针的内容标记为 volatile 更有意义:

    volatile uint32_t *cur_loc = (void*)mem_val;
  2. 以下是“重复符号错误”:

    char cur_loc[128];
    uint32_t *cur_loc = (void *)mem_val;

    实际上,第 2nd 行就足够了,因为指针可以像数组一样使用。 C 没有任何标准的边界检查。因此,指向uint32_t 的指针可以像uint32_t 元素的数组一样使用。

  3. 加上一些额外的括号,甚至可以设置数组的地址:

    volatile uint32_t (*curLoc)[128 / sizeof (uint32_t)] = (void*)mem_val;

    但是,要访问数组,必须始终使用“内容”运算符:(*curLoc)[i]。更不用说,括号是必不可少的(*curLoc[i] 做错了)。

所以,我做了一个小样本(3. 作为“反例”并练习我的 C 打字能力):

#include <stdint.h>
#include <stdio.h>

int main()
{
  char storage[32] = {
    '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
    '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
    '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
    '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'
  };
  const uintptr_t mem_val
    = (uintptr_t)&storage; /* 0x0219 <- a fix address wouldn't work on wandbox. */
  enum { size = sizeof storage / sizeof (uint32_t) };
  printf("size: %u\n", size);
  /* using pointer */
  volatile uint32_t *pCurLoc = (uint32_t*)mem_val;
  for (unsigned i = 0; i < size; ++i) printf(" %08x", pCurLoc[i]);
  puts("");
  /* using array */
  volatile uint32_t (*curLoc)[size] = (void*)mem_val;
  for (unsigned i = 0; i < size; ++i) printf(" %08x", (*curLoc)[i]);
  puts("");
  /* done */
  return 0;
}

输出:

size: 8
 03020100 07060504 0b0a0908 0f0e0d0c 13121110 17161514 1b1a1918 1f1e1d1c
 03020100 07060504 0b0a0908 0f0e0d0c 13121110 17161514 1b1a1918 1f1e1d1c

Live Demo on wandbox

【讨论】:

  • this:const uintptr_t mem_val = 0x0219; 是说指针指向的位置是一个常量值,我怀疑你真的想要:uintptr_t const mem_val = 0x0219; 表示指针是一个常量。
  • @user3629249 uintptr_t 是一个能够保存指针的无符号整数类型。记住这一点,const 出现在之前或之后应该没有区别。 (const intint const 相同,而 const int*int *const 相同。)
猜你喜欢
  • 2021-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 1970-01-01
相关资源
最近更新 更多