首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AVR-GCC链接器:“数据”-Section溢出

AVR-GCC链接器:“数据”-Section溢出
EN

Stack Overflow用户
提问于 2017-10-12 09:30:17
回答 3查看 1.8K关注 0票数 0

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

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

我想,如果链接器给“数据部分”增加了太多,就会导致程序不可预测的行为。问题是链接器不能帮助我找到这一点。所以我很难找到一个稳定的解决方案。

我使用Atmel提供的下列链接器文件:

代码语言:javascript
复制
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)
  }

}

我设法找出了代码肯定不再起作用的数据量,在此之前,我还没有出现明显的故障。该程序的输出大小为:

代码语言:javascript
复制
text       data     bss     dec     hex filename
210260    10914   25427  246601   3c349 (TOTALS)

avr-gcc-大小-A:

代码语言:javascript
复制
    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

我有明显的故障,其大小为:

代码语言:javascript
复制
210260    10918   25427  246605   3c34d (TOTALS)

但是,只增加文本而不增加数据并不会导致任何结果:

代码语言:javascript
复制
210270    10914   25427  246611   3c353 (TOTALS)

有没有人知道,为什么这个程序在这一点上失败?我如何预测未来的极限,或者让链接器给我一个警告,什么时候可能会发生这种情况?

我没有收到任何链接错误信息或警告。这个程序现在就崩溃了。

EN

回答 3

Stack Overflow用户

发布于 2017-10-12 09:44:14

.data部分中的所有内容都占用了Flash。Flash中的部分用来初始化RAM中的部件。你可能快没内存了。所以我的建议是尽可能多地标记const。做这件事将被移动到.text段,在那里它只占用闪存,为了更好的东西而离开内存。

票数 1
EN

Stack Overflow用户

发布于 2017-10-12 11:50:40

这里发生了一些严重的误解。

  • 0x00800200, LENGTH = 32K - 500。200小时不等于500小时,但等于512小时。而且,0x00810000 - 0x00800000不是32k,而是64 32k。到处都有这样的错误,不管是谁安装了这个链接文件,他们都不知道自己在做什么,也不知道十六进制数字。
  • “程序的输出大小为.”10914 + 25427 = 36341字节。怎么能工作的很好,你刚刚说你有32基B的物理内存在芯片上可用。您还为堆栈保留了512字节。它不是很好,它似乎暂时有效,纯粹是偶然的。

如果您认为当您分配比物理可用内存更多的内存时,您的程序可以正常工作,那么您就没有希望恢复该程序。内存不能在稀薄的空气中分配。类似地,您不能将大于256 k的RW部分相加在一起,除非该芯片上有一些特殊的启动区域ROM。

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

票数 1
EN

Stack Overflow用户

发布于 2017-10-12 09:40:45

对于很少的bss+data,您的kB部分(可能都是数据区域)超过了数据区域。

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

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

我认为确保不会出现问题的唯一方法是扩展数据区域(如果您的板有更多的RAM),或者减小您初始化的+未初始化的数据的大小。

或者,您的一些初始化数据会转到eprom区域,并且只有在添加了几个字节之后才会溢出数据。当然,使用avr大小的-A yourexecutable,应该会显示更多的细节。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46706076

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档