我正在使用Atmel AVR-GCC编写一个基于Atmel的Zigbee的项目。Atmega256rfr2( 256 k闪存,32k内存)
在添加了更多代码之后,我正在接近内存的极限(似乎是这样)。
我想,如果链接器给“数据部分”增加了太多,就会导致程序不可预测的行为。问题是链接器不能帮助我找到这一点。所以我很难找到一个稳定的解决方案。
我使用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)有没有人知道,为什么这个程序在这一点上失败?我如何预测未来的极限,或者让链接器给我一个警告,什么时候可能会发生这种情况?
我没有收到任何链接错误信息或警告。这个程序现在就崩溃了。
发布于 2017-10-12 09:44:14
.data部分中的所有内容都占用了Flash。Flash中的部分用来初始化RAM中的部件。你可能快没内存了。所以我的建议是尽可能多地标记const。做这件事将被移动到.text段,在那里它只占用闪存,为了更好的东西而离开内存。
发布于 2017-10-12 11:50:40
这里发生了一些严重的误解。
0x00800200, LENGTH = 32K - 500。200小时不等于500小时,但等于512小时。而且,0x00810000 - 0x00800000不是32k,而是64 32k。到处都有这样的错误,不管是谁安装了这个链接文件,他们都不知道自己在做什么,也不知道十六进制数字。如果您认为当您分配比物理可用内存更多的内存时,您的程序可以正常工作,那么您就没有希望恢复该程序。内存不能在稀薄的空气中分配。类似地,您不能将大于256 k的RW部分相加在一起,除非该芯片上有一些特殊的启动区域ROM。
您没有收到任何链接器警告的原因可能是因为您已经告诉链接器您有64 got可用,而物理芯片只有32 got。
发布于 2017-10-12 09:40:45
对于很少的bss+data,您的kB部分(可能都是数据区域)超过了数据区域。
可能是由于某些随机行为,您在某个点写入堆栈,导致程序崩溃。
链接器应警告您,如果区段不适合该区域。
我认为确保不会出现问题的唯一方法是扩展数据区域(如果您的板有更多的RAM),或者减小您初始化的+未初始化的数据的大小。
或者,您的一些初始化数据会转到eprom区域,并且只有在添加了几个字节之后才会溢出数据。当然,使用avr大小的-A yourexecutable,应该会显示更多的细节。
https://stackoverflow.com/questions/46706076
复制相似问题