c - 如果不使用 const,RAM 中不需要的分配,尽管放置在 Flash 绝对地址

标签 c gcc attributes constants stm32

我正在使用 GCC。我通过 .ld 链接器文件在 Flash 中创建了一个 SECTION, 我用指令 __attribute__((section... 数据似乎在闪存中,但如果我在声明数据时不使用 const 关键字,则会在 RAM 中分配相同的空间。

如果我使用 const RAM 不会被使用 - 但我注意到闪存的使用增加了,因为它在那里分配了两次!

链接器文件:

FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 14K
USER_DATA_FLASH (rx)      : ORIGIN = 0x8003800, LENGTH = 2K
}

SECTIONS
{ /* placing my named section at given address: */
  .my_block 0x8003800 :
 {
  KEEP(*(.UserDataSector)) 
 } > USER_DATA_FLASH
}

数组声明有初始化器:

mytab_type  __attribute__((section (".UserDataSector "))) progr16[16]=
{ 
    { {LIST1,LIST2....

在这种情况下,我没有使用const。假设 progr16 被强制放在闪存中,如果我在调试期间检查内存浏览器,它实际上看起来在那里。但它似乎也占用内存

FLASH    RAM
text     data    bss   dec     
9268     772     1948  11988    

如果我添加 const 关键字:

FLASH    RAM
text     data    bss    dec 
9972     68      1948   11988

好的,RAM 中保存了 704 字节的数据,但是为什么相同数量的字节会增加 Flash 的使用,如果这个值已经在 Flash 中的某个位置(因为初始化程序)?

最佳答案

我还没有机会像我计划的那样实际设置和构建一个独立项目来彻底测试它,但是添加 NOLOAD 是否有效?

SECTIONS
{ 
    .my_block (NOLOAD) :
    {
        KEEP(*(.UserDataSector));
    } >USER_DATA_FLASH
}

这是我在 v2.32 ld PDF 用户手册中为“NOLOAD”做的一些笔记: enter image description here

这似乎是您可能需要的。

此外,我通常将属性说明符放在变量之后,如许多官方 gcc 示例(例如 the ones under "section" here )所示,尽管我不确定这是严格要求的(请参阅 official syntax documentation here )。

即:

static my_type my_array_name[] __attribute__((section(".UserDataSector"))) =
{
    // member 1,
    // member 2,
    // member 3,
    // etc
};

另外,我必须说,你的问题中的格式(空格、对齐、缩进等)不是很好,并且沿着这些没有密切关注细节的思路,我在你的部分属性中看到你有一个末尾的额外空间:".UserDataSector" 而不是 ".UserDataSector",就像它应该的那样,所以这也可能是问题所在。

另外,还有一些注意事项:

  1. 请注意,您应该稍微清理格式、缩进等,以使问题中的代码更易于阅读。
  2. 我认为 KEEP 在这里不是必需的,但我认为它也不会伤害任何东西。
  3. 您应该研究和阅读官方 GNU 链接描述文件 (LD) 手册。它以 html 格式在线提供,请访问:https://sourceware.org/binutils/docs/ld/。最新版本是v2.32。

    1. 但是,我认为在 PDF 中学习要容易得多,因此您可以在其中键入、突出显示、标记、一次性搜索等。构建 LD pdf 用户手册,然后使用 Foxit Reader(交叉-平台,免费)来学习和标记手册。
    2. 如何构建链接描述文件 (LD) PDF 用户手册:
    3. 下载源代码:https://www.gnu.org/software/binutils/
      1. 例如:在此处获取最新的 binutils 版本(当前为 binutils-2.32.tar.xz):https://ftp.gnu.org/gnu/binutils/
    4. 将其解压(例如,在 Linux Ubuntu 中右键单击并转到“Extract Here”)。
    5. cd 进入文件夹:cd binutils-2.32
    6. 然后配置并制作:

      ./configure
      make
      make pdf
      
    7. 完成!现在是 PDF(使用 find | grep '\.pdf' 找到):

      binutils-2.32/libiberty/libiberty.pdf
      binutils-2.32/bfd/doc/bfd.pdf
      binutils-2.32/ld/ld.pdf    <----- THE MAIN ONE I WANT!
      binutils-2.32/gprof/gprof.pdf
      binutils-2.32/gas/doc/as.pdf
      binutils-2.32/binutils/doc/binutils.pdf
      
    8. 保存并使用 ld.pdf,它现在是我上面链接的 HTML 2.32 binutils 手册的 PDF 版本。

  4. 您可能需要阅读您的启动文件,看看它是否在做任何奇怪的事情。

就像我说的,我想在发布之前全面测试这个答案,但现在没有机会。不过,在过去的几周里,我在链接器脚本上花费了很多时间,所以我对其中的一些内存犹新,我认为这会有所帮助。

注意的其他链接描述文件问题

  1. Is accessing the "value" of a linker script variable undefined behavior in C?
  2. How to get value of variable defined in ld linker script from C

关于c - 如果不使用 const,RAM 中不需要的分配,尽管放置在 Flash 绝对地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55863306/

相关文章:

c - 访问函数中的链表 - C

C 项目 (POS) - 显示付款更改错误

c++ - 头文件和源文件中的内联函数

c - Glibc - ucontext.h 中的错误,但仅限于 -std=c11

objective-c - Objective-c 中的自定义属性

python - 为什么 setattr 和 getattr 允许空格?

MySQL 字符串格式化+条件语句

c - 删除二维整数数组,在 C 中将指针设置为空

c++ - Qt/C++ - 生成的条码不可读

c++ - 非捕获通用 lambda 应该衰减为函数指针吗?