avr-c++ micro how-to

Go To Last Post
94 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 3

Hi everybody,
a couple of months ago I started with AVR and c++. It's rather painful adventure, but now most of things seems to work. So I decided to share my little experience, maybe it will be useful for you.
First thing – setup. I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work. Remember that if you want to debug your application you need rather to turn off code optimization (-O0). In other case debugging is extremely hard thing to do and confusing. Final compilation can be done with any optimization options.
Next thing to do is to define new and delete operators:

#include 

void * operator new(size_t size);
void operator delete(void * ptr);

and implementation:

void * operator new(size_t size)
{
  return malloc(size);
}

void operator delete(void * ptr)
{
  free(ptr);
}

That's almost all. Almost because if you are using gcc 4.x and newer (I didn't check it with older versions) and you want to use templates, virtual inheritance and so on you must define some additional functions, which is not used now by compiler, but must be present to satisfy linker:

__extension__ typedef int __guard __attribute__((mode (__DI__)));

extern "C" int __cxa_guard_acquire(__guard *);
extern "C" void __cxa_guard_release (__guard *);
extern "C" void __cxa_guard_abort (__guard *);

Please be sure to define these functions exactly as I showed, I other case gcc could crash during compilation (segmentation fault!), and for sure your program WILL BE NOT working.
Implementation is as follow (very important too):

int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};

And last thing, if you use pure virtual functions you must define another function:

extern "C" void __cxa_pure_virtual(void);

and implementation:

void __cxa_pure_virtual(void) {};

This function is never called in normal operation. The only time this function may get called is if the application calls a virtual function while the object is still being created, which gives undefined behavior. So implementation is not very important for us.
With all this things defined I was able to compile my c++ programs without any problems, and I wish the same to you.
Greetings,
Tomasz.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brilliant!

Attention moderators! Sticky candidate?

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At the very least I thought Tomasz ought to repost this as a tutorial in the Tutorial Forum so it's doesn't get "lost"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also, someone put the term "CPlusPlus" in it so that it can be found by the search function. Oh look, someone just did :)

Regards,
Steve A.

The Board helps those that help themselves.

Last Edited: Sat. Apr 12, 2008 - 05:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't have any of the cxa stuff. I never heard of it. My virtual functions aren't pure though.

The only problem I have with virtual functions is they use a huge amount of RAM and quite a bit of program memory also.

I'm currently using gcc version 4.1.2.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

These array handlers may be useful too:

void * operator new[](size_t size) 
{ 
    return malloc(size); 
} 

void operator delete[](void * ptr) 
{ 
    free(ptr); 
} 

C: i = "told you so";

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

except the spurious semicolons that generate errors in pedantic + ansi mode,

int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};

,
you just made a top grade post.

I would also add '-fno-exceptions' and maybe '-ansi --pedantic -Wall' to avoid shooting ourselves in the foot. g++ AVR is uncharted minefield. Any other flags to include?

BTW in order to help newbies finding the g++ and make quicker, here is my example of Project Options/External tools that worked for me:
I:\WinAVR-20071221\bin\avr-g++.exe
I:\WinAVR-20071221\utils\bin\make.exe

The last trap is in the fact that by default printf is not supporting float numbers. However because the C++ projects can be complex, it is wise to go to Project Options/Libraries section, you might want to include
libprintf_flt
libscanf_flt
libc
libm
libobjc
but NOT libprintf_min, libscanf_min

BTW I remember the problem, when a simple code

int main()
{
	DDRC=0xFF;
	for(;;)
	{
		PORTC=0xFF;
		_delay_us(1);
		PORTC=0x00;
		_delay_us(1);
	}
}

...was not working just because I have been instancing a static class object in one of include files. It took me the whole night to find the problem, hopefully my suspicions pointed onto global objects very early. The funny part was, that everything worked when the project was big. Once I have simplified (!!!) main() function to the code above, it stopped working (freeze before main). I have hunted down the statically instantiated class in one of includes, and moved it as static object to main().
This time, however, it started complaining about lacking __cxa_guard_acquire, __cxa_guard_release.
So remember, when you make static class object in global scope, without providing these functions, the code will fail silently, depending on the actual size of the project and many other factors.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kbosak wrote:

I would also add '-fno-exceptions' and maybe '-ansi --pedantic -Wall' to avoid shooting ourselves in the foot. g++ AVR is uncharted minefield. Any other flags to include?

These will help with the code size.

-ffunction-sections 
-Wl,--gc-sections 

http://www.avrfreaks.net/index.p...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
Hi everybody,
a couple of months ago I started with AVR and c++. It's rather painful adventure, but now most of things seems to work. So I decided to share my little experience, maybe it will be useful for you.
First thing – setup. I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work. Remember that if you want to debug your application you need rather to turn off code optimization (-O0). In other case debugging is extremely hard thing to do and confusing. Final compilation can be done with any optimization options.
Next thing to do is to define new and delete operators:

#include 

void * operator new(size_t size);
void operator delete(void * ptr);

and implementation:

void * operator new(size_t size)
{
  return malloc(size);
}

void operator delete(void * ptr)
{
  free(ptr);
}

That's almost all.
... (abridged) ...

With all this things defined I was able to compile my c++ programs without any problems, and I wish the same to you.
Greetings,
Tomasz.

This is pretty impressive (I thought I knew a thing or two about C++, but "guard"s are a new one on me).

One thing I think you have missed, though, is that delete operators are supposed to safely do nothing if they're passed a NULL pointer. So your sample implementation of delete should look like this:

void operator delete(void * ptr)
{
  if (ptr)
    free(ptr);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

One thing I think you have missed, though, is that delete operators are supposed to safely do nothing if they're passed a NULL pointer. So your sample implementation of delete should look like this:

void operator delete(void * ptr)
{
  if (ptr)
    free(ptr);
}


This is a surprise to me. I always believed since 1990 that free(NULL) is always OK, even if I almost never wrote code using this. http://www.winehq.org/pipermail/...
says:
ANSI-C Standard:
----------------
The ANSI standard ANSI X3.159-1989 "Programming Language C." specifies
that free(NULL) is a no op.
"free deallocates the space pointed to by p: it does nothing if p is NULL."
Quoted from "The C Programming Language" second edition by Kernighan and
Ritchie with the subtitle "ANSI C".

This would indicate that your protection is superfluous.
BTW for nitpickers that like excess safety, the code should be:

if(ptr!=NULL)
{
    free(ptr);
}

because (oh there are long and useless discussions about that) NULL dont have to be 0 numerically.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
because (oh there are long and useless discussions about that) NULL dont have to be 0 numerically.
Actually NULL has to be 0 in C++ (and many C++ programmers avoid using NULL).

http://www.research.att.com/~bs/bs_faq2.html#null
/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kbosak wrote:

This is a surprise to me. I always believed since 1990 that free(NULL) is always OK, even if I almost never wrote code using this. http://www.winehq.org/pipermail/...
says:
ANSI-C Standard:
----------------
The ANSI standard ANSI X3.159-1989 "Programming Language C." specifies
that free(NULL) is a no op.
"free deallocates the space pointed to by p: it does nothing if p is NULL."
Quoted from "The C Programming Language" second edition by Kernighan and
Ritchie with the subtitle "ANSI C".

This would indicate that your protection is superfluous.

Wualll, I'll be darned. This is one of those superstitious "safety measure" habits that reinforce themselves; like wearing a Shriners hat to ward off flying squirrel attacks. You wear the hat, and voilla! no squirrels! After awhile, the two seem to be correlated. No particular harm done, but you DO look silly..

I'd always assumed that free()ing NULL was bad medicine, and even have dim recollection of crash dumps from our embedded code when it tried to do so (but we used an extremely old compiler). Anyway, I thought the safety of delete-ing NULL pointers was unique to C++.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
and many C++ programmers avoid using NULL

I am sorry but this is void* argument.
Most programmers are not compiler developers and most compiler developers don't care aboutev erything the Standard says, not to mention about being familiar with avr-g++.

There is more than that:

malloc(0)

in practice behaves like

new ptr[0]

The trick is that C++

new ptr[0]

is standard sanctioned: returning NONNULL, properly aligned pointer for a single element!

malloc(0)

returning nonnull may or may not be standard.
This helps implementing some dynamic data structures, I believe.
http://gcc.gnu.org/ml/libstdc++/...
"
The standard defines that allocators
(and operator new) may be asked for zero bytes. They must return an
address different from any other address that they have returned that
haven't since been released. (That disallows returning 0.) Most
implementations treat a call to operator new(0) identically to operator
new(1).
"

Last Edited: Sat. Jun 21, 2008 - 10:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.

It's only when you want to dynamically "churn the heap" that it is required. To put it another way, if the equivalent C program would use malloc and free, then your C++ program would also use them, via new and delete.

Balancing each new with a delete is considered good practice in programs that run on PCs, but it serves no purpose on AVR programs where there is no shutdown except a hardware reset. Actually I question if it has any purpose in embedded programs that run on PCs, but I do it just because it's "good practice".

On an AVR, just "new" everything at startup and run with what you have until the end of time or reset/powerdown, whichever comes first.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Balancing each new with a delete is considered good practice in programs that run on PCs, but it serves no purpose on AVR programs where there is no shutdown except a hardware reset.

Sorry, short-sighted idea. In fact many efficient linear algebra algorithms require special handling of sparse matrices for max speed. This calls for dynamic data structures. In order to keep implementation of those data structures clean, dynamic memory allocation is necessary. This is the major benefit of using C/C++ over FORTRAN in scientific programming. Using advanced linear algebra/geometry/fitting/optimization algoritms is very popular in many areas, just to mention GPS receivers. GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

Let's put it this way: you can get rid of malloc and free completely. But one day, you will write a complex data structure, that uses fixed memory pool. Next day you will find that in runtime this structure hides 20% of innovatory code and 80% of code that immitates malloc's functionality.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kbosak wrote:
Sorry, short-sighted idea.

So you are saying that any C programmer that doesn't include malloc and free in all his programs is short-sighted?

All I'm saying is C++ doesn't need malloc and free any more than C programs. If a program needs it, use it. Otherwise don't. Of course if you have excessive program memory then it doesn't matter. I rarely find myself in that situation though.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

steve17 wrote:
kbosak wrote:
Sorry, short-sighted idea.

So you are saying that any C programmer that doesn't include malloc and free in all his programs is short-sighted?

All I'm saying is C++ doesn't need malloc and free any more than C programs. If a program needs it, use it. Otherwise don't. Of course if you have excessive program memory then it doesn't matter. I rarely find myself in that situation though.


I was commetning this:
Quote:
The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OT:

Quote:
GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

That is a somewhat misleading statement. Definition of 'simpler' and 'easily' required.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Broxbourne wrote:
OT:
Quote:
GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

That is a somewhat misleading statement. Definition of 'simpler' and 'easily' required.

You can use Student-Lockroom programming to achieve the result.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
You can use Student-Lockroom programming to achieve the result.

Thanks, I didn't know that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
###############################################################################
# Makefile for the project cpptest
###############################################################################

## General Flags
PROJECT = cpptest
MCU = atmega128
TARGET = cpptest.elf
CC = avr-g++.exe

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall   --pedantic  -fno-exceptions  -Wl,--gc-sections  -ffunction-sections     -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ansi 
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d 

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -Wl,-Map=cpptest.map


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings


## Include Directories
INCLUDES = -I"I:\ATMEGA\ATMEGA128\..\..\WinAVR-20071221\avr\include\avr" 

## Libraries
LIBS = -lc -lm -lprintf_flt -lscanf_flt 

## Objects that must be built in order to link
OBJECTS = cpptest.o 

## Objects explicitly added by the user
LINKONLYOBJECTS = 

## Build
all: $(TARGET) cpptest.hex cpptest.eep cpptest.lss size

## Compile
cpptest.o: ../../cpptest.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

##Link
$(TARGET): $(OBJECTS)
	 $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET)
	avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@

%.eep: $(TARGET)
	-avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0

%.lss: $(TARGET)
	avr-objdump -h -S $< > $@

size: ${TARGET}
	@echo
	@avr-size -C --mcu=${MCU} ${TARGET}

## Clean target
.PHONY: clean
clean:
	-rm -rf $(OBJECTS) cpptest.elf dep/* cpptest.hex cpptest.eep cpptest.lss cpptest.map


## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
#include 
#include 

// C++  helpers /////////////////////
#include 
void * operator new(size_t size);
void operator delete(void * ptr); 
void * operator new(size_t size)
{
	return malloc(size);
}
void operator delete(void * ptr)
{
	free(ptr);
}
__extension__ typedef int __guard __attribute__((mode (__DI__)));
extern "C" int __cxa_guard_acquire(__guard *);
extern "C" void __cxa_guard_release (__guard *);
extern "C" void __cxa_guard_abort (__guard *);
int __cxa_guard_acquire(__guard *g)
{
	return !*(char *)(g);
}
void __cxa_guard_release (__guard *g)
{
	*(char *)g = 1;
}
void __cxa_guard_abort (__guard *)
{
}
extern "C" void __cxa_pure_virtual(void);
void __cxa_pure_virtual(void)
{
}
//////////////////////////////////////

class CCCP
{
	float a;
	float b;
public:
	CCCP()
	{
	}
	CCCP(float aarg)
	{
		a=aarg;
	}
};

static CCCP * cccp=NULL;
static CCCP cccp_static(1.2);//This doesn't work

int main()
{
	//cccp=new CCCP();//This doesn't work
	DDRC=0xFF;
	for(;;)
	{
		PORTC=0xFF;
		_delay_ms(50);
		PORTC=0x00;
		_delay_ms(50);
	}
	return 0;
}
Build started 23.6.2008 at 16:25:05
avr-g++.exe -I"I:\ATMEGA\ATMEGA128\..\..\WinAVR-20071221\avr\include\avr"  -mmcu=atmega128 -Wall   --pedantic  -fno-exceptions  -Wl,--gc-sections  -ffunction-sections     -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enu
ms -ansi -MD -MP -MT cpptest.o -MF dep/cpptest.o.d  -c  ../../cpptest.c

../../cpptest.c:51: warning: 'cccp' defined but not used
avr-g++.exe: --gc-sections: linker input file unused because linking not done
avr-g++.exe -mmcu=atmega128 -Wl,-Map=cpptest.map cpptest.o    -lc -lm -lprintf_flt -lscanf_flt  -o cpptest.elf
avr-objcopy -O ihex -R .eeprom  cpptest.elf cpptest.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex cpptest.elf cpptest.eep || exit 0
avr-objdump -h -S cpptest.elf > cpptest.lss

AVR Memory Usage
----------------
Device: atmega128

Program:     900 bytes (0.7% Full)
(.text + .data + .bootloader)

Data:         18 bytes (0.4% Full)
(.data + .bss + .noinit)


Build succeeded with 1 Warnings...
Archive member included because of file (symbol)

i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
                              i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o (exit)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
                              cpptest.o (__do_clear_bss)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
                              cpptest.o (__do_global_ctors)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
                              i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o) (__tablejump__)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                              cpptest.o (malloc)

Allocating common symbols
Common symbol       size              file

__brkval            0x2               i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
__flp               0x2               i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)

Memory Configuration

Name             Origin             Length             Attributes
text             0x00000000         0x00020000         xr
data             0x00800060         0x0000ffa0         rw !x
eeprom           0x00810000         0x00010000         rw !x
fuse             0x00820000         0x00000400         rw !x
lock             0x00830000         0x00000400         rw !x
signature        0x00840000         0x00000400         rw !x
*default*        0x00000000         0xffffffff

Linker script and memory map

Address of section .data set to 0x800100
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
LOAD cpptest.o
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libprintf_flt.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libscanf_flt.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libm.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a

.hash
 *(.hash)

.dynsym
 *(.dynsym)

.dynstr
 *(.dynstr)

.gnu.version
 *(.gnu.version)

.gnu.version_d
 *(.gnu.version_d)

.gnu.version_r
 *(.gnu.version_r)

.rel.init
 *(.rel.init)

.rela.init
 *(.rela.init)

.rel.text
 *(.rel.text)
 *(.rel.text.*)
 *(.rel.gnu.linkonce.t*)

.rela.text
 *(.rela.text)
 *(.rela.text.*)
 *(.rela.gnu.linkonce.t*)

.rel.fini
 *(.rel.fini)

.rela.fini
 *(.rela.fini)

.rel.rodata
 *(.rel.rodata)
 *(.rel.rodata.*)
 *(.rel.gnu.linkonce.r*)

.rela.rodata
 *(.rela.rodata)
 *(.rela.rodata.*)
 *(.rela.gnu.linkonce.r*)

.rel.data
 *(.rel.data)
 *(.rel.data.*)
 *(.rel.gnu.linkonce.d*)

.rela.data
 *(.rela.data)
 *(.rela.data.*)
 *(.rela.gnu.linkonce.d*)

.rel.ctors
 *(.rel.ctors)

.rela.ctors
 *(.rela.ctors)

.rel.dtors
 *(.rel.dtors)

.rela.dtors
 *(.rela.dtors)

.rel.got
 *(.rel.got)

.rela.got
 *(.rela.got)

.rel.bss
 *(.rel.bss)

.rela.bss
 *(.rela.bss)

.rel.plt
 *(.rel.plt)

.rela.plt
 *(.rela.plt)

.text           0x00000000      0x37e
 *(.vectors)
 .vectors       0x00000000       0x8c i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x00000000                __vectors
                0x00000000                __vector_default
 *(.vectors)
 *(.progmem.gcc*)
 *(.progmem*)
                0x0000008c                . = ALIGN (0x2)
                0x0000008c                __trampolines_start = .
 *(.trampolines)
 .trampolines   0x0000008c        0x0 linker stubs
 *(.trampolines*)
                0x0000008c                __trampolines_end = .
 *(.jumptables)
 *(.jumptables*)
 *(.lowtext)
 *(.lowtext*)
                0x0000008c                __ctors_start = .
 *(.ctors)
 .ctors         0x0000008c        0x2 cpptest.o
                0x0000008e                __ctors_end = .
                0x0000008e                __dtors_start = .
 *(.dtors)
                0x0000008e                __dtors_end = .
 SORT(*)(.ctors)
 SORT(*)(.dtors)
 *(.init0)
 .init0         0x0000008e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x0000008e                __init
 *(.init0)
 *(.init1)
 *(.init1)
 *(.init2)
 .init2         0x0000008e        0xc i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 *(.init2)
 *(.init3)
 *(.init3)
 *(.init4)
 .init4         0x0000009a       0x1a i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x0000009a                __do_copy_data
 .init4         0x000000b4       0x10 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
                0x000000b4                __do_clear_bss
 *(.init4)
 *(.init5)
 *(.init5)
 *(.init6)
 .init6         0x000000c4       0x16 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
                0x000000c4                __do_global_ctors
 *(.init6)
 *(.init7)
 *(.init7)
 *(.init8)
 *(.init8)
 *(.init9)
 .init9         0x000000da        0x8 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 *(.init9)
 *(.text)
 .text          0x000000e2        0x4 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x000000e2                __vector_22
                0x000000e2                __vector_28
                0x000000e2                __vector_1
                0x000000e2                __vector_32
                0x000000e2                __vector_34
                0x000000e2                __vector_24
                0x000000e2                __vector_12
                0x000000e2                __bad_interrupt
                0x000000e2                __vector_6
                0x000000e2                __vector_31
                0x000000e2                __vector_3
                0x000000e2                __vector_23
                0x000000e2                __vector_30
                0x000000e2                __vector_25
                0x000000e2                __vector_11
                0x000000e2                __vector_13
                0x000000e2                __vector_17
                0x000000e2                __vector_19
                0x000000e2                __vector_7
                0x000000e2                __vector_27
                0x000000e2                __vector_5
                0x000000e2                __vector_33
                0x000000e2                __vector_4
                0x000000e2                __vector_9
                0x000000e2                __vector_2
                0x000000e2                __vector_21
                0x000000e2                __vector_15
                0x000000e2                __vector_29
                0x000000e2                __vector_8
                0x000000e2                __vector_26
                0x000000e2                __vector_14
                0x000000e2                __vector_10
                0x000000e2                __vector_16
                0x000000e2                __vector_18
                0x000000e2                __vector_20
 .text          0x000000e6        0x0 cpptest.o
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
 .text          0x000000e6      0x1fc i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                0x000000e6                malloc
                0x00000236                free
                0x000002e2                . = ALIGN (0x2)
 *(.text.*)
 .text.__cxa_guard_acquire
                0x000002e2       0x14 cpptest.o
                0x000002e2                __cxa_guard_acquire
 .text.__cxa_guard_release
                0x000002f6        0x8 cpptest.o
                0x000002f6                __cxa_guard_release
 .text.__cxa_guard_abort
                0x000002fe        0x2 cpptest.o
                0x000002fe                __cxa_guard_abort
 .text.__cxa_pure_virtual
                0x00000300        0x2 cpptest.o
                0x00000300                __cxa_pure_virtual
 .text._Z41__static_initialization_and_destruction_0ii
                0x00000302       0x24 cpptest.o
 .text._GLOBAL__I__Znwj
                0x00000326        0xe cpptest.o
 .text._ZdlPv   0x00000334        0x6 cpptest.o
                0x00000334                operator delete(void*)
 .text._Znwj    0x0000033a        0x6 cpptest.o
                0x0000033a                operator new(unsigned int)
 .text.main     0x00000340       0x30 cpptest.o
                0x00000340                main
 .text.libgcc   0x00000370        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .text.libgcc   0x00000370        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .text.libgcc   0x00000370        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .text.libgcc   0x00000370        0xc i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
                0x00000374                __tablejump__
                0x00000370                __tablejump2__
                0x0000037c                . = ALIGN (0x2)
 *(.fini9)
 .fini9         0x0000037c        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
                0x0000037c                exit
                0x0000037c                _exit
 *(.fini9)
 *(.fini8)
 *(.fini8)
 *(.fini7)
 *(.fini7)
 *(.fini6)
 *(.fini6)
 *(.fini5)
 *(.fini5)
 *(.fini4)
 *(.fini4)
 *(.fini3)
 *(.fini3)
 *(.fini2)
 *(.fini2)
 *(.fini1)
 *(.fini1)
 *(.fini0)
 .fini0         0x0000037c        0x2 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 *(.fini0)
                0x0000037e                _etext = .

.data           0x00800100        0x6 load address 0x0000037e
                0x00800100                PROVIDE (__data_start, .)
 *(.data)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 .data          0x00800100        0x0 cpptest.o
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
 .data          0x00800100        0x6 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                0x00800102                __malloc_heap_start
                0x00800104                __malloc_heap_end
                0x00800100                __malloc_margin
 *(.data*)
 *(.rodata)
 *(.rodata*)
 *(.gnu.linkonce.d*)
                0x00800106                . = ALIGN (0x2)
                0x00800106                _edata = .
                0x00800106                PROVIDE (__data_end, .)

.bss            0x00800106        0xc load address 0x00000384
                0x00800106                PROVIDE (__bss_start, .)
 *(.bss)
 .bss           0x00800106        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 .bss           0x00800106        0x8 cpptest.o
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
 *(.bss*)
 *(COMMON)
 COMMON         0x0080010e        0x4 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                0x0080010e                __brkval
                0x00800110                __flp
                0x00800112                PROVIDE (__bss_end, .)
                0x0000037e                __data_load_start = LOADADDR (.data)
                0x00000384                __data_load_end = (__data_load_start + SIZEOF (.data))

.noinit         0x00800112        0x0
                0x00800112                PROVIDE (__noinit_start, .)
 *(.noinit*)
                0x00800112                PROVIDE (__noinit_end, .)
                0x00800112                _end = .
                0x00800112                PROVIDE (__heap_start, .)

.eeprom         0x00810000        0x0
 *(.eeprom*)
                0x00810000                __eeprom_end = .

.fuse
 *(.fuse)
 *(.lfuse)
 *(.hfuse)
 *(.efuse)

.lock
 *(.lock*)

.signature
 *(.signature*)

.stab           0x00000000      0x414
 *(.stab)
 .stab          0x00000000      0x414 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o

.stabstr        0x00000000       0x5f
 *(.stabstr)
 .stabstr       0x00000000       0x5f i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o

.stab.excl
 *(.stab.excl)

.stab.exclstr
 *(.stab.exclstr)

.stab.index
 *(.stab.index)

.stab.indexstr
 *(.stab.indexstr)

.comment
 *(.comment)

.debug
 *(.debug)

.line
 *(.line)

.debug_srcinfo
 *(.debug_srcinfo)

.debug_sfnames
 *(.debug_sfnames)

.debug_aranges
 *(.debug_aranges)

.debug_pubnames
 *(.debug_pubnames)

.debug_info
 *(.debug_info)
 *(.gnu.linkonce.wi.*)

.debug_abbrev
 *(.debug_abbrev)

.debug_line
 *(.debug_line)

.debug_frame
 *(.debug_frame)

.debug_str
 *(.debug_str)

.debug_loc
 *(.debug_loc)

.debug_macinfo
 *(.debug_macinfo)
OUTPUT(cpptest.elf elf32-avr)
LOAD linker stubs

After noticing some problems with my larger project, moved back to make to retest simpler code. With all our modifications, the code always hangs! I am surprised. I have tested the code some half a year ago. Creating global instances of classes works only if there are lots of code... Then it works. It means the classes are instantiated in some magic memory areas, overlapping innocent global variables (?).
I have retested so many other details, optimisation options etc. What went wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Proposal: alternatively, since our program in G++ for AVR is fully single-threaded by nature, we can define -fno-threadsafe-statics instead of defining __cxa_guard_acquire and friends.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kbosak wrote:
Proposal: alternatively, since our program in G++ for AVR is fully single-threaded by nature, we can define -fno-threadsafe-statics instead of defining __cxa_guard_acquire and friends.

That is bad assumption, one can write multi-threaded C++ AVR programs, and even without threads there is a possibility of for recursion involving ISRs. If such situations can occur in our program __cxa_guard_acquire and friends would need to protect against this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
That is bad assumption, one can write multi-threaded C++ AVR programs, and even without threads there is a possibility of for recursion involving ISRs. If such situations can occur in our program __cxa_guard_acquire and friends would need to protect against this.
True, but note that the __cxa_guard* implementation above is a minimum (dummy) implementation - it does not add any thread safety.
/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think fno-threadsafe-statics is a good solution for a default setting since a lot of programs written for AVR aren't multi-threaded. The only way I see this effecting an ISR is if someone is calling a function in the ISR in which case they could compile that one function without fno-threadsafe-statics and then write their own __cxa_guard* functions. I suppose there are more cases but I think needing __cxa_guard* is more of a special case.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TFrancuz wrote:
I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work.

Correct me if I'm wrong, but it seems to me that if I create my source file with an upper case C extension instead of lower case AVR-GCC will compile as C++ without the editing mentioned above.

I'm not sure if renameing from .c to .C will work. The file must probably be created with upper case from the beginning.

JHJ

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You probably need to "remove file(s) from project..", rename to .C and the "add existing source file(s)..." to be sure that Studio makes the right decision about invoking the C++ compiler but otherwise, yes, it sounds like that would be the easy answer.

Cliff

(previously there's been reports of folks having problems the other way round where they've inadvertently used a MAIN.C or something in Studio and ended up getting C++ warnings - so it should work)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
You probably need to "remove file(s) from project..", rename to .C and the "add existing source file(s)..." ...

Yes, because Studio refuses changing the extension.

Quote:
... to be sure that Studio makes the right decision about invoking the C++ compiler

No, Studio will still call avr-gcc.
avr-gcc itself makes the decision to use the C++-compiler due to the file name (.C) on the command line.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
No, Studio will still call avr-gcc.
avr-gcc itself makes the decision to use the C++-compiler due to the file name (.C) on the command line.

Thanks for stating the obvious but I know that - the whole point here was to prevent the need to edit the field in Studio where it invokes avr-gcc.exe

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmmm, I don't understand but then I don't use AVR Studio to do my builds.

For the record, I find files ending in .cpp get compiled as if they were C++ files, and files ending in .c are compiled as C files.

I never tried .C and I never heard of .hpp, just .h.

My makefile calls avr-gcc.exe

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Upon converting my code to the C++ project i came across 1 warning about my custom lcd characters:

static const PROGMEM unsigned char customCharacters[] =
{
	//Character 0
	0b00000,
	0b01110,
	0b10001,
	0b11111,
	0b10001,
	0b10001,
	0b01110,
	0b00000,

	//Character 1
	0b00000,
	0b11111,
	0b10000,
	0b10000,
	0b10000,
	0b10000,
	0b11111,
	0b00000
};

Gives: "warning: only initialized variables can be placed into program memory area"

Any thoughts?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's a known bug: http://www.avrfreaks.net/index.p...

Also, doing a web search with the error message will give you links to other reports about that as well as a link to the bug report on the avr-gcc bug tracker.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think I've just found another gotcha in AVR Studio, which hopefully some people may find useful?. (It took me a few hours of Google searching and guessing before I hit on the idea of what was going wrong).

Apparently AVR Studio doesn't support .CPP files. The files need to be called ".c" and not ".cpp" (even though the code in the file is C++).

When CPP files are used, the AVR Studio (V4.14 build 589) fails to generate compile instructions in the makefile for the object file, e.g. it looked like this in the makefile...
## Compile
##Link

But when the .CPP files were renamed to .C it then generated a makefile that looked like this (and compiled ok)...
## Compile
Wire.o: ../Wire.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

ArrayDisplay.o: ../ArrayDisplay.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

LCD1.o: ../LCD1.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

lcd.o: ../lcd.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

twi.o: ../twi.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

VirtualScreen.o: ../VirtualScreen.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

##Link

In hindsight, its very easy when you know that's what you have to do, but I've not seen it mentioned anywhere, not to call files CPP (which is what I usually use for other non-avr compilers like PC etc.).

I don't know if this is a bug or by design, but anyway, I thought this may help someone? ... (It would have helped me! :P).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll speculate:

AVR Studio is not case sensitive, and thus recognices both .c and .C as a file type that it thinks it can handle.

WinAVR/avr-gcc on the other hand IS case sensitive as it stems from the GNU/U*ix world, and there are three file types that I've seen used for C++ source files: .C (not to be confused with .c), .cpp and .cxx .

Thus AVR Studio thinks of your source files as C sources, but then passes them to avr-gcc which treats them as C++ source files. (The test you can make is to try to place C++ code in a .c source file, add it to Studio and see what happends. I'll bet that avr-gcc will spit it out.)

Although the approach you have taken seems to work it has the disadvantage that you can not set specific compiler flags for C++ sources different from those you set for C sources (unless you specify them for each file individually). In this sense AVR Studio does not support C++. If you will need special treatment for C++ sources then there is no other way that I know of than to write your own makefile and feed that to AVR Studio.

Here's some gcc documentation that seem to support my speculation:

Quote:
C++ source files conventionally use one of the suffixes `.C', `.cc', `.cpp', `.CPP', `.c++', `.cp', or `.cxx'[...]. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs [...]

And when you are ready for it, learning make is actually not that hard. The documentation is very good: http://www.gnu.org/software/make...

HTH!

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I recently faced a situation were I needed a Singleton-like (http://en.wikipedia.org/wiki/Singleton_pattern) object.

template< uint8_t BitNo >
ProtocolHandler< BitNo > &	ProtocolHandler< BitNo >::Machine( )
{
	static ProtocolHandler< BitNo >	machine;
	return	machine;
}

When compiling such code, I was taunted by this error:

Quote:
undefined reference to `atexit'

After some googling, I found this thread:
http://www.embeddedrelated.com/usenet/embedded/show/88449-1.php

Wich provides an easy solution that I want to share here to complete the "micro howto".

///	MCU would never "exit", so atexit can be dummy.
extern "C" void	atexit( void ) { }

And if I am here to collaborate, there are two other functions that can be usefull if one wants to avoid AVR-libc dynamic memory management concerns:

/// Placement new for allocating the object inside a given memory buffer.
void *	operator new( size_t, void * const buff )		{	return	buff;	}

/// Placement delete called automatically on "placement new" failure.
void	operator delete( void * p, void * const buff )	{	}

Quote:
The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.

I don't think so.
Dynamic memory management is just meant to avoid memory waste.
In situations were the processing is predictive enough and memory consumption is high, I can control when my data is going to use memory, instead of leaving them in RAM all the time - this data can even not fit, so the management is a must.
Of course the management system takes a little memory for itself, but it is generally a small portion of the heap (unless one plan to use the heap for allocating several single bytes, what is definitely not wise...)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the equivalent C program would benefit from using dynamic memory allocation, then the C++ program would also. But I've not encountered any embedded programs where that was the case.

Malloc and free use the heap a little less efficiently and inclusion of the malloc and free code also uses a considerable amount of program memory.

There is nothing in C++ that requires malloc and free, although it might seem that way. That's because most C++ programs run on PCs, where malloc and free are readily available, and most C++ programs are not embedded and do make good use of dynamic memory.

Some people recommed not dynamically allocating and freeing of memory while an embedded program is running. Maybe the heap software today is good enough, but that wasn't always the case.

I worked on a large and expensive embedded program that ran on PCs and had around 45 threads. We could run most of the software on our desktop machines but the customer, the Department of Defense, got ruggedized machines with a compact PCI chassis.

The rule was to allocate all memory at startup, and delete everything at shutdown. The shutdown thing was for the convenience of the programmers. The customer shut it down by powering it off. We used malloc and free, via new and delete, because there was no reason not to do so. These funcions were there and there was plenty of memory. But again, we only used them at startup and shutdown.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not wanting to appear dumb - just starting out on my first serious C++ project - but what is 'Student-Lockroom' programming?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have a reference to "Student-Lockroom programming" -- Google only brings up this thread.

Thanks.

Dr. David Harris OpenLCB Development Team openlcb.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear freaks

any body has a sample project in c++.containing all of stuff like makefile and main c file.
please post it.

I love Digital
and you who involved in it!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
main c file

Why the need for a main C file? As you can't create and use C++ objects from C code this will add an extra layer of calls to the code.

The somewhat simplified truth is that C++ can call C but not the other way around. The slightly more complicated version is: If your main is in a C source file it has "C linkage". It can call a function in a C++ file but that called function also has to have C linkage (which you get by using the extern "C" language construct). This function in turn can create and use C++ objects.

I seems you want a small C/C++ demo, and having a main in C rather than C++ only makes that demo more complicated.

Could you do with a project with a main function in a C++ file?

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

i mean the c++ main file sorry for that.all i want is a simple c++ demo.

I love Digital
and you who involved in it!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This will blink the LED on my Olimex P40 board.

Attachment(s): 

Last Edited: Tue. Mar 31, 2009 - 10:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thnaks a lot!

I love Digital
and you who involved in it!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hey.. i've got a cuestion.. does the c++ compiler support the implicit convertions for integrated types like strings, integers, etc..? For example, when a function argument should be a string, and i pass it a integer, can the convertion be done by the compiler?

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

For example, when a function argument should be a string, and i pass it a integer, can the convertion be done by the compiler?

Assuming that you by string mean a char * then the answer is no. This is not a pecularity of the avr-gcc compiler. This is how the C++ language is defined.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:
Quote:

Assuming that you by string mean a char * then the answer is no. This is not a pecularity of the avr-gcc compiler. This is how the C++ language is defined.

Thanks for the answer.. I'm using the c++.exe file to compile my program instead of avr-gcc.exe (just like TFrancuz says at the fist comment)so it's c++ language(i guess.. :roll: ), and it still doesn't work.. so, is there a way to make it able to work with implicit convertions?

..thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hey.. has anybody had a problem with strings (char *)? 'cause i'm trying strlen, strcat and itoa.. and they just dont work!!!! maybe there's something i'm doing wrong

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

and they just dont work

Shows as small a program as you possibly can that demonstrates them not working as far as you are concerned.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

so it's c++ language(i guess.. Rolling Eyes ), and it still doesn't work..

It does not matter if it is C or C++. There is no implicit conversion from int to char * in neither language. What makes you think there is?

And AFAIK the language is determined by the filename extension of the source file. Not that it matters in this case, though. You can easily determine if the compiler thinks it is a C or a C++ file that you are sending to it. Just throw a very simple class into it, eg

class Test
{
public:
   int i;
};

and if it barfs over that then it is C, not C++. There are other methods, including testing if CPLUSPLUS (or some such, I really don't recall and don't have the energy to search the correct preprocessor symbol name out) is defined.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Johan,

I want to drive my Jeep to Tahiti, but Jeeps get pretty poor gas mileage and I'm afraid I won't be able to make it from California to Hawaii so can you tell me how to flag down tankers along the way?

Smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I totally lost you there, Joe. Honestly. Knowing you (netwise), quite good I think, I suppose there is some really to-the-point wittiness or sarcasm somewhere in there regarding some mistake I made, but I cant spot it.

I have tried Googling "Smileys Jeep gas shortage bottom Pacific" with and without "driver nuts" but came up with nothing..

Help this stupid Swede out, and give me a clue. Please?!

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Johan,

It wasn't aimed at you, but an attempt to wisecrack about getting into details like char * while using the wrong vehicle for the job in the first place. Some people want to use C++ as C without studying the basics or the philosophical differences between procedural versus object oriented programming. Not pointed at you, just a poor joke about other folks who want to use C++ when they don't seem to know anything about why one would choose C++ over C.

Sorry,
Smiley

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

smileymicros wrote:
Johan,

It wasn't aimed at you, but an attempt to wisecrack about getting into details like char * while using the wrong vehicle for the job in the first place. Some people want to use C++ as C without studying the basics or the philosophical differences between procedural versus object oriented programming. Not pointed at you, just a poor joke about other folks who want to use C++ when they don't seem to know anything about why one would choose C++ over C.

Sorry,
Smiley

So.. i guess you're talking about me.. are not you? And i wonder, why does a philosopher (haha) say that other folks don't know anything about programming paradigms without asking them first?

Before you say anything, try to be sure... this is a tip for life

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Shows as small a program as you possibly can that demonstrates them not working as far as you are concerned.

i've overloaded the << operator to work with a class lcd and strings like: lcd<<"something";

in the function definition i've tried to use the strlen function like this:

Lcd & Lcd::operator<<(char *s)
{

...

int length = strlen(s);

...

}

and i use the variable length at a for loop to print the string.. but it does not make any loop

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I'd actually like to see a bit more, eg the whole of the implementation of the operator overload, a declaration/creation of an Lcd object and a call/use of the operator.

I dont have AVR Studio handy right now (just taking a break with working overtime). But I did pull together this small test in MS VC++ which works like a charm. I of-course simulate sending the characters to the LCD proper with a call to putchar, but apart from that I suppose I am close to what you have?

// JSkywalker.cpp

#include "stdafx.h"
#include 

class Lcd
{
public:
   Lcd & operator<<(char * s)
   {
      for (size_t i= 0; i

I will try something similar in AVR Studio when I get home, if I'm not too tired.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

It wasn't aimed at you, but an attempt to wisecrack about getting into details like char * while using the wrong vehicle for the job in the first place.

That's okay, Joe. I wasn't upset but rather in wisecrack mode myself. Still, and you know this, my position is that many (dare I say "most"?) times C++ is just as good vehicle as C for embedded systems. We might then be in a situation where someone uses an appropriate vehicle but does not know why (bad), and maybe how to operate it (worse).

Please note that I am not accusing JSkywalker being in either situation, but merely dwelling on Joes scenario in general!

Quote:

Sorry

No need to be, Joe. If you actually succeed in hurting me for real, we will settle that in a PM or two. No need for old grumpy beards to fight such things out in public. Anfd you haven't even gotten close yet. :wink:

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's what what I did:

1) Put the Lcd class in a C++ file, and in that file also put a global function test() that exercises the overloaded operator and gave that function C linkage (so that it can be called from main() that is in a C file):

//JSkywalker.cpp
#include 
#include 

class Lcd
{
public:
   Lcd & operator<<(char * s)
   {
      for (size_t i= 0; i

2) wrote a simple main.c, containing main() that calls test(). No, I didnt bother to create a header file for the test() function. Call me sloppy if you like...

//main.c
#include 

void test();

int main(void)
{
   test();

   return 0;
} 

3) Fiddled a bit with the makefile before I got it right (it's been a while since my last experiments with C++ on AVRs).

4) Built the whole shebang, started up AVR Studio, loaded the ELF file and stepped through the code. I see it looping inside the overloaded Lcd::operator<< outputting the chars to PORTB one after the other.

A total success as far as I am concerned.

So now tell us in similar detail, and preferrably in a likewise minimal test/demo project, what your problem is.

Attachment(s): 

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Never mind

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Never mind

What?

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All strings r working.. i've debugged it and i saw it works.. thanks for the help

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello Anyone,
doing embedded stuff with winCE for some time, now i'm back to 8 bit uC but won't miss c++ anymore. Thanks to a few hints from this great thread i'm quite happy now with AVRStudio and C++. Debugging is not as comfortable as with VisualStudio, but in former time we were happy when we had a console for debug output.

Now i would like to do some things like wrapping the peripherals i work with in C++ classes, or create waitable events and stuff.

Therefore it would be necessary to hook the handler methods of some objects to certain ISR vectors.
The only approach coming to my mind would be a dispatcher class. I could create some ugly file with all the ISR handlers in it, which call a static function of this dispatcher class, forwarding some ID or the current IP value to it, to tell which ISR was firing. Objects could then register their instance pointer and the address of a handler method to a global object of that dispatcher class.

This is of course ugly and absolutely not uC-like. Probably you cracks can tell a much better way. Any ideas?

Regards
Manuel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There has been a few discussions here and at avr-libc and avr-gcc lists about ISR's and C++

http://jennaron.com.au/avr/class...

http://lists.gnu.org/archive/htm...
http://lists.gnu.org/archive/htm...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for those links, the first one already pretty much answers my questions.

Manuel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Although not AVR or avr-gcc specific, these might also be interesting reads:
http://www.embedded.com/9900245?...
http://www.embedded.com/columns/...

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abrecht wrote:
i'm quite happy now with AVRStudio and C++. Debugging is not as comfortable as with VisualStudio,
Yes, the AVRStudio debugger says all class member data is "out of scope". That could be considered "not so comfortable". :)

Still, for me C++ is the only way to go.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I belive that readers of this forum would appreciate some concrete, AVR-specific examples that would allow for a quantitative comparison between C and C++ implementation of essentially the same problem specification.

To draw a fair comparison, one would need two equivalent AVR projects designed in object-oriented way, one in C and the other in C++. Otherwise, one would compare different programming paradigms and designs, not the direct impact of the programming language and compiler.

In this context, I believe that the projects at:

http://www.state-machine.com/avr

provide a unique opportunity to quantitatively compare the impact of C++. Specifically, the "QDK/C AVR-GNU" and "QDK/C++ AVR-GNU" projects use object-oriented designs with classes and single inheritance. They are both based on a small state-machine framework on top of which runs the classic "Dining Philosophers Problem" test application consisting of five Philosopher state machines and one Table state machine. The framework code consists mostly of a conditional logic to execute hierarchical state machines as well as an event queue, a timer module, and a tiny preemptive kernel. The Dining Philosophers application consists of state machines. I believe that this code is quite representative for typical projects that run on AVRmega MCUs. (These specific projects have been compiled for the AVR Butterfly board with the AVRmega169 MCU.)

So, here is the quantitative size comparison for the WinAVR/avr-gcc compiler (data taken from the map files in the release configuration):

                | "QDK/C AVR-GNU"  | "QDK/C++ AVR-GNU"
----------------+------------------+--------------------
Code size (ROM) |   5454 bytes     |  6200 bytes (+14%)
----------------+------------------+--------------------
Data size (RAM) |     48 bytes     |    88 bytes (+80%)

The C++ code uses the "Embedded C++" subset, which avoids exceptions and templates leaving basically only the object-oriented features (classes, inheritance, and virtual functions). Also, the C++ code is not using new and delete (and the C code is not using malloc and free).

The code size increase of 14% of C++ compared to C is typical, although for other compilers I've seen an increase of only about 5% for the same "Dining Philosophers" project.

However, the data size increase of 40 bytes is unusually high. I would expect an increase of some 12 bytes for the virtual pointers stored inside the 6 state machine objects that have virtual tables. The mapfiles indicate that the WinAVR compiler allocates virtual tables in the data space (RAM), which is not optimal because v-tables are synthesized at compile time and can typically be stored in ROM. I'm not aware of any compiler options for WinAVR to control placement of virtual tables. Perhaps someone knows how to force the v-tables into the program space (ROM)?

Finally, I hope that my post could help dispel the widespread belief that you can't do object-oriented (or at least object-based) programming in C. In fact, it is quite easy to implement classes and single inheritance in C. I've blogged about it at EmbeddedGurus.net:

http://www.embeddedgurus.net/sta...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The mapfiles indicate that the WinAVR compiler allocates virtual tables in the data space (RAM), which is not optimal because v-tables are synthesized at compile time and can typically be stored in ROM. I'm not aware of any compiler options for WinAVR to control placement of virtual tables. Perhaps someone knows how to force the v-tables into the program space (ROM)?

AFAIK there is no way to get avr-gcc to store the V-tables in ROM (ie in flash memory). This is a performance hit that you get when using C++ (with the avr-gcc compiler) on AVRs.

Thank you for this post. I'll try to find some time to analyze in more detail what constitutes the increases in code and data size.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I took a quick look at the code. It seems it wasn't written as a C++ program. I'd guess it was either a quick copy from C code or it was written by a C programmer masquerading as a C++ programmer. I don't know how that would affect the code size.

I'm reminded of a task switching kernel we used at my previous job. It was taken from Dr. Dobbs Journal. It was written in the C language but it was obviously written by a Fortran programmer. I re-wrote every line of code, which typically happens when I use someone elses code. It was buggy too. It suffered from the "priority inversion" problem. Once fixed and cleaned up, it was pretty neat.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All,

I browsed through this thread and failed to find source files where this discussion would be captured. Are those available anywhere? I could do a shot and upload something I have been using - based on the topmost parts of this thread. However, I am rather new in C++ and especially in embedded environment. I am not sure how *right* my files would be and certainly would appreciate more experienced developers to confirm or fix the files to a good shape.

It would also be nice to have these files available on the first post or other easily found location.

-mikko

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When just starting out with C++ and embedded programming it's easier to start with single thread programs. So using the -fno-threadsafe-statics switch will allow you to bypass the __cxa_guard stuff for a while. With embedded systems __cxa_guard wont be standard and will depend a lot on how the program is implemented. The best you can do is create stub files that can be filled in later when the specifics of the program/RTOS are known.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

which c++ compiler should we be using? the G++ one or C++ one?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just invoke avr-gcc, if the source files have a .cc or .C extension the C++ compiler will be invoked.

As you can see it doesn't actually matter which is actually used:

C:\WinAVR-20100110\bin>fc /b "avr-c++.exe" "avr-g++.exe"
Comparing files avr-c++.exe and AVR-G++.EXE
FC: no differences encountered

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Whatever discussed here, it seems the people at Arduino[1] are able to make C++ work (at least up to some point). Maybe their code can provide some pointers.

--
Alex.

[1] I hope I am allowed to use the A-word in this forum :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Has anybody got this to work with avr studio 5?
I couldn't find a way to configure a project for C++. I started a new project and added C++ files to it, but they didn't compile, they weren't even INCLUDED in the list of files to BE compiled, even though they were added to the project.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you tried AS6? It fixes a lot of the problems AS5 had.

I just started AS6 said "new project" then "c++ executable". It created a .cpp file for me and I typed this into it:

/*
 * GccApplication2.cpp
 *
 * Created: 15/05/2012 14:29:00
 *  Author: cliff
 */ 


#include 

class foo {
	public:
	void setvar(uint8_t c);
	void printvar();
	private:
	uint8_t myvar;
};

void foo::setvar(uint8_t c) {
	myvar = c;
}

void foo::printvar() {
	PORTB = myvar;
}

int main(void)
{
	foo x;
	x.setvar(37);
	x.printvar();
    while(1)
    {
        //TODO:: Please write your application code 
    }
}

When I build the .lss contains:

void foo::setvar(uint8_t c) {
	myvar = c;
  92:	fc 01       	movw	r30, r24
  94:	60 83       	st	Z, r22
}
  96:	08 95       	ret

00000098 <_ZN3foo8printvarEv>:

void foo::printvar() {
	PORTB = myvar;
  98:	fc 01       	movw	r30, r24
  9a:	80 81       	ld	r24, Z
  9c:	88 bb       	out	0x18, r24	; 24
}
  9e:	08 95       	ret

000000a0 
: int main(void) { a0: cf 93 push r28 a2: df 93 push r29 a4: 0f 92 push r0 a6: cd b7 in r28, 0x3d ; 61 a8: de b7 in r29, 0x3e ; 62 foo x; x.setvar(37); aa: ce 01 movw r24, r28 ac: 01 96 adiw r24, 0x01 ; 1 ae: 65 e2 ldi r22, 0x25 ; 37 b0: 0e 94 49 00 call 0x92 ; 0x92 <_ZN3foo6setvarEh> x.printvar(); b4: ce 01 movw r24, r28 b6: 01 96 adiw r24, 0x01 ; 1 b8: 0e 94 4c 00 call 0x98 ; 0x98 <_ZN3foo8printvarEv> bc: ff cf rjmp .-2 ; 0xbc

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
I just started AS6 said "new project" then "c++ executable". It created a .cpp file for me and I typed this into it:

Cool. :D

I was suprised to see this feature when I started to use AS6.

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." - Marcus Aurelius               

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello. Brilliant post; thanks loads for all the information. I'm trying to use new[] and delete[] on an Arduino (using Eclipse) and I think that native support for new[] and delete[] might have made some progress since the original post at the top of this thread.

Specifically, on avr-gcc 4.7.0 (installed on the latest version of Ubuntu: 12.10) it appears that new, new[], delete and delete[] all work out of the box.

But on avr-g++ 4.3.2 (installed by latest version of the Arduino IDE on Windows: 1.0.1) it appears that new and delete work out of the box but new[] and delete[] produce a undefined reference to `operator new[](unsigned int)' error.

Please may I ask two specific questions:

Firstly, is there any way to automatically detect whether new[] and delete[] are already defined? (e.g. a preprocessor directive of some sort)? For example, could we do something like #ifndef _OPERATOR_NEW_[]_ ?!

Secondly, on a platform which already has native new and delete but doesn't have new[] and delete[], should we make use of new and delete and our definitions of new[] and delete[]? e.g. something like this (I'm rather new at this game of manually defining new[] and delete[] so forgive me if this is a dumb suggestion):

void * operator new[](size_t size)
{
    return operator new(size);
}

void operator delete[](void * ptr)
{
    delete ptr;
} 

This appears to compile but produces this warning:

new_test.cpp: In function 'void operator delete [](void*)':
new_test.cpp:25: warning: deleting 'void*' is undefined
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Firstly, is there any way to automatically detect whether new[] and delete[] are already defined? (e.g. a preprocessor directive of some sort)? For example, could we do something like #ifndef _OPERATOR_NEW_[]_ ?!

Well one way would be to use these symbols:

E:\arduino-1.0.1\hardware\tools\avr\libexec\gcc\avr\4.3.2>avr-gcc -E -dM junk.c | grep GNU
#define __GNUC_PATCHLEVEL__ 3
#define __GNUC__ 4
#define __GNUC_MINOR__ 3

(it seems rather curious that the directory is called 4.3.2 but it appears to be 4.3.3?). Anyway just check the minor with something like:

#if __GNUC_MINOR__ == 3
 // define new/delete
#endif

Or perhaps more rigorously:

#define GCC_VERSION (__GNUC__ * 10000 \
                     + __GNUC_MINOR__ * 100 \
                     + __GNUC_PATCHLEVEL__)
...
#if GCC_VERSION <= 40302
 // define new/delete
#endif

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jack_kelly wrote:

This appears to compile but produces this warning:

new_test.cpp: In function 'void operator delete [](void*)':
new_test.cpp:25: warning: deleting 'void*' is undefined

The compiler can't know how to properly delete the pointer since it's void and the actual type it points to isn't specified.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have the following base class:
Class SerialPort
[
public:
SerialPort(size_t inputSize, size_t outputSize, uint_32 baudRate);
virtual bool Put(uint8_t data) = 0;
MyBuffer *GetInputBuff();
MyBuffer *GetOutputBuff();
// member variables are protected and not shown
};

I derive a class SerialPort0 from this
class SerialPort0 : public SerialPort
{
Public:
SerialPort0(size_t inputSize, size_t outputSize, uint32_t baudRate);
bool Put(uint8_t data);
};

And finally I build my main class
class MainClass
{
public:
MainClass();
~MainClass();
void Tick();
SerialPort *GetSerialPort();
void SetPort(SerialPort* _port);
private:
SerialPort *m_serialPort;
}

In the init code
I do the following

MainClass x,y;

x.setPort(y.GetSerialPort());

when I look at the m_serialPort I'm getting a Runtime Error message "An invalid DIE offset was passed to getDieFromId".

I'm stuck any ideas?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'm stuck any ideas?

This is not the place to discuss this - this thread serves to hold long time information that will be of benefit to all users of avr-g++. For specific usage questions start a separate (non sticky) thread.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks loads for the quick replies! I've been grepping through my /usr directory to see if I can find where new, new[], delete and delete[] are defined on my shiny new Ubuntu 12.10 system.

It appears Arduino 1.0.0 introduced the files /hardware/arduino/cores/arduino/new.cpp and new.h, the latter of which defines NEW_H and the functions new and delete (but not new[] or delete[]).

It also appears the binary file /usr/lib/gcc/avr/4.7.0/cc1plus includes the text delete[] several times. So I guess gcc-avr 4.7 has support for new, new[], delete and delete[]. Which is nice!

For reference, it seems that the x86 version of new etc. is defined in /usr/include/c++/4.7/new (which defines _NEW)

There is some discussion of adding new and delete to avr-libc: http://savannah.nongnu.org/patch... and http://lists.nongnu.org/archive/...

Some discussion about adding new and delete support in Arduino: http://code.google.com/p/arduino...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jack_kelly wrote:
It also appears the binary file /usr/lib/gcc/avr/4.7.0/cc1plus includes the text delete[] several times. So I guess gcc-avr 4.7 has support for new, new[], delete and delete[]. Which is nice!
cc1plus is the actual c++ compiler, so you shouldn't assume support just from that. Since the compiler needs to know that new is a special keyword even if there is no library present that supports it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's my "new.h" file which hopefully detects whether the relevant functions are defined and, if not, defines them:

#ifndef _CUSTOM_NEW_H_
#define _CUSTOM_NEW_H_

/* It appears that version 4.7.0 of avr-gcc defined
 * new[] and delete[] so if we detect an earlier version
 * then we must define new[] and delete[] ourselves.
 * This "#define GCC_VERSION" trick from clawson:
 * http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453&start=all&postdays=0&postorder=asc#1002400 */

#define GCC_VERSION (__GNUC__ * 10000 \
                     + __GNUC_MINOR__ * 100 \
                     + __GNUC_PATCHLEVEL__)

#if GCC_VERSION < 40700

/* Arduino 1.0.0 introduced the files
 * hardware/arduino/cores/arduino/new.cpp and new.h
 * the latter of which defines NEW_H.  
 * So if NEW_H is not defined then we should
 * define new and delete. */

#ifndef NEW_H
#define NEW_H
#include 
void * operator new(size_t size);
void operator delete(void * ptr);
#endif /* NEW_H */

// Arduino 1.0.1 doesn't include new[] or delete[]
void * operator new[](size_t size);
void operator delete[](void * ptr);

#endif /* GCC_VERSION */

#endif /* _CUSTOM_NEW_H_ */

let me know if this looks wrong!

Last Edited: Tue. Oct 16, 2012 - 09:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

atomicdog wrote:
cc1plus is the actual c++ compiler, so you shouldn't assume support just from that. Since the compiler needs to know that new is a special keyword even if there is no library present that supports it.

Ah, cool, thanks. That's interesting. So where do you think new[] and delete[] might be defined on my Ubuntu 12.10 system? (new[] and delete[] work out-of-the box on Ubuntu 12.10... the only reason I'm having to define them again is for folks on older systems).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

jack_kelly wrote:
atomicdog wrote:
cc1plus is the actual c++ compiler, so you shouldn't assume support just from that. Since the compiler needs to know that new is a special keyword even if there is no library present that supports it.

Ah, cool, thanks. That's interesting. So where do you think new[] and delete[] might be defined on my Ubuntu 12.10 system? (new[] and delete[] work out-of-the box on Ubuntu 12.10... the only reason I'm having to define them again is for folks on older systems).

I'm not sure where exactly it would be but should be in a library or object file somewhere. I believe looking at the Map file will tell you exactly which library file the function new was pulled in from.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'd imagine they'd most likely be in libc.a so try avr\lib

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pls,i try to install avr-gcc compiler on my window 7 but its not installing what im i to do pls help me

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Broxbourne wrote:
Quote:
You can use Student-Lockroom programming to achieve the result.

Thanks, I didni want to install avr-gcc compiler on my window 7 but not installing what im i to do

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Felix,

This is not the correct thread to diagnose problems about installing avr-gcc. Start a new thread and in it give more detail about what you are trying to do and what does not work. For example where did you get the avr-gcc you are trying to use on Win7 and what happens when you try to install. Do NOT answer in this thread - start a new one with clearer description.

Moderator.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This information is perhaps the best for a C++ starter on AVR Studio. I must say I have skipped a lot of time and energy digging that.

Thank you TFrancuz for sharing that. And thanks for finding me the following error!

"C:\Program Files\Atmel\Atmel Toolchain\AVR8 GCC\Native\3.4.2.876\avr8-gnu-toolchain\bin\avr-g++.exe" -o JBot.elf  I2C.o uart.o hmc5883l.o JBot.o   -Wl,-Map="JBot.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=atmega16a 
		I2C.o:(.rodata._ZTV3I2C[vtable for I2C]+0x4): undefined reference to `__cxa_pure_virtual'
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you want to use new and delete and/or new[] and delete[], you will need to include malloc and free or something similar.  That's usually done on a PC but not so much on a microcontroller. 

 

If you just want to use new and/or new[], I have a simple function that will allocate from the heap.  It may be somewhere in this thread, or I can post it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What the dickens is Student-Lockroom programming? 

madGambol