在 SRAM 中保留 space 用于 SRAM 衰减实验(C;AVR atmega644p;Atmel Studio 7)
Reserving space in SRAM for SRAM decay experiment (C ; AVR atmega644p ; Atmel Studio 7)
我希望在 atmega644p 上进行一些实验,以评估电源周期之间 SRAM 的衰减量。我的方法是将SRAM中的字节数设置为0xFF,然后当mcu上电时,统计这些字节中剩余1的个数。
为此,我需要读取和写入 1 的数组 to/from SRAM 中的已知内存地址。到目前为止,我有代码使用设置为 0x1000 的指针将值写入特定地址,然后在加电时我开始从该地址读取数组。但是,我需要一种方法来保证这部分 SRAM 内存(比如 0x100 + 64 字节)在读取之前不会分配给其他 variables/overwritten。
我在网上查看了分配内存段的可能性 - 我不知道在这种情况下这是否是一个好的解决方案,我什至不太确定如何去做。谁能建议一种巧妙的方法来解决这个问题?
如有任何问题请提问。
感谢您的帮助。
您需要通过在链接器文件中为它保留 space 来在 RAM 中创建一个自定义区域。重要的是它被标记为“no init”或类似的,否则 .bss
初始化和类似的可能会在调用 main() 之前发生在它上面。如何做到这一点是 linker-specific。
然而,为此编写软件似乎不必要地麻烦。只需使用 in-circuit 调试器:
- 确保您使用的调试器不为目标供电。
- 下载一个完全没有 RAM 的程序到闪存中。通过检查地图文件来确认这一点。
- 通过调试器将整个 RAM 设置为 0xFF。
- 断开电源,同时保持 in-circuit 调试器连接。
- 等待 x 个时间单位。
- 加电,在调试器中点击 MCU 复位,内存转储整个 RAM。
任何 half-decent 工具链都应该能够为您执行此操作。
如果您正在使用 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()!
}
在此之后,您将拥有所有未初始化的全局变量。例如,您可以声明一个全局数组并在启动时检查其内容。
我希望在 atmega644p 上进行一些实验,以评估电源周期之间 SRAM 的衰减量。我的方法是将SRAM中的字节数设置为0xFF,然后当mcu上电时,统计这些字节中剩余1的个数。
为此,我需要读取和写入 1 的数组 to/from SRAM 中的已知内存地址。到目前为止,我有代码使用设置为 0x1000 的指针将值写入特定地址,然后在加电时我开始从该地址读取数组。但是,我需要一种方法来保证这部分 SRAM 内存(比如 0x100 + 64 字节)在读取之前不会分配给其他 variables/overwritten。
我在网上查看了分配内存段的可能性 - 我不知道在这种情况下这是否是一个好的解决方案,我什至不太确定如何去做。谁能建议一种巧妙的方法来解决这个问题?
如有任何问题请提问。
感谢您的帮助。
您需要通过在链接器文件中为它保留 space 来在 RAM 中创建一个自定义区域。重要的是它被标记为“no init”或类似的,否则 .bss
初始化和类似的可能会在调用 main() 之前发生在它上面。如何做到这一点是 linker-specific。
然而,为此编写软件似乎不必要地麻烦。只需使用 in-circuit 调试器:
- 确保您使用的调试器不为目标供电。
- 下载一个完全没有 RAM 的程序到闪存中。通过检查地图文件来确认这一点。
- 通过调试器将整个 RAM 设置为 0xFF。
- 断开电源,同时保持 in-circuit 调试器连接。
- 等待 x 个时间单位。
- 加电,在调试器中点击 MCU 复位,内存转储整个 RAM。
任何 half-decent 工具链都应该能够为您执行此操作。
如果您正在使用 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()!
}
在此之后,您将拥有所有未初始化的全局变量。例如,您可以声明一个全局数组并在启动时检查其内容。