EmbDev.net

Forum: ARM programming with GCC/GNU tools Yagarto C++ Example


von Brendon H. (brenhale)


Rate this post
useful
not useful
Hello,

I am intending on using the yagarto tools for developing a product using
the SAM7X256 in c++, and despite all my searching have not found any
working example code to get started with.
There is of course plenty of c examples, and there are some c++ examples
with other toolchains, but nothing that will work out of the box. As I'm
sure you'll appreciate, getting something up and running before needing
to start fidlding is a good place to start a project!

Does anyone aware of any examples?

Thanks,
Bren

von Giovanni D. (gdisirio)


Rate this post
useful
not useful
Hello, I made a C++ demo using YAGARTO, it works on the LPC2148 but it
should be easy to port it to the SAM7X.

http://chibios.sourceforge.net

regards,
Giovanni

von Clifford S. (clifford)


Rate this post
useful
not useful
What specific problems are you having? There is nothing special about
C++, it is not GCC distribution specific, nor hardware specific so any
valid C++ code will work.

The only difference between supporting C and C++ is that the startup
code (usually in crt0.S) must invoke the constructors for any statically
allocated objects before calling main(). You may find your crt already
does that. In which case you are good to go.

C++ support is no different for Yagarto than it is for any other GCC
distribution, neither is it target specific, so you should be able to
adapt your existing C startup for C++ support.

According to
http://www.embedded.com/columns/technicalinsights/200900043, a function
is provided by the compiler's support library, so you only need this
ahead of invoking main():

    /* Invoke the static constructors */
    LDR     r12,=__libc_init_array
    MOV     lr,pc           /* set the return address */
    BX      r12             /* the target code can be ARM or THUMB */

However in my project we have implemented this code directly. I do not
have access to that here, but can get it if the above does not work for
you.

Also if you are invoking the compiler through gcc rather than g++ you
will have to explicitly link libstdc++ if you are using the C++ library.
For g++ it is a default library (which is the only difference between
gcc and g++). You may want to avoid the C++ standard library in any
case; it has a large initial code-size overhead.

Incidentally the article I linked above is based on an Atmel
AT91SAM7S-EK evaluation board using an AT91SAM7S64, so it is all
directly relevant to your target (except you have more RAM and Flash,
requiring only a linker script change). Links to all ten instalments of
the full article are at:
http://en.mikrocontroller.net/topic/113459#547315 or as a PDF at
http://www.state-machine.com/arm/Building_bare-metal_ARM_with_GNU.pdf.
The PDF hopefully fixes some of the errors in the article where some of
the listings are mixed up.

Clifford

von Clifford S. (clifford)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> The only difference between supporting C and C++ is that the startup
> code (usually in crt0.S) must invoke the constructors for any statically
> allocated objects before calling main(). You may find your crt already
> does that. In which case you are good to go.

Actually to support the static constructor calls you also need some
support in the linker script. Read the article I referenced, it tells
you all you need to know, as well as what compiler options to use to
remove the overhead of RTTI and exception handling for example.

von Clifford S. (clifford)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> However in my project we have implemented this code directly. I do not
> have access to that here, but can get it if the above does not work for
> you.

It turns out that I got my solution from Martin Thomas (I left the
credit in the comment):

/*
   Call C++ constructors (for objects in "global scope")
   ctor loop added by Martin Thomas 4/2005
   based on a Anglia Design example-application for ST ARM
*/
  LDR  r0, =__ctors_start__
  LDR  r1, =__ctors_end__
ctor_loop:
  CMP  r0, r1
  BEQ  ctor_end
  LDR  r2, [r0], #4
  STMFD  sp!, {r0-r1}
  MOV  lr, pc
  MOV  pc, r2
  LDMFD  sp!, {r0-r1}
  B   ctor_loop
ctor_end:


This uses the associated linker scropt fragment:

/* .ctors .dtors are used for c++ constructors/destructors */
/* added by Martin Thomas 4/2005 based on Anglia Design example */
.ctors :
{
 PROVIDE(_ctors_start_ = .);
 KEEP(*(SORT(.ctors.*)))
 KEEP(*(.ctors))
 PROVIDE(_ctors_end_ = .);
}

.dtors :
{
 PROVIDE(_dtors_start_ = .);
 KEEP(*(SORT(.dtors.*)))
 KEEP(*(.dtors))
 PROVIDE(_dtors_end_ = .);
}

   . = ALIGN(4);
/* mthomas - end */

Now I used that code directly on a Samsung S3C2410X ARM9, with WinARM,
but I can assure you that the target nor the flavor of GNU toolchain you
are using are particularly relevant - that is to say you don't need a
Yagarto specific example.

It is not clear exactly what you are having a problem with, it is
possible that all the answers so far have been a waste of time because
you have not been specific about what problem you have. The simplest
possible comples C++ program looks like this:

int main()
{
}

Note that it is also valid C code. So first of all can you compile and
link that as C++? If you put it in a file with a .cpp extension C++
compilation will be automatic, although it may make things simpler later
if you use arm-elf-g++ rather than arm-elf-gcc. Other than that, if you
have C compilation working, then C++ compilation should be
straightforward.

Then I suggest that you test the the runtime environment is valid:

class test
{
    public :
       test() { strcpy( teststr, "hello, world" ) } ;
       char teststr[32] ;
}

static test AnObject ;

int main()
{
    printf( "%s\n", AnObject.teststr ) ;
}

This demonstrates that the constructoir for AnObject was correctly
called. Note I used the C stdio library rather than C++ iostream,
because I am assuming that you already have that working in C code, if
not use some other output mechanism, something you already have working
in C.

If all that works, you will not have too many problems. Be cautious
however of stack and heap allocation. Some parts of the standard library
in both C and C++, specifically stdio and iostream require a fairly
significant amount of stack, the C++ library uses the heap extensively
too, if you have not got malloc/free working in C (by implementing the
sbrk syscall), then you will not have much luck with the string or STL
libraries, and the new/delete operators will not work, but these may be
just too heavyweight in any case. I generally stick to the C library in
embedded C++ code.

Clifford

von Clifford S. (clifford)


Rate this post
useful
not useful
> class test
> {
>     public :
>        test() { strcpy( teststr, "hello, world" ) } ;
>        char teststr[32] ;
> }
>
> static test AnObject ;
>
> int main()
> {
>     printf( "%s\n", AnObject.teststr ) ;
> }
>

Should have added:

#include <cstdio>


and for complete portability

using std::printf ;

Although the latter is not necessary on any compiler I have used since
the C library is generally copied to the std:: namespace not moved, so
it exists in both :: and std::

Clifford

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.