【发布时间】:2015-06-08 14:22:20
【问题描述】:
我有一个微控制器,它有很多闪存,分为 1k 个闪存扇区。 我想在闪存期间将质数闪存到特定的内存区域,然后在第一次启动期间将生成一个加密密钥,然后质数将被擦除并覆盖。
我希望将质数隐藏在 m_text 中,而不是使用链接描述文件为质数创建读/写内存区域。
固件、素数和引导加载程序分别编译,生成 3 个用于闪存的 .hex 文件。
假设固件代码从 0x2000 开始,长度为 0x2000,在该区域内,我想分配一个 1024 字节的扇区,以后可以擦除和覆盖该扇区,而不会使固件变砖。
使用以下代码,我可以读取、擦除和写入数据到闪存,但我有一些问题:
- 使用以下代码 gcc 会在 0x3000 分配扇区吗?如果没有,怎么办?
- 您知道更好的方法吗?
代码:
...
typedef uint8_t sector[1024];
uint32_t* prime = (sector*)0x3000;
uint32_t data = *prime;
uint32_t dataToWrite = 0xdeadbeef;
flash_init();
flash_sector_erase(0x3000);
flash_block(0x3000,(uint8_t*)&dataToWrite,4);
data = *prime;
...
链接脚本
MEMORY {
...
m_text(rx): ORIGIN = 0x00002000, LENGTH = 0x2000
...
}
更新: 我必须使用 GCC 在给定的闪存地址保留空间,这表明其他编译器对此有解决方案,但使用 GCC 我必须使用链接器脚本。
来自here 我读到这个:
特殊的链接器变量点 `.'始终包含当前输出 位置计数器。自 .总是指输出中的一个位置 部分,它只能出现在 SECTIONS 中的表达式中 命令。这 。符号可能出现在普通符号所在的任何地方 允许在表达式中。
为 .将导致位置计数器移动。 这可用于在输出部分创建孔。那个地点 计数器可能永远不会向后移动。
SECTIONS
{
output :
{
file1(.text)
. = . + 1000;
file2(.text)
. += 1000;
file3(.text)
} = 0x1234;
}
在前面的示例中,
.text' section fromfile1' 位于 在输出部分的开头output'. It is followed by a 1000 byte gap. Then the.text' 部分来自file2' appears, also with a 1000 byte gap following before the.text' 部分来自file3'. The notation= 0x1234' 指定要写入的数据 间隙(请参阅输出部分填充部分)。
我的 m_text 部分如下所示:
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
所以我能做的就是把它改成:
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
. = NEXT(0x400); /* move to start of next 1kb section*/
. += 0x400; /* jump 1k forward */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
} > m_text
现在我们在闪存上保留了数据,但地址将取决于 .text 的大小,这并不理想,但如果我们将 FW 代码中的直接寻址更改为节名然后取来自 FW 项目的 .text 的大小并填充到下一个 1024 字节扇区以获取我们将导入到 Prime number 项目的地址。
我对扇区之前的填充也不太满意,在理想情况下,我们会用“垃圾代码”或随机数据填充它,我已经看到您可以指定要填充的模式,但任何一致的模式将向逆向工程师发出多达 0xffffff 或 0x00000 ;)
有更好的想法吗?
【问题讨论】:
-
类似问题here.
标签: c embedded bare-metal linker-scripts