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
You should tell the compiler that they are C functions: extern "C" { void LowLevelInit(void); void InitPeriphery(void); }
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.
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
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
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
> 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
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
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
Log in with Google account
No account? Register here.