turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Which toolchain?

Fri Mar 27, 2015 6:04 pm

I read somewhere that the official tool chain is:
https://github.com/raspberrypi/tools
but is it just raspbian-official?
I have it installed on my slackware-laptop already for cross-compiling.

What's the "standard" tool chain amongst the bare metal people?
Or is the official tool chain as good as any?

[edit]
Could have been a bit more specific about the official tool chain:
gcc-linaro-arm-linux-gnueabihf-raspbian
De-bugging is for sissies - real men do de-monstrations.

User avatar
DougieLawson
Posts: 36578
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: Which toolchain?

Fri Mar 27, 2015 7:34 pm

Anything on https://github/raspberrypi belongs to the RPF so probably counts as "official".
Note: Having anything humorous in your signature is completely banned on this forum. Wear a tin-foil hat and you'll get a ban.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Fri Mar 27, 2015 7:50 pm

But what's the "standard" tool chain amongst the bare metal people?
Or is the official tool chain as good as any?

BTW, does the official toolchain ld support different load/execute addresses?
I kinda grew to like them in certain situations, when I worked with TI C6000 series device.

[edit]
Ah, 'find' is nice thing with documents:
Searching for 'load address' in http://193.87.95.148/openwrt/rpi_cross/ ... pdf/ld.pdf
found VMA, LMA and AT-command.
Looks like different load/execute addresses are supported.
De-bugging is for sissies - real men do de-monstrations.

JacobL
Posts: 76
Joined: Sun Apr 15, 2012 2:23 pm

Re: Which toolchain?

Fri Mar 27, 2015 9:02 pm

Not sure if it is very standard, but I use crosstool-ng http://crosstool-ng.org/ to compile the toolchain for my PC targeted specifically to the RPI CPU

These are instructions for creating a compiler for Linux kernels, baremetal work is very similar: http://www.bootc.net/archives/2012/05/2 ... pberry-pi/

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Sat Mar 28, 2015 10:54 am

So this:

Code: Select all

bash-4.2$ arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11) 4.8.3 20140106 (prerelease)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
is as good as any?
De-bugging is for sissies - real men do de-monstrations.

JacobL
Posts: 76
Joined: Sun Apr 15, 2012 2:23 pm

Re: Which toolchain?

Sat Mar 28, 2015 9:11 pm

Best way to find out would probably be to compile a simple program with the exact -mcpu for your pi. For pi 1, you should run it with -mcpu=arm1176jzf-s - I am not sure of the exact one for pi 2, but someone here probably have it. Otherwise it is normally easy enough to determine from the list in the gcc man page.

If your compiler accepts the option, and the program works, that would be a good start. Sometimes you need to specify the exact supported cpu in the crosstool-ng configuration.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Sat Mar 28, 2015 11:04 pm

The product page says:
A 900MHz quad-core ARM Cortex-A7 CPU
(And that is selected in the eclipse project settings for my first ever RPi 2B program-to-be.)

I just want to be as 'compatible' with the others as I can - and I don't like missing useful features others have.
De-bugging is for sissies - real men do de-monstrations.

JacobL
Posts: 76
Joined: Sun Apr 15, 2012 2:23 pm

Re: Which toolchain?

Sat Mar 28, 2015 11:12 pm

A quick look at "man gcc" shows that there is an option named "-mcpu=cortex-a7". Compiling with this one should give you an exact match to that CPU. Again, you might need to select this CPU name when building your toolchain with crosstool-ng. If you want a toolchain tailored specifically to this CPU in order to "not miss useful features", crosstool-ng is probably the easiest way to go, since you can configure it exactly to your CPU without having to manually piece together the toolchain.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Sat Mar 28, 2015 11:30 pm

Why should I compile a tool chain, if I have a working one?
And more importantly, which toolchain? Gnu? Linaro? Some other?
De-bugging is for sissies - real men do de-monstrations.

mimi123
Posts: 583
Joined: Thu Aug 22, 2013 3:32 pm

Re: Which toolchain?

Sun Mar 29, 2015 9:49 am

turboscrew wrote:Why should I compile a tool chain, if I have a working one?
And more importantly, which toolchain? Gnu? Linaro? Some other?
you can use binutils and clang also

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: Which toolchain?

Sun Mar 29, 2015 10:49 am

Compiling your own toolchain is pretty much a minority interest. You should be able to get by with an off-the-shelf toolchain (the CPUs on the pi models are not exactly bleeding edge) unless you're looking for a specific optimisation that's only available in a specific version of a compiler, testing a specific version of a compiler, or want to do something "interesting" like using the guts of LLVM as a back end for your own language.

Or, of course, if you derive some sort of perverse pleasure from compiling toolchains.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Sun Mar 29, 2015 3:05 pm

Could this be a good reason:

I made an eclipse project of 3 files - copied here:
https://balau82.wordpress.com/2010/02/2 ... sing-qemu/
and edited the c-file:

Code: Select all

/*
 * RPI_test.c
 *
 *  Created on: Mar 27, 2015
 *      Author: jaa
 */

#include <stdint.h>

/* delay() borrowed from OSDev.org */
static inline void delay(int32_t count)
{
	asm volatile("__delay_%=: subs %[count], %[count], #1; bne __delay_%=\n"
		 : : [count]"r"(count) : "cc");
}

void c_entry() {
 delay(10000);
}

**** startup.s ****
.global _Reset
_Reset:
 LDR sp, =stack_top
 BL c_entry
 B .

****  RPi_test.ld ****
ENTRY(_Reset)
SECTIONS
{
 . = 0x10000;
 .startup . : { startup.o(.text) }
 .text : { *(.text) }
 .data : { *(.data) }
 .bss : { *(.bss COMMON) }
 . = ALIGN(8);
 . = . + 0x1000; /* 4kB of stack memory */
 stack_top = .;
}
I selected the official tool chain:
I selected processor: Cortex A7
I added the linker script:
-T "/home/jaa/workspace/test/RPi_test/RPi_test.ld" -nostartfiles -nodefaultlibs -nostdlib -Xlinker --gc-sections -Wl,-Map,"RPi_test.map"

When I 'build project':

Code: Select all

17:59:21 **** Build of configuration Debug for project RPi_test ****
make all 
Building file: ../RPI_test.c
Invoking: Cross ARM C Compiler
arm-linux-gnueabihf-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -std=gnu11 -MMD -MP -MF"RPI_test.d" -MT"RPI_test.o" -c -o "RPI_test.o" "../RPI_test.c"
Finished building: ../RPI_test.c
 
Building file: ../startup.S
Invoking: Cross ARM GNU Assembler
arm-linux-gnueabihf-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -x assembler-with-cpp -MMD -MP -MF"startup.d" -MT"startup.o" -c -o "startup.o" "../startup.S"
Finished building: ../startup.S
 
Building target: RPi_test.elf
Invoking: Cross ARM C Linker
arm-linux-gnueabihf-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -T "/home/jaa/workspace/test/RPi_test/RPi_test.ld" -nostartfiles -nodefaultlibs -nostdlib -Xlinker --gc-sections -Wl,-Map,"RPi_test.map" -o "RPi_test.elf"  ./RPI_test.o ./startup.o   
startup.o: In function `_Reset':
/home/jaa/workspace/test/RPi_test/Debug/../startup.S:3: multiple definition of `_Reset'
./startup.o:/home/jaa/workspace/test/RPi_test/Debug/../startup.S:3: first defined here
collect2: error: ld returned 1 exit status
make: *** [RPi_test.elf] Error 1

17:59:22 Build Finished (took 533ms)
The same thing if I 'make all' manually.

Or maybe someone here knows what the problem is?
Of course the code would not run on RPi, but the point was the compilation - or rather - linking.
Where the heck did the linker invented a second '_Reset' ( multiple definition of `_Reset') ?

Maybe my tool chain is not good for bare metal?
Which tool chain would you recommend for bare metal?

[edit]
Oh, and should I keep this tool chain for (possible) Raspbian programming?
De-bugging is for sissies - real men do de-monstrations.

JacobL
Posts: 76
Joined: Sun Apr 15, 2012 2:23 pm

Re: Which toolchain?

Sun Mar 29, 2015 7:49 pm

turboscrew wrote: Or maybe someone here knows what the problem is
Not sure, but you may need to add "-ffreestanding" to your compiler command line. Alternatively, this might be your problem: "arm-linux-gnueabihf". The toolchain is targeted to Linux, not baremetal, so there might be some implied code that needs to be removed.
Oh, and should I keep this tool chain for (possible) Raspbian programming?
Linux and baremetal normally use different toolchains, but since the toolchain is actually targeted to Linux, you might have better luck with it under Raspbian than for baremetal.

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: Which toolchain?

Sun Mar 29, 2015 8:28 pm

That's almost certainly a linker invocation error, it indicates that somehow startup.o is being linked twice into the finished executable.

My guess would be that your linker script is to blame, that it's pulling the .text section from startup.o, and then *all* text sections. I generally use a separate section for the vector table, viz:

.section .reset, "ax"
.global __reset
...

and then use the .reset section in the linker script.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Sun Mar 29, 2015 9:18 pm

You mean:

Code: Select all

.startup . : { startup.o(.text) }
 .text : { *(.text) }
I recall that the same sections were not taken twice, but then, it's been long time since I used linker scripts with "pure" gcc. The last ones have probably been tampered with by HW manufacturers.
I recall, with TI there were the specific sections first, and at the end of the linker script there were defaults: *.text, *.data, ...

Also the linker script and the startup.s were taken (as a proof for a point) from a web site, so I think for some people it must have worked.

Anyway, tufty, your comment makes sense. I'll try with making the two mentioned sections explicitly separate.

[edit]
At least here: http://www.math.utah.edu/docs/info/ld_3.html#SEC14
it says:
filename
You may simply name a particular input file to be placed in the current output section; all sections from that file are placed in the current section definition. If the file name has already been mentioned in another section definition, with an explicit section name list, then only those sections which have not yet been allocated are used. To specify a list of particular files by name:

.data : { afile.o bfile.o cfile.o }
(Still going to test the theory.)
De-bugging is for sissies - real men do de-monstrations.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Sun Mar 29, 2015 9:45 pm

Even more weird:
changing the linker script to:

Code: Select all

ENTRY(_Reset)
SECTIONS
{
 . = 0x10000;
 .startup . : { startup.o(.text) }
 .text : { RPI_test.o(.text) }
 .data : { *(.data) }
 .bss : { *(.bss COMMON) }
 . = ALIGN(8);
 . = . + 0x1000; /* 4kB of stack memory */
 stack_top = .;
}
resulted to:

Code: Select all

00:50:03 **** Build of configuration Debug for project RPi_test ****
make all 
Building file: ../RPI_test.c
Invoking: Cross ARM C Compiler
arm-linux-gnueabihf-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -std=gnu11 -MMD -MP -MF"RPI_test.d" -MT"RPI_test.o" -c -o "RPI_test.o" "../RPI_test.c"
Finished building: ../RPI_test.c
 
Building file: ../startup.S
Invoking: Cross ARM GNU Assembler
arm-linux-gnueabihf-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -x assembler-with-cpp -MMD -MP -MF"startup.d" -MT"startup.o" -c -o "startup.o" "../startup.S"
Finished building: ../startup.S
 
Building target: RPi_test.elf
Invoking: Cross ARM C Linker
arm-linux-gnueabihf-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -T "/home/jaa/workspace/test/RPi_test/RPi_test.ld" -nostartfiles -nodefaultlibs -nostdlib -Xlinker --gc-sections -Wl,-Map,"RPi_test.map" -o "RPi_test.elf"  ./RPI_test.o ./startup.o   
startup.o: In function `_Reset':
/home/jaa/workspace/test/RPi_test/Debug/../startup.S:3: multiple definition of `_Reset'
./startup.o:/home/jaa/workspace/test/RPi_test/Debug/../startup.S:3: first defined here
RPI_test.o: In function `c_entry':
/home/jaa/workspace/test/RPi_test/Debug/../RPI_test.c:17: multiple definition of `c_entry'
./RPI_test.o:/home/jaa/workspace/test/RPi_test/Debug/../RPI_test.c:17: first defined here
collect2: error: ld returned 1 exit status
make: *** [RPi_test.elf] Error 1

00:50:04 Build Finished (took 935ms)
Now 'c_entry' also becomes multiply defined!
and also with gcc-arm-none-eabi-4_9-2014q4/

Code: Select all

00:41:34 **** Build of configuration Debug for project RPi_test ****
make all 
Building file: ../RPI_test.c
Invoking: Cross ARM C Compiler
arm-none-eabi-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -std=gnu11 -MMD -MP -MF"RPI_test.d" -MT"RPI_test.o" -c -o "RPI_test.o" "../RPI_test.c"
Finished building: ../RPI_test.c
 
Building file: ../startup.S
Invoking: Cross ARM GNU Assembler
arm-none-eabi-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -x assembler-with-cpp -MMD -MP -MF"startup.d" -MT"startup.o" -c -o "startup.o" "../startup.S"
Finished building: ../startup.S
 
Building target: RPi_test.elf
Invoking: Cross ARM C Linker
arm-none-eabi-gcc -mcpu=cortex-a7 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections  -g3 -T "/home/jaa/workspace/test/RPi_test/RPi_test.ld" -nostartfiles -nodefaultlibs -nostdlib -Xlinker --gc-sections -Wl,-Map,"RPi_test.map" -o "RPi_test.elf"  ./RPI_test.o ./startup.o   
startup.o: In function `_Reset':
/home/jaa/workspace/test/RPi_test/Debug/../startup.S:3: multiple definition of `_Reset'
./startup.o:/home/jaa/workspace/test/RPi_test/Debug/../startup.S:3: first defined here
RPI_test.o: In function `c_entry':
/home/jaa/workspace/test/RPi_test/Debug/../RPI_test.c:17: multiple definition of `c_entry'
./RPI_test.o:/home/jaa/workspace/test/RPi_test/Debug/../RPI_test.c:17: first defined here
collect2: error: ld returned 1 exit status
make: *** [RPi_test.elf] Error 1

00:41:36 Build Finished (took 1s.890ms)
Am I haunted or something?
De-bugging is for sissies - real men do de-monstrations.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Mon Mar 30, 2015 1:04 am

I made the linker script this way, and it works - the code links:

Code: Select all

ENTRY(_Reset)
SECTIONS
{
 . = 0x10000;
 /* .startup . : { startup.o(.text) } */
 .text : { *(.text) }
 .data : { *(.data) }
 .bss : { *(.bss COMMON) }
 . = ALIGN(8);
 . = . + 0x1000; /* 4kB of stack memory */
 stack_top = .;
}
If, instead of

Code: Select all

 .text : { *(.text) }
I put

Code: Select all

 
.text : { startup.o(.text)}
.text : { *(.text) }
the linker complains about "multiple definition of `_Reset'".

Code: Select all

 
.text : { startup.o(.text)}
.text : { RPI_test.o(.text) }
causes multiple definitions of both '_Reset' and 'c_entry'.
BUT, this works again (as if it NEEDS an asterisk before dot):

Code: Select all

 .text : { startup*.o(.text) }
 .text : { *.o(.text) }
and this works too:

Code: Select all

 .startup . : { startup*.o(.text) }
 .text : { *.o(.text) }
It seems to work as long as in the file name there's an asterisk before dot.
Not 'file.o' but 'file*.o'. WHAT?
That applies to both toolchains I tried, the official 'arm-linux-gnueabihf' and
'gcc-arm-none-eabi-4_9-2014q4'.

Weird, but I can make it work, so fine. Took all day to figure that out, though.
Oh well, it's 3 AM. Time to go to bed anyway... (SIGH)
De-bugging is for sissies - real men do de-monstrations.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Mon Mar 30, 2015 1:13 am

Couldn't resist, had to try:

Code: Select all

 .startup . : { startup*.o(.text) }
 .text : { startup*.o(.text) }
 .text : { *(.text) }
That works too! No multiple definitions! :shock:
De-bugging is for sissies - real men do de-monstrations.

turboscrew
Posts: 174
Joined: Sat Jan 18, 2014 1:50 pm
Location: Nokia (town), Finland

Re: Which toolchain?

Mon Mar 30, 2015 4:01 pm

I think I also just found a solution to the other problem: the assembly uses the same symbols .
as C. No underscore is added.

This seems to work:

in C-file:
extern char __code_begin;
extern char __text_end;
extern char __new_org;
...
void start1()
{
...
}

in asm-file:
.extern __code_begin
.extern __text_end
.extern start1
...
ldr pc, =start1

in linkerscript:
ENTRY(_start)

SECTIONS
{
. = 0x0000;
.text :
{
start*.o(.vector)
}
/* Starts at LOADER_ADDR. */
. = 0x8000;
__text_start = .;
.text :
{
/* If special boot section */
/* KEEP(*(.text.boot)) */
*(.init)
start1*.o(.text)
__code_begin = .;
*(.text)
}
/* align to page size */
/* . = ALIGN(4096); */
__text_end = .;

__data_start = .;
.data :
{
*(.data)
}
__data_end = .;

__bss_start = .;
.bss :
{
bss = .;
*(.bss)
}
__bss_end = .;

__new_org = 0x1f000000;
__end = .;
}
De-bugging is for sissies - real men do de-monstrations.

tufty
Posts: 1456
Joined: Sun Sep 11, 2011 2:32 pm

Re: Which toolchain?

Mon Mar 30, 2015 4:07 pm

That looks a lot like there are filename globbing issues going on there.

Return to “Bare metal, Assembly language”