AVR-GCC链接器:“;“数据”-区段溢流

AVR-GCC链接器:“;“数据”-区段溢流,c,gcc,linker,avr,C,Gcc,Linker,Avr,我正在使用Atmel AVR-GCC编译一个基于Atmel的Zigbee Bitcloud的项目。在Atmega256rfr2上(256k闪存,32k RAM) 在添加了更多的代码之后,我接近了内存的极限(似乎是这样) 我发现,如果链接器向“数据部分”添加了太多内容,就会导致程序的不可预测行为。问题是链接器不能帮助我找到这一点。因此,我正在努力寻找一个稳定的解决方案 我正在使用Atmel提供的以下链接器文件: OUTPUT_FORMAT("elf32-avr") OUTPUT_ARCH(avr:

我正在使用Atmel AVR-GCC编译一个基于Atmel的Zigbee Bitcloud的项目。在Atmega256rfr2上(256k闪存,32k RAM)

在添加了更多的代码之后,我接近了内存的极限(似乎是这样)

我发现,如果链接器向“数据部分”添加了太多内容,就会导致程序的不可预测行为。问题是链接器不能帮助我找到这一点。因此,我正在努力寻找一个稳定的解决方案

我正在使用Atmel提供的以下链接器文件:

OUTPUT_FORMAT("elf32-avr")
OUTPUT_ARCH(avr:6)

MEMORY
{
    text   (rx)   : ORIGIN = 0x00000000, LENGTH = 256K
    boot   (rx)   : ORIGIN = 0x0003F000, LENGTH = 4K
    access (rx)   : ORIGIN = 0x0003FFF0, LENGTH = 16
    data   (rw!x) : ORIGIN = 0x00800200, LENGTH = 32K - 500  /* leave 500 bytes for stack */
    eeprom (rw!x) : ORIGIN = 0x00810000, LENGTH = 8K
}

SECTIONS
{  
.text :
  {
    PROVIDE(__text_start = .);

    *(.vectors)
    KEEP(*(.vectors))
    . = ALIGN(0x400);

    /* PDS NV memory section */
    PROVIDE(__d_nv_mem_start = .);
    . = ALIGN(0x4400);
    PROVIDE(__d_nv_mem_end = .);

    /* Non-volatile file system PDS_FF section */
    PROVIDE(__pds_ff_start = .);
    KEEP(*(.pds_ff))
    PROVIDE(__pds_ff_end = .);

    /* Non-volatile file system PDS_FD section */
    PROVIDE(__pds_fd_start = .);
    KEEP(*(.pds_fd))
    PROVIDE(__pds_fd_end = .);

    *(.progmem.gcc*)
    *(.progmem*)
    . = ALIGN(2);

    *(.trampolines*)
    *(.jumptables*)
    *(.lowtext*)

    *(.init0)
    KEEP (*(.init0))
    *(.init1)
    KEEP (*(.init1))
    *(.init2)
    KEEP (*(.init2))
    *(.init3)
    KEEP (*(.init3))
    *(.init4)
    KEEP (*(.init4))
    *(.init5)
    KEEP (*(.init5))
    *(.init6)
    KEEP (*(.init6))
    *(.init7)
    KEEP (*(.init7))
    *(.init8)
    KEEP (*(.init8))

    *(.text.main)
    KEEP (*(.text*main))
    *(.text)
    *(.text.*)

    PROVIDE(__text_end = .);
  } > text

  .data : AT (ADDR(.text) + SIZEOF(.text))
  {
    PROVIDE(__data_start = .);
    *(.data*)
    *(.rodata*)
    *(.gnu.linkonce.d*)
    . = ALIGN(2);
    PROVIDE(__data_end = .);
  } > data

  .bss __data_end :
  {
    PROVIDE(__bss_start = .);
    *(.bss*)
    *(COMMON)
    PROVIDE(__bss_end = .);
  } > data

  .noinit __bss_end :
  {
    *(.noinit*)
    PROVIDE(__heap_start = .);
  } > data

  __stack_start = .;

  __data_load_start = LOADADDR(.data);
  __data_load_end = __data_load_start + SIZEOF(.data);

  .access_section :
  {
    KEEP(*(.access_section*))
    *(.access_section*)
  } > access

  .boot_section :
  {
    *(.boot_section*)
  } > boot

  .eeprom :
  {
    FILL(0xff)
    BYTE(0xff)
    . = . + LENGTH(eeprom)-1;
  } > eeprom

  /DISCARD/ :
  {
    *(.init9)
    *(.fini9)
  }

}
我设法弄清楚代码在多少数据量下肯定不再工作,直到多少数据量我才发现明显的故障。 该程序的输出大小为:

text       data     bss     dec     hex filename
210260    10914   25427  246601   3c349 (TOTALS)
avr gcc尺寸-A:

    section              size      addr
    .data                2722   8389120
    .text              209468         0
    .bss                25426   8391842
    .noinit                 1   8417268
    .access_section         4    262128
    .boot_section         798    258048
    .eeprom              8192   8454144
    .debug_info        538541         0
    .debug_abbrev       46706         0
    .debug_loc          73227         0
    .debug_aranges       5704         0
    .debug_ranges        6032         0
    .debug_line        108276         0
    .debug_str          89073         0
    .comment               92         0
    .debug_frame        14252         0
    Total             1128514
我有明显的故障,大小为:

210260    10918   25427  246605   3c34d (TOTALS)
仅增加文本,而不增加数据,不会导致任何结果:

210270    10914   25427  246611   3c353 (TOTALS)
有人知道为什么程序在这一点上失败了吗?我如何预测未来的极限,或者让链接器在可能发生这种情况时给我一个警告

我没有收到任何链接器错误消息或警告。程序在这一点上就崩溃了。

您的bss+数据部分(可能都会转到数据区域)超出了您的数据区域数kB

可能是由于一些随机行为,您在某个点写入堆栈,导致程序崩溃

如果节不适合区域,链接器应该警告您

我认为确保不会发生问题的唯一方法是扩展数据区域(若你们的主板有更多RAM),或者减小初始化+未初始化数据的大小


或者,您的一些初始化数据进入eprom区域,只有在添加几个字节后,数据才会溢出。请务必使用avr大小的可执行文件,该文件应显示更多细节。

您的bss+数据部分(可能都位于数据区域)超出数据区域数kB

可能是由于一些随机行为,您在某个点写入堆栈,导致程序崩溃

如果节不适合区域,链接器应该警告您

我认为确保不会发生问题的唯一方法是扩展数据区域(若你们的主板有更多RAM),或者减小初始化+未初始化数据的大小



或者,您的一些初始化数据进入eprom区域,只有在添加几个字节后,数据才会溢出。请务必使用avr大小的可执行文件,它应该显示更多细节。

数据部分的所有内容都占用闪存和RAM。闪存中的部件用于初始化RAM中的部件。你的内存可能快用完了。因此,我的建议是尽可能多地标记
const
。执行该操作将被移动到
.text
段中,在该段中,它只占用Flash并保留RAM,以便进行更好的操作。

.data
部分中的所有内容都占用Flash和RAM。闪存中的部件用于初始化RAM中的部件。你的内存可能快用完了。因此,我的建议是尽可能多地标记
const
。做这件事将被转移到
.text
部分,在那里它只占用Flash,留下RAM来做更好的事情。

这里有一些严重的误解

  • 0x00800200,长度=32K-500
    。200h与500不同,但与512相同。而且,
    0x00810000-0x00800000
    不是32k而是64kib。到处都有这样的错误,不管是谁安装了这个链接器文件,都不知道他们在做什么,也不知道十六进制数
  • “程序的输出大小为…”10914+25427=36341字节。它怎么能工作得很好,你刚才说芯片上有32kib的物理内存。您还为堆栈保留512字节。它不太好用,现在看来似乎很管用,纯粹是偶然的
如果您认为当您分配的内存超过实际可用内存时,您的程序可以正常工作,那么您就不可能恢复此程序。内存无法在稀薄的空气中分配。类似地,除非该芯片上有一些特殊的引导区域ROM,否则不能将大于256k的RW部分添加在一起


你没有收到任何链接器警告的原因可能是因为你告诉链接器你有64kib可用,而物理芯片只有32kib。

这里有一些严重的误解

  • 0x00800200,长度=32K-500
    。200h与500不同,但与512相同。而且,
    0x00810000-0x00800000
    不是32k而是64kib。到处都有这样的错误,不管是谁安装了这个链接器文件,都不知道他们在做什么,也不知道十六进制数
  • “程序的输出大小为…”10914+25427=36341字节。它怎么能工作得很好,你刚才说芯片上有32kib的物理内存。您还为堆栈保留512字节。它不太好用,现在看来似乎很管用,纯粹是偶然的
如果您认为当您分配的内存超过实际可用内存时,您的程序可以正常工作,那么您就不可能恢复此程序。内存无法在稀薄的空气中分配。类似地,除非该芯片上有一些特殊的引导区域ROM,否则不能将大于256k的RW部分添加在一起


您没有收到任何链接器警告的原因可能是您告诉链接器您有64kib可用,而物理芯片只有32kib。

常量变量仍将占用SRAM。Const不能用于声明数据在程序空间中。@Rev1.0当
Const
不在程序空间中时,注释实际将数据放入程序空间的内容会很有用,-
PROGMEM
属性。@Rev1.0:A
静态Const
通常由