2

I'm using the gcc cross-compiler for the LEON2 processor (Sparc v8), however after inspecting the startup code I wanted to provide my own for various reason (we are working in space applications and the code is not up to standards and its also very complicated in my opinion. Also I find this part very interesting). And since we are only using the ported newlib and no RTOS I thought this could be doable without too much work.

In order to do this I compiled my application with -nostartfiles and so I provided my own start entry point etc... The code was taken from the actual startup files with some modification from me.

This seems to work however I'm now stuck at the part where I'm supposed to initialize the newlib.

In order to understand how this works I compiled with and without the -nostartfiles flag to find the differences. I'm only showing the last part here when gcc calls collect2 since the other parts are not relevant.

This is a simple application built without -nostartfiles

/opt/sparc-elf-4.4.2/bin/../libexec/gcc/sparc-elf/4.4.2/collect2
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/../../../../sparc-elf/lib/locore_mvt.o 
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/../../../../sparc-elf/lib/crt0.o
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crti.o
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crtbegin.o
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/../../../../sparc-elf/lib/pnpinit_simple.o
-L/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2 
-L/opt/sparc-elf-4.4.2/bin/../lib/gcc 
-L/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/../../../../sparc-elf/lib 
/tmp/ccCfxzLR.o 
-lgcc
--start-group -lc -lgcc -lleonbare --end-group
-lgcc 
--start-group -lc -lgcc -lleonbare --end-group
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crtend.o
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crtn.o

Now after some tweaking I managed to get something similar for my application.

/opt/sparc-elf-4.4.2/bin/../libexec/gcc/sparc-elf/4.4.2/collect2
-o debug/BSW 
-L../../drv_EEPROM/SRC/debug 
-L/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2 
-L/opt/sparc-elf-4.4.2/bin/../lib/gcc 
-L/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/../../../../sparc-elf/lib 
-Map BSW_memory.map 
debug/trap_table.o 
debug/trap_reset.o 
debug/trap_access_exception.o 
debug/trap_fp_disabled.o 
debug/trap_window_overflow.o 
debug/trap_window_underflow.o 
debug/cpu_info.o 
debug/cpu_init.o 
debug/init_hooks.o 
debug/start_sequence.o 
debug/main.o 
debug/pnpinit_simple.o 
debug/register_atexit.o 
-lDrvEEPROM 
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crti.o 
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crtbegin.o 
-lgcc -lc -lgcc -lleonbare -lgcc -lc -lgcc -lleonbare 
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crtend.o 
/opt/sparc-elf-4.4.2/bin/../lib/gcc/sparc-elf/4.4.2/crtn.o 
-Tlinkbootram

I've debugged this in GDB and I can see my code is properly executed, at least it seems, up until the main is called. My main is very simple with just a call to printf. Sadly this call to printf never returns and seems to loop forever. So I guess some initialization is not correctly done.

I'm trying to understand how things are done but all this stuff is quite obscure and not a lot of documentation seems available. I'm still learning so I probably am missing something important but maybe some knowledgeable people on here could provide some way forward? Thanks.

Leo
  • 500
  • 5
  • 15

1 Answers1

1

There is some good documentation on porting Newlib here, including implementation of the C Runtime initialisation. The CRT tasks include:

  • Set up the target platform in a consistent state. For example setting up appropriate exception vectors.
  • Initialize the stack and frame pointers
  • Invoke the static data initialization including C++ constructors for static objects.
  • Carry out any further platform specific initialization.
  • Call the C main function.
  • Call C++ static object destructors on exit from main().
  • Exit with the return code supplied on exit from main().

It is not clear how you have determined than printf() is not returning, but there are a number of possibilities such as insufficient stack, or in fact it does return but when the printf() call returns main() will exit and what happens then is up to your C runtime - presumably it will loop indefinitely? If exit from main() disables interrupts and your printf() output is buffered and interrupt driven, you might not see any output. Another possibility is that as the last statement in main() the printf() call return may be optimised by "merging" it with the main() return. I suggest you at least place a for(;;); at the end of main() to block it from returning.

printf() itself is somewhat heavyweight as a starting point for test; it required significant stack space and working support for stdout and syscalls. I'd perhaps start with something lower level and simpler with fewer or no dependencies on the library such as toggling a GPIO or unbuffered serial output.

Clifford
  • 88,407
  • 13
  • 85
  • 165