C 在嵌入式目标闪存的m_文本存储区域中保留存储空间
我有一个微控制器,有很多闪存,分为1k闪存扇区。 我想在闪烁期间将素数闪烁到一个特定的内存区域,然后在第一次引导期间将生成一个加密密钥,然后素数将被擦除和覆盖 我更喜欢将素数隐藏在m_文本中,而不是使用链接器脚本为素数创建读/写内存区域 固件、素数和引导加载程序分别编译,生成用于闪存的3.hex文件 假设FW代码从0x2000开始,长度为0x2000,在该区域内,我想分配一个1024字节的扇区,以后可以在不阻塞FW的情况下擦除和覆盖该扇区 使用以下代码,我可以读取、擦除和写入闪存中的数据,但我有一些问题:C 在嵌入式目标闪存的m_文本存储区域中保留存储空间,c,embedded,bare-metal,linker-scripts,C,Embedded,Bare Metal,Linker Scripts,我有一个微控制器,有很多闪存,分为1k闪存扇区。 我想在闪烁期间将素数闪烁到一个特定的内存区域,然后在第一次引导期间将生成一个加密密钥,然后素数将被擦除和覆盖 我更喜欢将素数隐藏在m_文本中,而不是使用链接器脚本为素数创建读/写内存区域 固件、素数和引导加载程序分别编译,生成用于闪存的3.hex文件 假设FW代码从0x2000开始,长度为0x2000,在该区域内,我想分配一个1024字节的扇区,以后可以在不阻塞FW的情况下擦除和覆盖该扇区 使用以下代码,我可以读取、擦除和写入闪存中的数据,但我有
MEMORY {
...
m_text(rx): ORIGIN = 0x00002000, LENGTH = 0x2000
...
}
更新:
我必须使用GCC在给定的闪存地址上预留空间,其他编译器对此有解决方案,但使用GCC我必须使用链接器脚本
我从中读到:
特殊链接器变量点“.”始终包含当前输出
位置计数器。从那以后。始终引用输出中的位置
节中,它只能出现在节中的表达式中
指挥部。这个符号可以出现在普通符号所在的任何位置
在表达式中允许
给…赋值。将导致位置计数器移动。
这可用于在输出截面中创建孔。地点
计数器不能向后移动
在上一个示例中,file1'中的.text'部分位于
在输出部分的开头output'。然后是一个
1000字节的间隔。然后,file2'中的
.text'部分也会出现
在中的
.text”部分之前有1000字节的间隙
file3'。符号
=0x1234'指定要在中写入的数据
间隙(请参见“输出”部分“填充”)
我的m_文本部分如下所示:
.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
现在我们在闪存上保留了数据,但地址将取决于的大小。文本的大小并不理想,但是,如果我们将FW代码中的直接寻址改为节名,然后将.text的大小从FW项目和padd移到下一个1024字节的扇区,以获得我们将导入素数项目的地址,那么这可能会起作用
我对扇区之前的填充也不太满意,在一个理想的世界中,我们会用“垃圾代码”或随机数据填充它,我已经看到您可以指定填充的模式,但任何一致的模式都会在逆向工程中亮起0xffffff或0x00000;)
有更好的主意吗?您可以使用gcc\uu属性((section(“m\u text”))
将数组定位到m\u text
部分
内存区域不是节。因此,您需要将此节添加到链接器脚本中,将其放入此内存区域(不确定,如果两者使用不同的名称空间,但最好为区域和节使用不同的名称)。如果该程序未加载,则必须是NOLOAD
(很像.bss
)
或者只使用C构造,而根本不使用链接器工具。但是,这将阻止数据随程序加载,因此只有当您打算将该区域与程序分开编程时,它才起作用。不确定您使用的编译器是什么,但对于GCC,您可以使用section
属性指定该节。质数和引导加载程序是分开编译的,产生用于闪存的3.hex文件。@Maidenone:那么我要么使用C-only方法,使用转换为实际类型的绝对地址(很像外围寄存器-您可以使用const
来防止意外写入),要么使用NOLOAD
方法。但是我如何控制内存分配的位置呢?假设程序从0开始,长度为200,我希望在不覆盖程序数据的情况下将素数设置为50。@MaideOne:您必须更改程序的闪存区域,以排除保留(m_文本)区域。最好的建议是对数组/表使用最上面的扇区,对程序使用最下面的所有扇区,反之亦然(对于ARM,最好保留较低的两个扇区,因为ARM希望其重置向量位于较低的1/2字处)。请注意,如果要从引导加载程序中分别擦除/写入表,则每个表都需要一个单独的扇区。@Maidenone:请注意,您不分配,而是保留该区域。这是一个很小但很重要的区别。类似的问题。
.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