【问题标题】:Reserving space in SRAM for SRAM decay experiment (C ; AVR atmega644p ; Atmel Studio 7)在 SRAM 中为 SRAM 衰减实验保留空间 (C ; AVR atmega644p ; Atmel Studio 7)
【发布时间】:2021-02-06 11:33:05
【问题描述】:

我希望在 atmega644p 上进行一些实验,以评估电源循环之间 SRAM 的衰减量。我的方法是将SRAM中的字节数设置为0xFF,然后当MCU上电后,统计这些字节中剩余的1个数。

为此,我需要从 SRAM 中的已知内存地址读取和写入 1 数组。到目前为止,我的代码使用设置为 0x1000 的指针将值写入特定地址,然后在加电时开始从该地址读取数组。但是,我需要一种方法来保证这部分 SRAM 内存(例如,0x100 + 64 字节)在读取之前不会分配给其他变量/被覆盖。

我在网上查看了分配内存段的可能性——我不知道在这种情况下这是否是一个好的解决方案,甚至不太确定如何去做。任何人都可以提出一个解决这个问题的巧妙方法吗?

如有任何问题,请提出澄清。

感谢您的帮助。

【问题讨论】:

  • Can anyone suggest a neat way of approaching this? 指定在链接描述文件中不使用的区域。这就是链接描述文件的用途。
  • 您的 SRAM 是否总是降级 1->0?这是否记录在您的特定设备的某个地方?如果您假设因为当您的代码运行时 RAM 始终为 0,那可能只是因为这就是初始化将 RAM 归零的原因,即已知状态。
  • 我的理解是 SRAM 中的位具有默认状态,可以是 1 或 0。这个想法是,如果将足够的位设置为 1,大约 50% 将变为零,因为它们会腐烂。

标签: c embedded avr atmega


【解决方案1】:

您需要通过在链接器文件中为其保留空间来在 RAM 中创建一个自定义区域。重要的是它被标记为“no init”或类似的,否则.bss 初始化和类似的可能在 main() 被调用之前发生在它上面。如何做到这一点是特定于链接器的。

但是,为此编写软件似乎是不必要的麻烦。只需使用在线调试器:

  • 确保您使用的调试器不会为目标供电。
  • 将完全不使用no RAM 的程序下载到闪存中。通过检查地图文件确认这一点。
  • 通过调试器将整个 RAM 设置为 0xFF。
  • 在保持在线调试器连接的同时断开电源。
  • 等待 x 个时间单位。
  • 上电,在调试器中点击 MCU 复位,内存转储整个 RAM。

任何半体面的工具链都应该能够为您做到这一点。

【讨论】:

  • 嗨 Lundin,它在软件中实现的原因是为了评估 SRAM 衰减,这是在尝试找到一种解决方案来确定电源周期之间经过的时间,嵌入式间歇供电考虑到设备。感谢有关链接器的提示;我正在努力弄清楚如何做到这一点。 Atmel Studio 中似乎有一些用于内存设置的选项,我想这些选项会为我添加所需的行到链接器中。我将继续阅读文档来解决这个问题。我正在使用 AVR GNU 顺便说一句
  • @samp99 这听起来不太专业... RAM 费用将在很大程度上取决于您的电源电压、去耦或大容量电容,谁知道还有什么。只需像其他人一样将电池备用 RTC 集成到硬件中。
【解决方案2】:

如果您使用的是 AVR/GNU,那么当 C 应用程序启动时,它会清除整个内存并根据需要初始化全局变量。

为避免这种情况,您可以使用选项 -nostartfiles -nodefaultlibs -nostdlib 配置链接器以排除所有启动文件

如果您使用的是 Atmel Studio,您可以像这样配置它:

之后,您可以标记您的 main 以将其称为初始化代码:

int main(void) __attribute__((naked, section(".init9")));

现在您将拥有不执行任何初始化的“裸”代码。 这意味着您至少需要初始化堆栈指针并清除寄存器r1(avr-gcc 假定它包含零):

int main(void) {
    asm volatile (
        "clr r1\n" // load zero into r1
        "cli" // clear I flag  
    );
    SPL = (uint8_t)RAMEND;
    SPH = (uint8_t)(RAMEND >> 8);


    ... // here goes your code

    for(;;); // do not leave main()!
}

在此之后,您将取消初始化所有全局变量。例如,您可以声明一个全局数组并在启动时检查其内容。

【讨论】:

  • 太好了,非常感谢您的回答。通过禁用启动文件,如果我希望 mcu 正常运行并在测量 SRAM 衰减后执行其他功能,这是否会产生任何不利影响。测量 SRAM 衰减是为了估计自上次嵌入式设备断电以来经过的时间——例如,如果 MCU 充当物联网设备,它是否仍能通过这种方法正常运行?是否可以将除 main() 之外的另一个函数声明为初始化代码,然后 main 函数包含正常程序的其余部分?
  • 另外,大概禁用标准库会删除诸如 printf 等功能?
  • @samp99 是的,你可以用它制作一个可行的程序,只要确保初始化所有变量,还要注意中断向量和 PROGMEM 字段是如何编译的,如果它们被使用。
  • 我也不确定 printf 等(你如何在那些 MCU 中使用它们?)。所以,最好检查编译后代码的反汇编
  • 我已将标准 io 流重定向到 UART - 关键是,使用这种方法,我的理解是我们无法访问标准库。无论如何,感谢您的帮助,我需要对适用的启动文件进行更多阅读
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-03
  • 1970-01-01
  • 2010-10-31
相关资源
最近更新 更多