hallo, in meinem code bin ich wohl in das "static initialization order fiasco" gestolpert. ganz gemeine sache dies :( ok, ich weiß immer noch nicht genau, warum, aber sei's erstmal drum. die lösungen dazu in der c++-faq sehen dazu vor, eine statische variable in einer function zu halten. soweit so gut. nun beschwert sich aber der avr-c++ mit undefinierten referenzen auf "__cxa_guard_acquire" bzw. "__cxa_guard_release". im moment habe ich diese erst einmal leer definiert. ist das korrekt so? oder muss dort etwas getan werden, wenn ja, was? falls noch zeit ist: was bedeuten diese funktionen, im netz wird man da nicht gerade mit info's überhäuft. vielen dank, schönen sonntag, bye kosmo
Ist zwar sicherlich der falsche Prozessor, aber darauf kommt's nicht an: http://www.codesourcery.com/cxx-abi/abi.html, Sektion 3.3.2. (google groups, hit #2)
oha. den link habe ich nicht gefunden, sorry. danke vielmals.
hm, das problem scheint wo anders zu liegen. wird jetzt OT: wie legt man globale objekte in einem programm in der bootloader-area an? bisher habe ich immer static Objecttype __object; und gut ist. im normalen flash funktioniert das auch, aber seit ich in der bootloader-area arbeite, funktioniert nichts mehr. verschieben tue ich den ganzen code mittels --section-start=.text=0xXXXXX hat jemand einen vorschlag und kann mir helfen? mir gehen nach mehreren stunden leider langsam die ideen aus :( thx!
einfaches beispiel: extern "C" { #include <avr/io.h> } class A { public: A(){ /* Set the baud rate */ UBRR0H = (unsigned char) (51>>8); UBRR0L = (unsigned char) 51; /* Enable UART receiver and transmitter */ UCSR0B = ( ( 1 << RXEN0 ) | ( 1 << TXEN0 ) ); /* Set frame format: 8N1 */ UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); /* send .. something */ while ( !(UCSR0A & (1<<UDRE0)) ); UDR0 = 'D'; while ( !(UCSR0A & (1<<UDRE0)) ); UDR0 = '\r'; } }; mache ich static A __a; und in der main nichts, passiert auch nichts, die kiste hängt. kein globales, sondern einlokales objekt in der main ala int main(int argc, char** args) { A __a; return 0; } und es funktioniert :(
Bitte benutze keine Bezeichner, die mit zwei Unterstrichen beginnen. Das wird zwar an deinem Problem jetzt nichts ändern, aber diese Bezeichner sind für Compiler und Bibliothek reserviert. > extern "C" { > #include <avr/io.h> > } Erstens steht auch bei C++ das # immer in Spalte 1, zweitens sollte das extern "C" nicht nötig sein. Wenn doch, dann schreibe bitte einen detaillierten Bugreport. Alle avr-libc-Headerdateien sollte mittlerweile C++-sicher sein.
keine zwei unterstriche, ok. include in erster spalte, ok. beim "extern" richte ich mich nach der avr-libc- doku. da steht zwar drin, das wird behoben (in der art jdf.), aber gut, nun weiß ich bescheid. bitte den anderen thread dann einfach ignorieren, hat sich zeitlich leider überschnitten. bug-report mache ich nach einholen einer weiteren meinung. danke.
> beim "extern" richte ich mich nach der avr-libc- doku. da steht zwar > drin, das wird behoben (in der art jdf.), aber gut, nun weiß ich > bescheid. Hmm, das müsste man wohl mal überarbeiten... Bezüglich des Präprozessors: # include ... ist OK. Nur das # muss ganz vorn stehen (so will's der Standard).
hallo, ich habe nun das obige beispiel noch einmal vereinfacht, indem statt usart-ausgabe verschiedene pins gestzt werden. im detail so: #include <avr/io.h> class A { public: A(){ PORTE |= (1 << 7); } }; A test_a; int main(int argc, char** args) { PORTE |= (1 << 2); while(1); return 0; } auf Port E kann ich an dem Board nach außen geführte Pins auf High setzen. das problem ist unverändert. im bootloader ausgeführt, bleiben beide Pins (durch 7 bzw. 2 angesprochen) auf null. meine konfiguration: at90can128, fusebits auf D8, text-section entsprechend nach 1E000 verschoben. gcc version 4.1.1. @Jörg: was würde Dir noch für den bug-report fehlen? habe derartiges noch nicht so oft getan.
Hallo Joe, ich hatte auch schon einmal ein ähnliches Problem. Leider kann ich mich jetzt nicht mehr an die Details erinnern, aber soweit ich weiß, war es bei mir ein Fehler im Makefile. Wenn Du willst, kannst Du Dein Makefile mal hier reinstellen. Vielleicht erinnere ich mich wieder an Details, wenn ich Dein Makefile einsehe. Karsten
> im bootloader ausgeführt, bleiben beide > Pins (durch 7 bzw. 2 angesprochen) auf null. Was erst einmal nicht verwundert, da du DDRE nicht auf Ausgang setzt. ;-) Im Ernst: ich würde das gern mal selbst nachvollziehen. Schreib mir bitte nochmal die genauen Compiler-Kommandozeilen auf. Zumindest ein kurzer Blick zeigt mir erst einmal keine Auffälligkeiten, der statische Konstruktor ist auch im Bootloader- Fall vorhanden. Ob er wirklich gerufen wird, ist im Disassembler schwer zu erkennen.
jörg, mit dem DDRE hast du wie immer recht :) anbei das Makefile, falls notwendig. die compileraufrufe im einzelnen: /localapp/cross-gcc/avr/bin/avr-c++ -c -mmcu=at90can128 -I. -D GCC_MEGA_AVR -I. -I../../Source/include -I../Common/include -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wsign-compare -Waggregate-return -Wunused -Wa,-adhlns=a_test.lst -fno-exceptions a_test.cpp -o a_test.o /localapp/cross-gcc/avr/bin/avr-c++ -mmcu=at90can128 -I. -D GCC_MEGA_AVR -I. -I../../Source/include -I../Common/include -g -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wsign-compare -Waggregate-return -Wunused -Wa,-adhlns=a_test.o -fno-exceptions a_test.o --output a_test.elf -Wl,-Map=a_test.map,--cref,--section-start=.text=0x1E000 /localapp/cross-gcc/avr/bin/avr-objcopy -O ihex -R .eeprom a_test.elf a_test.hex das wars (das eeprom-geplapper des makefiles spare ich aus, weil nicht gebraucht, ebenso die warnungen) nach dem hinweis von karsten werde ich noch ein wenig mit den compiler-options probieren.
ich kann es etwas weiter eingrenzen. die meisten compiler-options raus -c -mmcu=at90can128 -I. -I. -g -O0 -Wall -Wextra -Wshadow -Wpointer-arith -Wcast-align -Wsign-compare -Waggregate-return -Wunused -fno-exceptions a_test.cpp -o a_test.o den linker nur noch -Wl,-Map=a_test.map,--cref,--section-start=.text=0x1F000 tun und ende. wie schon zu sehen, auch mal eine andere bootloader-size ausprobiert, man weiß ja nie. und im Konstruktor der globalen Klasse eine while-true angefügt, um ein mögliches reset und löschen der Pins zu verhindern. leider alles ohne veränderung bisher.
Ich habe das via Simulation und Einzelschritt mal runterbrechen können. Das Problem ist im GCC bzw. in dessen libgcc.S. Damit kannst du den Bugreport für den GCC schreiben (http://gcc.gnu.org/ , dort zum Bugzilla weitergehen). Ich würde dir empfehlen, dich bei avr-gcc-list at nongnu.org anzumelden und das dort ebenfalls noch einmal zum Besten zu geben. Wir haben jetzt ja fast einen C++- Maintainer ;-), Rolf Magnus (auch hier gelegentlich aktiv) wollte sich dieser Dinge annehmen. Folgendes Stück aus libgcc.S wird zum Verhängnis (du darfst das im Bugreport zitieren): #ifdef L_ctors .section .init6,"ax",@progbits .global __do_global_ctors __do_global_ctors: ldi r17, hi8(__ctors_start) ldi r28, lo8(__ctors_end) ldi r29, hi8(__ctors_end) rjmp .do_global_ctors_start .do_global_ctors_loop: sbiw r28, 2 mov_h r31, r29 mov_l r30, r28 XCALL _tablejump_ .do_global_ctors_start: cpi r28, lo8(__ctors_start) cpc r29, r17 brne .do_global_ctors_loop #endif /* L_ctors */ Die Initialisierung von r28/r29 funktioniert nur für Daten, die sich unterhalb 64 KiB befinden, da der 16 bits überschreitende Teil der Adressen (__ctors_start, __ctors_end) nicht beachtet wird. Damit werden r30/r31 nicht mit den eigentlichen Daten für den Konstruktor geladen sondern mit Daten, die 64 KiB weiter unten stehen, also letztlich mit 0xffff. Der Code bei _tablejump_ springt dann die Adresse an, die von dieser Stelle geladen wird... Damit ist das Fiasko komplett. Fazit: C++ im Bootloader ist derzeit nur für AVRs <= 64 KiB ROM möglich, wenn statische Konstruktoren oder Destruktoren im Spiel sind.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.