Hallo, ich habe bisher nur mit AVR µCs gearbeitet und schaue mir nun die STM32 Serie an. Ich habe das STM32F4Discovery Board hier und teste gerade C++ Code mit Exceptions. Ich habe ein vorhanderes größeres Projekt, welches ursprüchlich für den PC programmiert wurde und Exceptions nutzt, und dies soll nun auf µC portiert werden. Mich interessiert daher wie viel Overhead Exceptions auf den Cortex-M4 µCs haben. Man hört ja teilweise, dass Exceptions kein Laufzeit Overhead haben wenn keine Exception geworfen wird. Hat hier schon jemand Erfahrungen mit Exceptions auf ARM µCs gemacht? Ich habe dazu ein kleines Beispielprojekt angefangen, welches ich angehängt habe (Es ist eine Makefile dabei, allerdings habe ich das ganze unter Windows erstellt, da mich CooCox in den Wahnsinn getrieben hat). Prinzipiell funktionieren die Exceptions allerdings nur bis Optimierungslevel O1. Bei O2, O3 und Os macht der µC sonstwas, da keine LED eingeschaltet wird. Hat hier jemand eine Idee wieso die höheren Optimierungslevel nicht funktionieren? Was mich auch stark gewundert hat ist, dass die Codegröße sich von 1KB auf 60KB mit Exceptions vergrößert hat. Klar Exceptions zu behandeln ist nicht einfach aber so viel Code?
Ich habe gerade noch ein wenig rumprobiert und muss einige meiner Aussagen korrigieren. Tatsächlich funktioniert das Optimierungslevel Os doch, aber O2 und O3 immer noch nicht. Auch hat das Ganze nichts mit den Exceptions zu tun sondern trifft auch auf Code ohne Exceptions zu. Weiter habe ich festgestellt, dass der Code nur dann nicht läuft wenn ich das -O2 und -O3 Flag beim Linken mit angebe. Man kann jetzt zwar mit dem Os Optimierungslevel arbeiten aber trotzdem frage ich mich wieso der Linker verrückt spielt wenn man -O2 oder -O3 übergibt.
Sebastian V. O. schrieb: > nur dann nicht läuft wenn ich das -O2 und -O3 Flag beim Linken mit > angebe Das ist besonders seltsam, denn eigentlich sollte sich der Linker darum gar nicht kümmern. Ruf' den Compiler(treiber) mal mit der Option -v auf, dann erzählt er dir, mit welchen Optionen er die einzelnen Backends startet.
Jörg Wunsch schrieb: > Das ist besonders seltsam, denn eigentlich sollte sich der Linker > darum gar nicht kümmern. Seit LTO tut er das aber. Oliver
LTO hatte ich auch schon im Verdacht aber wenn ich LTO deaktiviere funktioniert Os auch nicht mehr, nur noch O0 und O1. Ich habe nun den Fehler aber weiter eingrenzen können auf den Code der für meine main.cpp (ohne Exceptions) generiert wird. Mit deaktiviertem LTO funktioniert alles wenn ich die main.cpp mit O1 compiliere. Alle höheren Optimierungslevel funktionieren nicht mehr. Es liegt aber definitiv an der main.cpp denn alle anderen .c Dateien kann ich mit O3 oder Os compilieren. Ich habe mal die generierten Assemblies von meiner main.cpp angehängt. Eventuell kann dort jemand einen Fehler entdeckt. Meine Assemblerkenntnisse (erst recht für ARM) sind leider recht beschränkt.
Sebastian V. O. schrieb: > Eventuell kann dort jemand einen Fehler entdeckt. Wenn es erst beim Linken passiert, helfen die dir gar nichts, denn der Witz an LTO ist ja gerade, dass der Maschinencode zur Linkzeit nochmal geändert wird.
Der Test gerade war ohne LTO. Ich hoffe daher, dass der Linker mir nicht nochmal irgendwas kaputt macht. Falls der oben von mir hochgeladene Assemblercode keine groben Auffälligkeiten zeigt kann ich nochmal ein Disassembly von dem gelinkten Zeug machen.
Sebastian V. O. schrieb: > Was mich auch stark gewundert hat > ist, dass die Codegröße sich von 1KB auf 60KB mit Exceptions vergrößert > hat. Klar Exceptions zu behandeln ist nicht einfach aber so viel Code? In den Exceptions gibt es eine "demangle" funktion, welche den funktionsnamen? wiederherstellt, wo die Exception geworfen wurde. Dieser frisst viel Code. Bei NXP mit mitgelieferten C++ wird der glaube ich irgendwie übergangen und damit der Code klein. Gruß Felix
Ich habe hier nochmal Disassemblies vom ganzen Programm angehängt. O1 läuft und O2 nicht. Sind ca. 30 Zeilen unterschiedlich in der main und factorial Funktion. Bis auf die main.cpp wurde mit Os compiliert.
Ok ich habe mich jetzt selbst durch den Assembler Code gearbeitet und festgestellt, dass Zugriffe auf die Register des µC verändert wurden. Das Problem ist in den folgenden Zeilen C-Code:
1 | RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; // Clock für Port D aktivieren |
2 | GPIOD->MODER = 0x55000000; // Pin 12..15 als Ausgang deklarieren |
Ab Optimierungslevel O2 entscheidet sicher Compiler die Zugriffe umzuordnen, sodass zuerst GPIOD->MODER und dann RCC->AHB1ENR geschrieben wird. Offensichtlich scheint das Ganze in dieser Reihenfolge nicht zu funktionieren und die LEDs bleiben dunkel. Durch eine memory barrier konnte ich das Problem lösen, allerdings finde ich dies eine unschöne Lösung. Ich kann mir auch kaum vorstellen, dass ich bisher der einzige bin der auf dieses Problem gestoßen ist.
Hm. Die Register sollten eigentlich volatile sein, und ich war mir bis eben eigentlich ziemlich sicher, daß der Compiler volatile statements nicht frei umsortieren darf. Leider finde ich auf die Schelle nichts dazu iMac-Standard ;) Oliver
OK ich habe nochmal genau in den Assembler Code geguckt. Tatsächlich werden die Daten doch in der korrekten Reihenfolge in den Speicher zurück geschrieben. Ich habe mich durch die Reihenfolge in der die Daten in ein Register geschrieben werden verwirren lassen. Allerdings sind beiden Store Befehle direkt nacheinander. Macht einem hier eventuell das Pipelining einen Strich durch die Rechnung? Oder das Aktivieren des Takts dauern einen kurzen Moment?
wegen der Code-Größe: RTTI deaktivieren? aber mach erst mal die andere Sache zu ende. Bin gespannt obs doch noch klappt. Stephan
Ich habe das Ganze jetzt noch genauer analysiert und in der hexfile rumgepfuscht um NOPs zwischen die beiden Stores einzufügen. Dabei habe ich festgestellt, dass es mindstens zwei NOPs braucht damit die LEDs funktionieren. Warum habe ich immer noch nicht ganz verstanden.
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.