我正在使用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-size -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)
有没有人知道,为什么程序在这一点上失败了?如果可能发生这种情况,我怎样才能预测未来的限制或让链接器给我一个警告?
我没有收到任何链接器错误消息或警告。该程序此时崩溃了。
答案 0 :(得分:1)
Everything in the .data
section takes up Flash and RAM. The part in Flash is used to initialize the part in RAM. You're probably running out of RAM. So my suggestion is to mark as much as possible as const
. Doing that thing will be moved into the .text
segment, where it occupies just Flash and leaves RAM for better things.
答案 1 :(得分:1)
这里有一些严重的误解。
should
。 200h与500不同,但与512相同。此外,0x00800200, LENGTH = 32K - 500
不是32k而是64kib。全部都有很多这样的错误,无论谁设置这个链接器文件都不知道他们在做什么,他们不知道十六进制数。如果您认为当您分配的内存超过实际可用内存时,您的程序可以正常工作,那么您无需恢复此程序。记忆不能在空气中分配。同样,除非在该芯片上有一些特殊的引导区ROM,否则不能将大于256k的RW部分加在一起。
您没有收到任何链接器警告的原因可能是因为您告诉链接器您有64kib可用,而物理芯片只有32kib。
答案 2 :(得分:0)
Your bss+data sections (both probably go to data region) exceed your data region for few kB.
Probably due to some random behavior, you write over your stack at some point, which crashes your program.
Linker should warn you if section does not fit the region.
I think only way to be sure no issues will occur is to extend data region (if yor board has more RAM), or decrease size of your initialized + uninitialized data.
Or maybe some of your initialized data goes to eprom region, and only after you add few bytes you overflow data. To be sure use avr-something-size -A yourexecutable, which should show more detail.