EmbDev.net

Forum: ARM programming with GCC/GNU tools compilation using arm-elf-tools


von Armand I. (iostrym)


Rate this post
useful
not useful
Hi everyone,

I have installed arm-elf-tools by typing
sh arm-elf-tools-20030314.sh

then I would like to compile a boot.S file for arm7tdmi.

So I type :

arm-elf-as -marm7tdmi boot.S

And I obtain no error, no message in the console but a file called a.out
that contain only one thing :

ELF     a

What is the problem ? did I made something wrong ?

Thanks for your help

Regards,

von Fordp (Guest)


Rate this post
useful
not useful
I am no guru, but the following points may help you.

1) I am guessing you are not using WinARM. This is a WinARM forum, as
you are using GNU tools a lot will be the same as WinARM. You may want
to post on the GNU ARM yahoo group instead.

2) I would not suggest you start with nothing, it will take a long time
to get where you want to be. Why not download some demo application for
your chip. You do no mention what chaip that is????

3) I suggest you download Jim Lynch's tutorial. It is based around
Windows and Eclispe I know but a lot is still relevant to any GCC ARM
development.

4) In your command line you did not specify an output file name GNU
tools tend to default to outputting a if you do not specify. It seems to
have output a.elf which is file which can contain both your machine code
and debugging sysmbols to go with it.

5) The level of questions you are asking would lead me to think that the
chances of a.elf doing anything useful is pretty close to zero. Read my
comments above give yourself a better chance of getting something
working. I may be wrong on this and do not take it personally.

Good Luck.
FordP

armand iostrym wrote:
> Hi everyone,
>
> I have installed arm-elf-tools by typing
> sh arm-elf-tools-20030314.sh
>
> then I would like to compile a boot.S file for arm7tdmi.
>
> So I type :
>
> arm-elf-as -marm7tdmi boot.S
>
> And I obtain no error, no message in the console but a file called a.out
> that contain only one thing :
>
> ELF     a
>
> What is the problem ? did I made something wrong ?
>
> Thanks for your help
>
> Regards,

von Armand I. (iostrym)


Rate this post
useful
not useful
thanks for your help,

the title of the forum is WinARM / ARM-GCC. isn't it also a gcc forum ?
My processor is an ARM7TDMI and the chip is an ACTEL FPGA called M7
ProASIC3 in which you can implement an ARM7TDMI. the file I would like
to compile is not very complex. It is a very simple boot sequence with
some LDR and ADR...
the strange things is that the a.out seems to be empty (ELF     a)
unless I don't have the right software to read it ?

However I will look at the tutorial you indicate previously.

von Stefan (Guest)


Rate this post
useful
not useful
Why don't you use gcc (or better a makefile) to call the assembler?

The *.S extension is for assembler files which should be parsed by the
preprocessor (see 'Assembler code which must be preprocessed'
http://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Options).

I don't know whether the assembler calls the preprocessor itself, but i
don't think so. Normally this is the job of gcc

arm-elf-gcc -mcpu=arm7tdmi -c boot.S -o boot.obj

should work.

Stefan

von Armand I. (iostrym)


Rate this post
useful
not useful
I don't understand the difference between *.s and *.S :

file.s
    Assembler code.
file.S
    Assembler code which must be preprocessed.

the preprocessor action is for *.c file, to remplace #define by the real
value for exemple. As an assembler file hasn't any #define or include,
why is there a need to preprocessor an assembler file ?

Stefan wrote:
> Why don't you use gcc (or better a makefile) to call the assembler?
>
> The *.S extension is for assembler files which should be parsed by the
> preprocessor (see 'Assembler code which must be preprocessed'
> http://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Options).
>
> I don't know whether the assembler calls the preprocessor itself, but i
> don't think so. Normally this is the job of gcc
>
> arm-elf-gcc -mcpu=arm7tdmi -c boot.S -o boot.obj
>
> should work.
>
> Stefan

von Martin Thomas (Guest)


Rate this post
useful
not useful
> the title of the forum is WinARM / ARM-GCC. isn't it also a gcc forum ?

Yes it is. WinARM is just a collection and the arm-elf gnu-toolchain is
the main part of the collection so this forum has to be some kind of
"arm gcc forum" too. It has been the intention to be not only a WinARM
forum (see my "Welcome" message).

> I don't understand the difference between *.s and *.S :
>
> file.s
>     Assembler code.
> file.S
>     Assembler code which must be preprocessed.
>
> the preprocessor action is for *.c file, to remplace #define by the real
> value for exemple. As an assembler file hasn't any #define or include,
> why is there a need to preprocessor an assembler file ?

It is very convinient. The preprocessor offers a lot of functions which
are not available or less functional than the build-in functions of the
assembler. You can use all options you know from your c-coding in your
assembler-sources too (and do not need to learn about all
assembler-"."-functions). The preprocessor is basicly an "automatic
text-replacer" and does not care if it works on a text which is
c-source-code or assembler-source-code.

Martin Thomas

von Armand I. (iostrym)


Rate this post
useful
not useful
Thanks you all for your help.

So to conclude, a *.s file containing C and asm should be
pre-processored with gcc and a *.S file with only assembler code should
be assembled with as ?

gcc --> pre-processor and compilation
as --> assembling.

but sometimes gcc can also do all the compilation flow including as?

And finally another question, to be sure, extension .s, .S, .cpp etc.
are only used to indicate to the user what sort of file is it but the
extension is not important for gcc ?

Great thanks to everyone, Regards,

von Stefan (Guest)


Rate this post
useful
not useful
*.s = only assembler code
as only is possible, but gcc invoking as is better

*.S = assembler code and preprocessor (cpp) macros
gcc invoking cpp and later as is better

gcc is the caller for preprocessor and/or compiler and/or assembler
and/or linker. You can call the whole toolchain or parts of it with gcc.
And make is the caller of gcc...

And the extension is very important. gcc decides whether to call cpp
(*.c, *.S) or not (*.s) with the extension!

Regards
Stefan

von Armand I. (iostrym)


Rate this post
useful
not useful
Thanks,

So it seems that arm-elf-gcc -mcpu=arm7tdmi -S boot.S would be ok to
make the pre-processoring and the compilation of my assembling file. I
thought I would get as a result a .s file but this command doesn't
create anything. I have no error but also no output file.

I try also arm-elf-gcc -mcpu=arm7tdmi -E boot.S and I see that the
preprocessing is ok because it remplace that #define by their value. but
the output is print on the console.

So maybe I have to make something like : toto.s << arm-elf-gcc
-mcpu=arm7tdmi -E boot.S

but it's weird because I thought that with arm-elf-gcc -mcpu=arm7tdmi -S
boot.S I could get the final *.s file.

von Stefan (Guest)


Rate this post
useful
not useful
-S : Stop after compilation and generate the assembly code. This code
will be saved in a file with the extension ".s". A extract of the
assembler code is given below. Input files that don't require
compilation are ignored.

=> You don't have a source file to compilate, because you havn't a c
source file but a assembler source file. gcc doesn't make anything.

-E : Do only preprocessing, no compiling or assembling. Output results
to standard output file a.out.

-o file : Place output in file file. This applies regardless to whatever
sort of output is being produced, whether it be an executable file, an
object file, an assembler file or preprocessed C code.

If -o is not specified, the default is to put an executable file in
a.out, the object file for source.suffix in source.o, its assembler file
in source.s, a precompiled header file in source.suffix.gch, and all
preprocessed C source on standard output.

OK. I would try

arm-elf-gcc -mcpu=arm7tdmi -E boot.S -o boot.s

von Armand I. (iostrym)


Rate this post
useful
not useful
arm-elf-gcc -mcpu=arm7tdmi -E boot.S -o boot.s work
and
arm-elf-gcc -mcpu=arm7tdmi -E boot.S > boot.s work also.

thanks for your help;

Everything is okay, I unerstand quite perfectly the gcc flow thanks to
all of you.

Nevertheless, I have a new problem with the linker. If I want to run a
complete gcc flow to compile boot.S, I have the following error :

/tmp/cc4Zc7LE.o: In function `_start':
/tmp/cc4Zc7LE.o(.text+0x0): multiple definition of `_start'
/usr/local/arm-elf/lib/crt0.o(.text+0x0): first defined here
/usr/local/arm-elf/lib/libc.a(__uClibc_main.o): In function
`__uClibc_start_main':
__uClibc_main.o(.text+0xf4): undefined reference to `main'
collect2: ld returned 1 exit status

nm boot.o :
00000020 t Remap_address
0000001c t Remap_command
00000000 T _start

and
nm crt0.o:
         U abort
         U main
00000000 T _start
         U __uClibc_main

I made a some research and I have found that crt0.o is an "execution
startup routine". the two are using _start and it seems to be
incompatible. However I don't call crt0.o somewhere so I don't
understand why there is a problem with this object file. Moreover,
crt0.o need to define main that obviously I don't define... What is the
purpose of this object file and do you know why it seems to be linked
with my boot.s ?

Best regards and thanks a lot for everything

von Stefan (Guest)


Rate this post
useful
not useful
You don't have a problem with the linker, but with your project. Did you
mix startup code from different projects? When you wrote boot.S, how
could you be sure that other source files in your project didn't use the
global symbol _start already?

Often the startup code is organized in several source files, which are
assembler files for the initial and low-level work and later some c
source files for the higher-level work. Typical tasks in crt0.c or
crt0.s are

* copy DATA from ROM to RAM
* zero BSS
* open file descriptors (optional)
* call main (optional with arguments)
* handle an abort or an exit or a return from main

You can extent crt0.c to perform other tasks too i.e. REMAP and
exception vectors, but other people prefer to do this in another source
file and call this file boot.S, startup.S or vectors.S....

> __uClibc_main.o(.text+0xf4): undefined reference to `main'

You need at least an application function main() in your project. This
function is called after initialization. But this is basic C.

von Armand I. (iostrym)


Rate this post
useful
not useful
Hi, great thanks for your help !

It's strange because my project in fact is one file : boot.S :

#define I_BIT   (1 << 7)
#define F_BIT   (1 << 6)
#define ARM_MODE_SVC 0x13 // SVC -> supervisor mode.

  .global  _start // make symbol visible to the linker

_start:
  mov   r0, #(ARM_MODE_SVC | I_BIT | F_BIT )    /* disable interrupts. 
r1
= 11010011*/
  msr   cpsr, r0

  /* Load the address where to jump */
  ldr  r12, uClinux_kernel_decompression_address  /* get the real jump
address ( after remap ) */

  adr r0, Remap_command
  adr r1, Remap_address
    str r0, [r1]        /* REMAP command */

  mov  pc, r12      /* jump to the uClinux_kernel_decompression address 
and
break the pipeline */

Remap_command:
  .long  0x00000001    /* REMAP command */

Remap_address:
    .long  0x20000000  /* REMAP address */

It's a bootloader that perform a remap, the disable of interruptions and
then jump to the adress a another program that will be compiled
indepenantly of this file.
I would like to program the ROM with the bootloader at the adress
0x00000000 and separatly made another program (anything) that I will
just have to program at the precedent jump adress.
In my case it will be the decompression of the kernel in the ram to
prepare its execution. (quite ambitious, but I will try :-) )
Do you think my approach is good ? or maybe I have to compile the
bootloader and the called program in one project ?
But today, this project is composed by one file, boot.S and there should
be no call to crt0.s. I still don't understand why this file is include
"by default" in my project...
Maybe it due to my cross compilation tools chain that may be specific to
uClinux... If I understand what you said, the real boot of my project is
crt0.s whereas I havn't specified it anywhere ?

Regards,

von Stefan (Guest)


Rate this post
useful
not useful
When you

> If I want to run a complete gcc flow to compile boot.S,

then there might be command lines and/or options in your makefile and/or
gcc environment options which include the libraries and the
c-runtime-library-startup-code aka crt0 for a complete project named
uClinux. But you can switch on verbose mode for gcc and get all command
lines and so on for the project in order to check this.

The algorithm of your boot.S and the relevance for a emulated ARM7
system in a FPGA chip (right?) is too complicated for me. I don't
understand your new symbol uClinux_kernel_decompression_address and its
relevance to the Remap_address esp. with =Remap_address = 0x20000000.

It is hard enough to start a simple application program (main) on a chip
from scratch, but you try even something harder - you try to start a OS
(uClinux) which will start automatically an application user program
(main)... this is way above my experience level now.

I would look in the porting section of the OS whether somebody has
already written a port (startup code including crt0...) for my target
(processor type and layout of the board = type/addresses of RAM/ROM...)
or i would modify an existing port. But writing a startup code from
scratch, uff ;-)

von Stefan (Guest)


Rate this post
useful
not useful
armand iostrym wrote:
> I would like to program the ROM with the bootloader at the adress
> 0x00000000 and separatly made another program (anything) that I will
> just have to program at the precedent jump adress.
> In my case it will be the decompression of the kernel in the ram to
> prepare its execution. (quite ambitious, but I will try :-) )
> Do you think my approach is good ? or maybe I have to compile the
> bootloader and the called program in one project ?

Both methods are possible and used within the programming community.

von Armand I. (iostrym)


Rate this post
useful
not useful
The step by step flow is working:

Pre-processor:
arm-elf-gcc -mcpu=arm7tdmi -E boot.S -o boot.s

assembly :
arm-elf-as -arm7tdmi boot.s -o boot.o

link :
arm-elf-ld boot.o

And I get a.out that is the final object file.

But if I do directly the complete flow with

Arm-elf-gcc -mcpu=arm7tdmi boot.S

I have the precedent error.

Right, it's an ARM7TDMI included in ACTEL FPGA. Have you ever heard of
it? uuu, how do you guess that it was included in a FPGA? you are very
strong :-)

The boot.S isn't complex, the "uClinux_kernel_decompression_address"
will be the adress to jump after the remap and it will perform the
decompression of the kernel. It's already done, I use a uClinux
distribution for ATMEL AT91. It's not completely clear for me but at
least I don't do things from scratch :-) All the work is done for
uClinux (not entirely :-/ ), there is already a startup code for the
kernel ... but as these distribution are made for people who use a
eveluation board with integrated bootloader I have to do mine.

Remap_address and Remap_command are the adresses where to write the
Remap_command in order to perform the Remap.
Maybe there is a better way to write it but the remap is only done by
writing a data in a specific register of the memory controller.

I agree with you, it's hard to start with an OS but that's why I train
myself with this small bootloader.

As I said in a post in another topic, I would like to compile separately
the boot.S and the uClinux distribution. There is already a makefile for
the uClinux distribution. I have a lot of thing to do to adapt the
uClinux distrib' for my architecture. At the end of the process I would
like to get one executable file for the bootloader to put at adresse
0x00000000 and one binary file for the uClinux. That's why I would like
to compile the boot.S separately and absolutely not include crt0.o...

Okay, I understand now... I use the verbose mode and I see that :

assembler:
/usr/local/arm-elf/bin/as -marm7tdmi -o /tmp/cc0973Dx.o /tmp/cc9NAHkj.s
linker:
 /usr/local/lib/gcc-lib/arm-elf/2.95.3/collect2 -X
/usr/local/arm-elf/lib/crt0.o -L/usr/local/lib/gcc-lib/arm-elf/2.95.3
-L/usr/local/arm-elf/lib /tmp/cc0973Dx.o -lgcc -lc -lgcc

So in the complete gcc flow, there is an inclusion of the crt0.o in my
project due to the fact it's a tool chain made for uClinux. And that why
my step by step approach is working. Thanks to you !

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.