在嵌入式目标上的FLASH的m_text内存区域中保留内存空间

时间:2015-06-08 14:22:20

标签: c embedded bare-metal linker-scripts

我有一个微控制器,闪存分为1k个闪存扇区。 我希望在闪存期间将素数闪存到特定的存储区域,然后在第一次启动期间将生成加密密钥,然后将删除和覆盖素数。

我更希望隐藏m_text中的素数,而不是使用链接描述文件为素数创建读/写内存区域。

固件,素数和引导程序分别编译,产生3个用于闪存的.hex文件。

假设FW代码从0x2000开始并且它是0x2000长,在该区域内我想分配一个1024字节的扇区,以后可以擦除和覆盖,而不会使FW变砖。

使用以下代码,我可以读取,擦除和写入闪存数据,但我有一些问题:

  1. 使用以下代码将gcc分配到0x3000的扇区?如果没有,怎么样?
  2. 你知道更好的方法吗?
  3. 代码:

    ...
    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我读到了这个:

      

    特殊链接器变量dot`。'始终包含当前输出   地点柜台。自从。始终指的是输出中的位置   部分,它可能只出现在SECTIONS中的表达式中   命令。的。符号可以出现在普通符号的任何位置   允许表达。

         

    为...分配值。将导致位置计数器被移动。   这可用于在输出部分中创建孔。那个地点   柜台可能永远不会倒退。

    SECTIONS
    {
      output :
        {
          file1(.text)
          . = . + 1000;
          file2(.text)
          . += 1000;
          file3(.text)
        } = 0x1234;
    }
    
      

    在上一个示例中,.text' section from file1'位于   在输出部分的开头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
    

    现在我们已经在flash上​​保留了数据,但地址将取决于.text的大小并不理想,但是如果我们从FW代码中的直接寻址更改为节名称然后取从FW项目和padd到。下一个1024字节扇区的.text大小,以获取我们将导入Prime数字项目的地址。

    我对扇区之前的填充也不太满意,在一个理想的世界中,我们会用#"垃圾代码"或随机数据,我已经看到你可以指定一个模式来填充,但任何一致的模式将向反向工程师发出高达0xffffff或0x00000;)

    任何更好的想法?

2 个答案:

答案 0 :(得分:1)

您可以使用gcc cat将数组定位到m_text部分。

内存区域不是一个部分。因此,您需要将此部分添加到链接器脚本,将其放入此内存区域(不确定,如果两者都使用不同的命名空间,但为区域和节具有不同的名称将是更好的样式)。如果未加载该程序,则必须为__attribute__((section("m_text") ))(非常类似于NOLOAD)。

或者您只使用C构造而根本没有链接器。但是,这会阻止数据加载程序,因此只有在打算从程序中单独编程该区域时才能正常工作。

答案 1 :(得分:1)

不确定您使用的编译器,但使用GCC,您可以指定section属性details here的部分。