Skip to main content
wbarkley
Associate III
August 8, 2012
Question

C++ dev questions

  • August 8, 2012
  • 7 replies
  • 1281 views
Posted on August 08, 2012 at 18:30

I have some PLC .cpp source/header files that I want to port over to my micro code that uses linked lists and what not.  I noticed that main is a c file as is the rest of the stm320xx std periph drivers. 

Can I use c++ src/inc files and call those functions from main.c?

Do I have to make main.c into main.cpp?

Is this just asking for trouble and i should implement an array/struct solution instead of using linked lists?

    This topic has been closed for replies.

    7 replies

    Tesla DeLorean
    Guru
    August 8, 2012
    Posted on August 08, 2012 at 18:45

    I'm not a C++ guy, although I can follow along well enough to understand whats happening.

    You should be able to mix-n-match, just watch for the name mangling that C++ does, and the calling conventions.

    I would definitely leave the library and main in C if I could.

    One of the other things to watch is that C++ wants to allocate memory at run time, which gets a lot more complicated in systems with finite resources, and embedded.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Andrew Neil
    Super User
    August 9, 2012
    Posted on August 10, 2012 at 01:20

    Note that linked lists don't have to be dynamically allocated...

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    andyturk
    Associate II
    August 11, 2012
    Posted on August 11, 2012 at 10:42

    Use the

    extern ''C''

    construct to selectively turn off the C++ name mangling. You use this in your C++ code to create hooks that straight C code can call. If C++ is to call C code, then the declaration that C++ sees should include extern ''C''.

    That takes care of most of the issues. You'll probably want to turn off exceptions and RTTI too, but that's more of a command line switch than anything you do in the source code. Lastly, C++ compilers spit out static initialization code that your linker script and startup code will need to know about.

    It takes a little bit of effort to get things going the first time, but it's very easy after that, and letting the compiler generate your static initialization code is much nicer than doing it by hand.

    And linked lists are especially tasty in C++ ...

    http://getoffmylawnentertainment.com/blog/2011/05/18/the-curiously-recurring-template-pattern/

    timotet
    Associate II
    August 18, 2012
    Posted on August 18, 2012 at 22:32

    @turk.andy

     

    '' Lastly, C++ compilers spit out static initialization code that your linker script and startup code will need to know about.''

    Can you give an example of this? And how to do it.

    much appreciated

    Tim

    Tesla DeLorean
    Guru
    August 19, 2012
    Posted on August 19, 2012 at 05:55

    In GNU/GCC you call __libc_init_array prior to calling main.

    /* Call static constructors */ bl __libc_init_array or something akin to

    /* Call C++ constructors */
    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:

    which calls the individual constructor functions. Now in a PC system you'd also have the complementary destructors, but embedded systems are not designed to exit. Although a bit dated this might provide some background

    http://www.state-machine.com/arm/Building_bare-metal_ARM_with_GNU.pdf

    http://newlib.sourcearchive.com/documentation/1.0/init_8c-source.html

    .text :
    {
    ..
    KEEP(*(.init))
    *(.text .text.*)
    KEEP(*(.fini))
    *(.gcc_except_table)
    } >FLASH
    . = ALIGN(4);
    /* .ctors .dtors are used for c++ constructors/destructors */
    .ctors :
    {
    PROVIDE(__ctors_start__ = .);
    KEEP(*(SORT(.ctors.*)))
    KEEP(*(.ctors))
    PROVIDE(__ctors_end__ = .);
    } >FLASH
    .dtors :
    {
    PROVIDE(__dtors_start__ = .);
    KEEP(*(SORT(.dtors.*)))
    KEEP(*(.dtors))
    PROVIDE(__dtors_end__ = .);
    } >FLASH

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    timotet
    Associate II
    August 20, 2012
    Posted on August 20, 2012 at 06:14

    Thanks for the reply clive1, and the documentation.

     

     

    andyturk
    Associate II
    August 20, 2012
    Posted on August 20, 2012 at 19:59

    Clive1 got it right, as usual. You don't *need* assembly though. Here's a simple reset handler in C++ that does the same thing: http://pastebin.com/wvcZUzPL