EmbDev.net

Forum: ARM programming with GCC/GNU tools Calling C functions inside a C++ Class ?


von Flying A. (flying)


Rate this post
useful
not useful
Hi

I am trying to write a small program in c++ for SAM7-EX256 Olimex Board.

I want the program to perform the following task:

By pressing one button sw1 backlight lcd should be on.
by pressing the other button sw2 backlight lcd should be off.

My sample code is as follows:

//*--------------------------------------------------------------------- 
-------
//* AT91SAM7X example application "C++"
//*
//*--------------------------------------------------------------------- 
-------

#include <stdint.h>
#include <stdio.h>

#define GLOBALOBJECT
//********************* includes
#include "AT91SAM7X256.h"
#include "board_ex256.h"
#include "registers.h"
#include "lcd.h"
#include "bits.h"


AT91PS_PIO    m_pPIOA  = AT91C_BASE_PIOA;
AT91PS_PIO    m_pPIOB  = AT91C_BASE_PIOB;


#define LCD_RESET_LOW     m_pPIOA->PIO_CODR   = BIT2
#define LCD_RESET_HIGH    m_pPIOA->PIO_SODR   = BIT2



//********************* external functions
extern  void LowLevelInit(void);
extern  void InitPeriphery(void);

class Display {
public:
  Display();
  virtual ~Display();

  void on();
  void off();
};

Display::Display()
{
}

Display::~Display()
{
}

void Display::on()
{

Backlight(BKLGHT_LCD_ON);

}

void Display::off()
{

Backlight(BKLGHT_LCD_OFF);

}

void init(void) {


//*************** lowlevel init (watchdog, PLL clock, default
interrupts, etc.)
  LowLevelInit();
  InitPeriphery();
//****************** init lcd
  InitLCD();
  LCDSettings();

} //init

#ifdef GLOBALOBJECT
// #warning "using 'global' LedHandler-Object"
Display ds;
#endif

//Display ds;

int main(void)
{
//Display ds;
#ifndef GLOBALOBJECT
// #warning "using 'local' LedHandler-Object"
Display ds;
#endif

init();

while(1) {

    // check button SW1
    if(!((m_pPIOB->PIO_PDSR) & BIT24)) {
        ds.on();
    }

    // check button SW2
    if(!((m_pPIOB->PIO_PDSR) & BIT25)) {
        ds.off();
    }

  }

}

Now i want to clarify whether i can call a function like Backlight
declared in other file lcd.c in my class as shown in the code above. I
have checked some sample c++ programs from winarm projects page and the
functions declared in c file are called in a class.

I am getting the following errors when i compile the above code using
Yagarto Eclipse IDE:

undefined reference to `Backlight(unsigned char)'  C++_test  main.cpp
line 51  1177945831239  1791
undefined reference to `Backlight(unsigned char)'  C++_test  main.cpp
line 58  1177945831239  1790
undefined reference to `InitLCD()'  C++_test  main.cpp  line 69
1177945831239  1788
undefined reference to `InitPeriphery()'  C++_test  main.cpp  line 67
1177945831239  1787
undefined reference to `LCDSettings()'  C++_test  main.cpp  line 70
1177945831239  1789
undefined reference to `LowLevelInit()'  C++_test  main.cpp  line 66
1177945831239  1786

If anyone of you are doing programming in c++ with arm microcontroller
and have any suggestions on my code please reply me.

Have a nice evening ahead.

Regards
Rajitha

von A.K. (Guest)


Rate this post
useful
not useful
You should tell the compiler that they are C functions:

extern "C" {
  void LowLevelInit(void);
  void InitPeriphery(void);
}

von A.K. (Guest)


Rate this post
useful
not useful
The usually way is to either place those extern "C" braces around the
include statements (typically used für other people's code) or to make
the include files themselves safe für use by C++ by placing

  #ifdef __cplusplus
     extern "C" {
  #endif

on top, and

  #ifdef __cplusplus
     }
  #endif

on bottom of the include file.

von Clifford S. (clifford)


Rate this post
useful
not useful
What A.K. said. some further information:

The extern "C" declaration forces C linkage in C++ code. C linkage
disables name-mangling and C++ specific features such as function
overloading, reference parameters, namespace or class membership, bool
type, class type parameters etc.

While C linkage is commonly used to call C code from C++, it also allows
C++ code to be called from C. A C++ function with C linkage only needs
to have a C compatible interface, the code within it may use C++
constructs and libraries. So for example you can write C wrappers for
C++ code and libraries if you wish.

Here are some detailed explanations and related gotcha's:
http://david.tribble.com/text/cdiffs.htm#C99-mangling
http://www.ddj.com/dept/cpp/184402045
http://docs.hp.com/en/2159/otherlangs.htm

von Flying A. (flying)


Rate this post
useful
not useful
A.K. wrote:
> The usually way is to either place those extern "C" braces around the
> include statements (typically used für other people's code) or to make
> the include files themselves safe für use by C++ by placing
>
>   #ifdef __cplusplus
>      extern "C" {
>   #endif
>
> on top, and
>
>   #ifdef __cplusplus
>      }
>   #endif
>
> on bottom of the include file.

Hi Thank you for the information.

Now i changed my code to something like this:

//*--------------------------------------------------------------------- 
-------
//* AT91SAM7X example application "C++"
//*
//*--------------------------------------------------------------------- 
-------

#include <stdint.h>
#include <stdio.h>


//********************* includes
#ifdef __cplusplus
     extern "C" {
#endif

#include "AT91SAM7X256.h"
#include "board_ex256.h"
#include "registers.h"
#include "lcd.h"
#include "bits.h"

#ifdef __cplusplus
     }
#endif


AT91PS_PIO    m_pPIOA  = AT91C_BASE_PIOA;
AT91PS_PIO    m_pPIOB  = AT91C_BASE_PIOB;


#define LCD_RESET_LOW     m_pPIOA->PIO_CODR   = BIT2
#define LCD_RESET_HIGH    m_pPIOA->PIO_SODR   = BIT2



//********************* external functions
extern "C" {
  void LowLevelInit(void);
  void InitPeriphery(void);

}

class Display {
public:
  Display();
  void Backlight(unsigned char state);
};

Display::Display()
{
}

void Display::Backlight(unsigned char state) {

  if(state == BKLGHT_LCD_ON)
    pPIOB->PIO_SODR   = BIT20;    // Set PB20 to HIGH
  else
    pPIOB->PIO_CODR   = BIT20;    // Set PB20 to LOW

}

void init(void) {


//*************** lowlevel init (watchdog, PLL clock, default
interrupts, etc.)

  void LowLevelInit(void);
  void InitPeriphery(void);
  void InitLCD();
  void LCDSettings();

} //init

int main(void)
{

init();
Display ds;
while(1) {

    // check button SW1
    if(!((m_pPIOB->PIO_PDSR) & BIT24)) {
        ds.Backlight(BKLGHT_LCD_ON) ;
    }

    // check button SW2
    if(!((m_pPIOB->PIO_PDSR) & BIT25)) {
        ds.Backlight(BKLGHT_LCD_OFF);
    }

  }

}

When i compile i am not getting any compile errors.

But when i flash the board it says flashing finished in 0s 203128us and
nothing happens.

I dont understand where is the problem ?

Is my way of calling the functions and initializing objects correct ?

Regards
Flying

von Flying A. (flying)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> What A.K. said. some further information:
>
> The extern "C" declaration forces C linkage in C++ code. C linkage
> disables name-mangling and C++ specific features such as function
> overloading, reference parameters, namespace or class membership, bool
> type, class type parameters etc.
>
> While C linkage is commonly used to call C code from C++, it also allows
> C++ code to be called from C. A C++ function with C linkage only needs
> to have a C compatible interface, the code within it may use C++
> constructs and libraries. So for example you can write C wrappers for
> C++ code and libraries if you wish.
>
> Here are some detailed explanations and related gotcha's:
> http://david.tribble.com/text/cdiffs.htm#C99-mangling
> http://www.ddj.com/dept/cpp/184402045
> http://docs.hp.com/en/2159/otherlangs.htm

Hi thank you for the links.

I will go thru them maybe i will find some more information.

Regards
Flying

von Jonathan D. (dumarjo)


Rate this post
useful
not useful
> Hi thank you for the links.
>
> I will go thru them maybe i will find some more information.
>
> Regards
> Flying

Do you have a main.bin file very small ? this file should look at least
the same size of you C only code.

Jonathan

von Flying A. (flying)


Rate this post
useful
not useful
Jonathan Dumaresq wrote:
>> Hi thank you for the links.
>>
>> I will go thru them maybe i will find some more information.
>>
>> Regards
>> Flying
>
> Do you have a main.bin file very small ? this file should look at least
> the same size of you C only code.
>
> Jonathan

Hi

I have a main.bin file it has half the size of c main.bin.

Now debugging is working but i can't understand the assembly language
instructions its showing when i set the break points.

Can you please tell me how i can check where my program is going wrong
using debugger.

I can step in and step out thru the instructions but i dont understand
the instructions it shows in the disassembly view.

Regards
Flying

von Flying A. (flying)


Rate this post
useful
not useful
Jonathan Dumaresq wrote:
>> Hi thank you for the links.
>>
>> I will go thru them maybe i will find some more information.
>>
>> Regards
>> Flying
>
> Do you have a main.bin file very small ? this file should look at least
> the same size of you C only code.
>
> Jonathan

Hi

Maybe i have a linking problem with my program.

I have one more question which linker file usually we should use RAM.ld
or ROM.ld.

Because for c++ programs i always see both .ld files.

If we use ROM.ld then we should select RUN_MODE=ROM_RUN and
VECTOR_LOCATION=VECTORS_IN_RAM in makefile is it correct?

But when i see my ROM.ld file there is a command like __FIRST_IN_RAM =
ORIGIN(DATA); is it ROM or RAM?

where we can get more description about these files?

I defined only ROM.ld. How we can make decision which mode to go for?
Does this depend on the application or its our choice?

Here is my AT91SAM7x256-ROM.ld file. Is it correct ?

/*---------------------------------------------------------------------- 
-----*/
/*-         ATMEL Microcontroller Software Support  -  ROUSSET  -
*/
/*---------------------------------------------------------------------- 
-----*/
/* The software is delivered "AS IS" without warranty or condition of
any    */
/* kind, either express, implied or statutory. This includes without
*/
/* limitation any warranty or condition with respect to merchantability
or   */
/* fitness for any particular purpose, or against the infringements of
*/
/* intellectual property rights of others.
*/
/*---------------------------------------------------------------------- 
-----*/
/*- File source          : GCC_FLASH.ld
*/
/*- Object               : Linker Script File for Flash Workspace
*/
/*- Compilation flag     : None
*/
/*-
*/
/*- 1.0 20/Oct/04 JPP    : Creation
*/
/*---------------------------------------------------------------------- 
-----*/

/*
  modified for the WinARM example - M.Thomas (not Atmel)
  - ramfunc-section/C++-support and more
*/

/*
//*** <<< Use Configuration Wizard in Context Menu >>> ***
*/


/*
// <h> Memory Configuration
//   <h> Code (Read Only)
//     <o>  Start <0x0-0xFFFFFFFF>
//     <o1> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Data (Read/Write)
//     <o2> Start <0x0-0xFFFFFFFF>
//     <o3> Size  <0x0-0xFFFFFFFF>
//   </h>
//   <h> Top of Stack (Read/Write)
//     <o4> STACK <0x0-0xFFFFFFFF>
//   </h>
// </h>
*/

/* Memory Definitions */

/* mt change code origin from 0x00000000 */
MEMORY
{
  CODE (rx) : ORIGIN = 0x00100000, LENGTH = 256K
  DATA (rw) : ORIGIN = 0x00200000, LENGTH = 64K
  STACK (rw) : ORIGIN = 0x00204000,LENGTH = 0x00000000
}

__FIRST_IN_RAM = ORIGIN(DATA);

/* Section Definitions */

SECTIONS
{
  /* first section is .text which is used for code */
  . = 0x0000000;

  .text :
  {
    KEEP(*(.vectorg))
    . = ALIGN(4);
    KEEP(*(.init))
    *(.text .text.*)                   /* remaining code */
    *(.gnu.linkonce.t.*)
    *(.glue_7)
    *(.glue_7t)
    *(.gcc_except_table)
    *(.rodata)                 /* read-only data (constants) */
    *(.rodata.*)
    *(.gnu.linkonce.r.*)
    . = ALIGN(4);
  } >CODE

  . = ALIGN(4);

  /* .ctors .dtors are used for c++ constructors/destructors */

  .ctors :
  {
    PROVIDE(_ctors_start_ = .);
    KEEP(*(SORT(.ctors.*)))
    KEEP(*(.ctors))
    PROVIDE(_ctors_end_ = .);
  } >CODE

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

  . = ALIGN(4);

  _etext = . ;
  PROVIDE (etext = .);

  /* .data section which is used for initialized data */
  .data : AT (_etext)
  {
  _data = . ;
  KEEP(*(.vectmapped))
  . = ALIGN(4);
  *(.fastrun .fastrun.*)
  . = ALIGN(4);
  SORT(CONSTRUCTORS)
  . = ALIGN(4);
  *(.data)
  *(.data.*)
  *(.gnu.linkonce.d.*)
  . = ALIGN(4);
  } >DATA

  . = ALIGN(4);

  _edata = . ;
  PROVIDE (edata = .);

  /* .bss section which is used for uninitialized data */
  .bss :
  {
  __bss_start = . ;
  _bss_start_ = . ;
  *(.bss)
  *(.bss.*)
  *(.gnu.linkonce.b.*)
  *(COMMON)
  . = ALIGN(4);
  } >DATA
  . = ALIGN(4);
  _bss_end_ = . ;

  _end = .;
  PROVIDE (end = .);

  .int_data :
  {
    *(.internal_ram_top)
  } > STACK



  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  /* DWARF debug sections.
   Symbols in the DWARF debugging sections are relative to the beginning
   of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }

}


Regards
Flying

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.