AVR-GCC链接器:“;“数据”-区段溢流
我正在使用Atmel AVR-GCC编译一个基于Atmel的Zigbee Bitcloud的项目。在Atmega256rfr2上(256k闪存,32k RAM) 在添加了更多的代码之后,我接近了内存的极限(似乎是这样) 我发现,如果链接器向“数据部分”添加了太多内容,就会导致程序的不可预测行为。问题是链接器不能帮助我找到这一点。因此,我正在努力寻找一个稳定的解决方案 我正在使用Atmel提供的以下链接器文件: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:
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来做更好的事情。这里有一些严重的误解
。200h与500不同,但与512相同。而且,0x00800200,长度=32K-500
不是32k而是64kib。到处都有这样的错误,不管是谁安装了这个链接器文件,都不知道他们在做什么,也不知道十六进制数0x00810000-0x00800000
- “程序的输出大小为…”10914+25427=36341字节。它怎么能工作得很好,你刚才说芯片上有32kib的物理内存。您还为堆栈保留512字节。它不太好用,现在看来似乎很管用,纯粹是偶然的李>
你没有收到任何链接器警告的原因可能是因为你告诉链接器你有64kib可用,而物理芯片只有32kib。这里有一些严重的误解
。200h与500不同,但与512相同。而且,0x00800200,长度=32K-500
不是32k而是64kib。到处都有这样的错误,不管是谁安装了这个链接器文件,都不知道他们在做什么,也不知道十六进制数0x00810000-0x00800000
- “程序的输出大小为…”10914+25427=36341字节。它怎么能工作得很好,你刚才说芯片上有32kib的物理内存。您还为堆栈保留512字节。它不太好用,现在看来似乎很管用,纯粹是偶然的李>
您没有收到任何链接器警告的原因可能是您告诉链接器您有64kib可用,而物理芯片只有32kib。常量变量仍将占用SRAM。Const不能用于声明数据在程序空间中。@Rev1.0当
Const
不在程序空间中时,注释实际将数据放入程序空间的内容会很有用,-PROGMEM
属性。@Rev1.0:A静态Const
通常由