我有一个微控制器,其中有许多闪存分为1k闪存扇区。我想在闪烁期间将素数闪存到特定的内存区域,然后在第一次启动期间将生成一个加密密钥,然后素数将被擦除和覆盖。
我更愿意隐藏质数在m_text中,而不是用链接器脚本为质数创建一个读写内存区域。
固件,素数和引导加载程序分别编译,导致用于flash的3 .hex文件。
假设FW代码从0x2000开始,它是0x2000长,在该区域内,我想分配一个1024字节的扇区,以后可以擦除和覆盖而不阻塞FW。
使用以下代码,我可以读取,擦除和写入数据到闪存,但我有一些问题:
- 下面的代码将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在给定的flash地址保留空间,似乎其他编译器对此有解决方案,但与GCC一起,我必须使用链接器脚本。
从这里我读到这个:
特殊的链接器变量点'。'总是包含当前输出位置计数器。自从。总是指输出中的一个位置section中,它只能出现在section中的表达式中命令。的。符号可以出现在普通符号所在的任何地方
赋值给。将导致位置计数器被移动。这可以用来在输出部分创建孔洞。的位置计数器不能向后移动。
SECTIONS
{
output :
{
file1(.text)
. = . + 1000;
file2(.text)
. += 1000;
file3(.text)
} = 0x1234;
}
在前面的示例中,定位了
.text' section from
文件e1'在输出部分的开头,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字节扇区,以获得我们将导入到素数项目的地址,则可能会起作用。
我对扇区之前的填充也不太满意,在理想的世界里,我们会用"垃圾代码"或随机数据填充它,我已经看到你可以指定一个模式来填充,但是任何一致的模式都会像0xffffff或0x00000一样发光到逆向工程师;)
有更好的主意吗?
不确定您使用的是哪种编译器,但使用GCC,您可以在这里指定section
属性详细信息的部分
您可以使用gcc __attribute__((section("m_text") ))
将数组定位到m_text
部分。
一个内存区域不是一个section。因此,您需要将该部分添加到链接器脚本中,并将其放入该内存区域(不确定,如果两者使用不同的名称空间,但是为区域和部分使用不同的名称会更好)。如果它没有加载到程序中,它必须是NOLOAD
(很像.bss
)。
或者你只使用C结构而不使用链接器。但是,这将阻止数据与程序一起加载,因此只有当您打算将该区域与程序分开编程时才有效。