-
Notifications
You must be signed in to change notification settings - Fork 15
ARC64 Hello World example
You should have the ARC64 toolchain installed. The PATH environment variable needs to set and point to your toolchain installation.
A modulefile example can be as fallows:
#%Module1.0########################################################################
##
## ARC gcc module file
##
set ModulesVersion "arc64"
proc ModulesHelp {} {
global version
puts stderr " This module loads the ARC ELF toolchain"
puts stderr " Version $version"
puts stderr ""
}
module-whatis "arc_elf"
set arcinstall <my toolchain install path>
prepend-path PATH $arcinstall/bin
conflict arc_elf
Code hello.c:
#include <stdio.h>
void main (void)
{
printf ("Hello Workd\n");
}
Compiling for nSIM simulator using GNU hostlink I/O:
arc64-elf-gcc -O2 hello.c --specs=nsim.specs -o hello.x
Executing using nSIM simulator:
nsimdrv -on nsim_isa_enable_timer_0 -on nsim_isa_enable_timer_1 -off invalid_instruction_interrupt -off memory_exception_interrupt -on nsim_download_elf_sections -on nsim_emt -prop=nsim_isa_family=arc64 -p nsim_isa_div_rem_option=2 -p nsim_isa_mpy_option=3 -p nsim_isa_atomic_option=1 -p nsim_isa_shift_option=0 -p nsim_isa_bitscan_option=0 ./hello.x
Compiling for nSIM/MDB usign MWDT hostlink I/O:
arc64-elf-gcc -O2 hello.c --specs=hl.specs -o hello.x
Executing using MDB:
mdb -arc64 -run -cl hello.x
Executing using nSIM:
nsimdrv -on nsim_isa_enable_timer_0 -on nsim_isa_enable_timer_1 -off invalid_instruction_interrupt -off memory_exception_interrupt -on nsim_download_elf_sections -prop=nsim_isa_family=arc64 -p nsim_isa_div_rem_option=2 -p nsim_isa_mpy_option=3 -p nsim_isa_atomic_option=1 -p nsim_isa_shift_option=0 -p nsim_isa_bitscan_option=0 ./hello.x
Compiling for QEMU simulator:
arc64-elf-gcc -O2 hello.c --specs=qemu.specs -o hello.x
Executing using QEMU:
qemu-system-arc64 -M arc-sim -cpu arc64 -m 2G -nographic -no-reboot -monitor none -serial stdio -kernel hello.x
The default script is sufficient for applications starting at address 0x0000000
. The default heap is 20k, the default stack size 64k. The default linker script is providing the following heap/stack variables:
__start_heap
__end_heap
__stack
__stack_top
Using arc64-elf-nm:
arc64-elf-nm hello.x | grep "_heap"
The output will show the addresses of the heap start and end. The same we can do using stack matching pattern.
Changing the default stack or heap size can be done easily using the following linker commands:
-Wl,--defsym=__HEAP_SIZE=256m -Wl,--defsym=__STACK_SIZE=1024m
which will change the HEAP and the STACK accordingly. N.B. we can use either one, no need to increase stack size if sufficient. However, the programmer needs to make sure the stack and the heap are within the target memory range (he can use nm app as shown above).
If the default linker script doesn't satisfies the target needs one can use a custom script. Here it is a template:
MEMORY {
ICCM : ORIGIN = 0x00000000, LENGTH = 0xc0000000
DCCM : ORIGIN = 0xc0000000, LENGTH = 0x40000000
}
.ivt DEFINED (ivtbase_addr) ? ivtbase_addr : ORIGIN(ICCM) :
{
PROVIDE (__ivtbase_addr = .);
KEEP (*(.ivt));
} > ICCM
.text :
{
. = ALIGN(4);
KEEP (*(SORT_NONE(.init)))
/* Start here after reset. */
. = ALIGN(4);
KEEP (*crt0.o(.text.__startup))
/* Remaining code. */
. = ALIGN(4);
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf.em. */
*(.gnu.warning)
} > ICCM =0
.fini :
{
KEEP (*(SORT_NONE(.fini)))
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
} > ICCM =0
.jcr :
{
KEEP (*(.jcr))
} > ICCM
.rodata :
{
*(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*)
} > ICCM
.rodata1 : { *(.rodata1) } > ICCM
__data_image = .;
PROVIDE (__data_image = .);
.data :
{
PROVIDE (__data_start = .) ;
KEEP (*(.data))
*(.data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
} > DCCM
.ctors :
{
KEEP (*crtbegin*.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
} > DCCM
.dtors :
{
KEEP (*crtbegin*.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
} > DCCM
.sbss :
{
PROVIDE (__sbss_start = .);
PROVIDE (___sbss_start = .);
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
PROVIDE (__sbss_end = .);
PROVIDE (___sbss_end = .);
} > DCCM
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } > DCCM
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(32 / 8);
_end = .;
PROVIDE (end = .);
} > DCCM
.noinit :
{
*(.noinit*)
. = ALIGN(32 / 8);
PROVIDE (__start_heap = .) ;
} > DCCM
PROVIDE (__stack_top = (ORIGIN (DCCM) + LENGTH (DCCM) - 1) & -4);
PROVIDE (__end_heap = ORIGIN (DCCM) + LENGTH (DCCM) - 1);
}