Running UC3A FreeRTOS Demo from SDRAM
I am working with a client that plans on using an AT32UC3A0512-based controller board with 64MB of SDRAM @0xD0000000 and oodles of battery-backed SRAM for critical data. This controller board has two SPI DataFlash chips to provide storage for binary program files.
We would like to use FreeRTOS for the controller but need to configure it to run from the SDRAM instead of from internal CPU FLASH memory. I’ve written a loader program that initializes (and tests) SDRAM, then loads a binary file into SDRAM and executes it. I’ve modified one of the Atmel 1.3.0 software framework programs (USART demo) to run from SDRAM and it works fine.
I’ve not been successful, however, at rebuilding the FREERTOS Demo program in the 1.3.0 Software Framework to run out of SDRAM at 0xD0000000. For now I am using the EVK1100 board for proof of concept testing. I am using the gnu Makefile version of the project, and can use the original config.mk file to build it to run succcessfully from internal FLASH memory. But I suspect that my modified config.mk file for SDRAM execution is not right.
When running from SDRAM on the EVK1100, the USART demo spits out 24 characters on the USART, then dies. No LEDs flash at all. My loader program disables global interrupts before jumping to 0xD0000000. Of course, the JTAGICE Mk II cannot help me here because the SDRAM isn’t running after a reset.
The config.mk is shown below – it’s one that was posted on the AVRFreaks support forum (AVR General) by J Cesnik on Mar 21, 2008.
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf32-avr32", "elf32-avr32",
"elf32-avr32")
OUTPUT_ARCH(avr32:uc)
ENTRY(_start)
SEARCH_DIR("/home/mingwbuild/mingwavr32/avr32/lib");
/* Do we need any of these for elf?
__DYNAMIC = 0; */
MEMORY
{
SDRAM (rxai!w) : ORIGIN = 0xD0000000, LENGTH = 0x02000000
INTRAM (wxa!ri) : ORIGIN = 0x00000000, LENGTH = 64K
}
SECTIONS
{
/* Read-only sections, merged into text segment: */
PROVIDE (__executable_start = 0xD0000000); . = 0xD0000000;
.interp : { *(.interp) } >SDRAM AT>SDRAM
.reset : { *(.reset) } >SDRAM AT>SDRAM
.hash : { *(.hash) } >SDRAM AT>SDRAM
.dynsym : { *(.dynsym) } >SDRAM AT>SDRAM
.dynstr : { *(.dynstr) } >SDRAM AT>SDRAM
.gnu.version : { *(.gnu.version) } >SDRAM AT>SDRAM
.gnu.version_d : { *(.gnu.version_d) } >SDRAM AT>SDRAM
.gnu.version_r : { *(.gnu.version_r) } >SDRAM AT>SDRAM
.rel.init : { *(.rel.init) } >SDRAM AT>SDRAM
.rela.init : { *(.rela.init) } >SDRAM AT>SDRAM
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } >SDRAM AT>SDRAM
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } >SDRAM AT>SDRAM
.rel.fini : { *(.rel.fini) } >SDRAM AT>SDRAM
.rela.fini : { *(.rela.fini) } >SDRAM AT>SDRAM
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } >SDRAM AT>SDRAM
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } >SDRAM AT>SDRAM
.rel.data.rel.ro : { *(.rel.data.rel.ro*) } >SDRAM AT>SDRAM
.rela.data.rel.ro : { *(.rel.data.rel.ro*) } >SDRAM AT>SDRAM
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } >SDRAM AT>SDRAM
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } >SDRAM AT>SDRAM
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } >SDRAM AT>SDRAM
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } >SDRAM AT>SDRAM
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } >SDRAM AT>SDRAM
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } >SDRAM AT>SDRAM
.rel.ctors : { *(.rel.ctors) } >SDRAM AT>SDRAM
.rela.ctors : { *(.rela.ctors) } >SDRAM AT>SDRAM
.rel.dtors : { *(.rel.dtors) } >SDRAM AT>SDRAM
.rela.dtors : { *(.rela.dtors) } >SDRAM AT>SDRAM
.rel.got : { *(.rel.got) } >SDRAM AT>SDRAM
.rela.got : { *(.rela.got) } >SDRAM AT>SDRAM
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } >SDRAM AT>SDRAM
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } >SDRAM AT>SDRAM
.rel.plt : { *(.rel.plt) } >SDRAM AT>SDRAM
.rela.plt : { *(.rela.plt) } >SDRAM AT>SDRAM
.init :
{
KEEP (*(.init))
} >SDRAM AT>SDRAM =0xd703d703
.plt : { *(.plt) } >SDRAM AT>SDRAM
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} >SDRAM AT>SDRAM =0xd703d703
.fini :
{
KEEP (*(.fini))
} >SDRAM AT>SDRAM =0xd703d703
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } >SDRAM AT>SDRAM
.rodata1 : { *(.rodata1) } >SDRAM AT>SDRAM
.eh_frame_hdr : { *(.eh_frame_hdr) } >SDRAM AT>SDRAM
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } >SDRAM AT>SDRAM
.gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } >SDRAM AT>SDRAM
.dalign : { . = ALIGN(8); PROVIDE(_data_lma = .); } >SDRAM AT>SDRAM
PROVIDE (_data = ORIGIN(INTRAM));
. = ORIGIN(INTRAM);
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } >INTRAM AT>SDRAM
.gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } >INTRAM AT>SDRAM
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } >INTRAM AT>SDRAM
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } >INTRAM AT>SDRAM
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn’t pretty. */
PROVIDE (__preinit_array_start = ALIGN(32 / 8));
.preinit_array : { KEEP (*(.preinit_array)) } >INTRAM AT>SDRAM
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { KEEP (*(.init_array)) } >INTRAM AT>SDRAM
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { KEEP (*(.fini_array)) } >INTRAM AT>SDRAM
PROVIDE (__fini_array_end = .);
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn’t matter if the user does not
actually link against crtbegin.o; the
linker won’t look for a file to match a
wildcard. The wildcard also means that it
doesn’t matter which directory crtbegin.o
is in. */
KEEP (*crtbegin*.o(.ctors))
/* We don’t want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} >INTRAM AT>SDRAM
.dtors :
{
KEEP (*crtbegin*.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} >INTRAM AT>SDRAM
.jcr : { KEEP (*(.jcr)) } >INTRAM AT>SDRAM
.data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) } >INTRAM AT>SDRAM
.dynamic : { *(.dynamic) } >INTRAM AT>SDRAM
.got : { *(.got.plt) *(.got) } >INTRAM AT>SDRAM
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
KEEP (*(.gnu.linkonce.d.*personality*))
SORT(CONSTRUCTORS)
} >INTRAM AT>SDRAM
.data1 : { *(.data1) } >INTRAM AT>SDRAM
.balign : { . = ALIGN(8); _edata = .; } >INTRAM AT>SDRAM
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(8);
} >INTRAM AT>SDRAM
. = ALIGN(8);
_end = .;
PROVIDE (end = .);
__heap_start__ = ALIGN(8);
. = ORIGIN(INTRAM) + LENGTH(INTRAM) – 0x1000;
__heap_end__ = .;
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.stack ORIGIN(INTRAM) + LENGTH(INTRAM) – 0x1000 :
{
_stack = .;
*(.stack)
. = 0x1000;
_estack = .;
} >INTRAM AT>SDRAM
/DISCARD/ : { *(.note.GNU-stack) }
}
-————————————-
Here’s the linker output displayed:
uc3a0512-rtosdemo.elf :
section size addr
.reset 0x2008 0xd0000000
.got 0xc 0x18
.init 0x1c 0xd0002008
.text 0xbf78 0xd0002024
.exception 0x200 0xd000e000
.fini 0x18 0xd000e200
.rodata 0x294 0xd000e218
.dalign 0x4 0xd000e4ac
.ctors 0x8 0x4
.dtors 0x8 0xc
.jcr 0x4 0x14
.data 0x844 0x24
.bss 0x320 0x868
.comment 0x9fc 0x0
.debug_aranges 0x9e0 0x0
.debug_pubnames 0x1156 0x0
.debug_info 0x100c1 0x0
.debug_abbrev 0x1fe3 0x0
.debug_line 0x29aa 0x0
.debug_frame 0x2bcc 0x0
.debug_str 0xd02 0x0
.debug_loc 0x3129 0x0
.stack 0x1000 0xf000
.debug_ranges 0x1e8 0x0
Total 0x2db2f
text data bss dec hex filename
0xe448 0x864 0x1324 65488 ffd0 uc3a0512-rtosdemo.elf
I can’t help but notice that there’s no .heap shown.
Any hints would be most appreciated. I do not profess to be a linker expert and hopefully won’t need to be to get past
this issue.
Thanks,
Dave Squires
SQUIRES ENGINEERING, INC.
Running UC3A FreeRTOS Demo from SDRAM
FreeRTOS runs out of RAM fine on ARM7 and Coldfire so I think you are right to suspect the linker script. You could try the AVRFreaks WEB site to see if anybody can give you a linker script that is all set as you need it.
Running UC3A FreeRTOS Demo from SDRAM
I’ve got a pertinent update. Apparently in Atmel’s updated datasheet (08/2008) for the AVR32 UC3A processor, they now say that code execution from SDRAM does NOT work in any revision of silicon, contrary to the errata of the previous (04/2008) datasheet for the UC3A chips.
So now according to the best information I have, running FreeRTOS (or anything else) from SDRAM on a silicon Rev E, H, I J chip is not expected to work.
So my linker script may or may not be an issue. Trival (non-FreeRTOS) programs seem to work. I may have just gotten lucky. :)
Dave