Bin Einsteiger in AVR GCC (sonst arbeite ich mit ASM) und habe heute das erste C Programm mit AVR GCC geschrieben. Hatte keine Probleme mit dem Compiler, läuft alles super, aaaaber im Build-Fenster steht: 2316 bytes (7.1% full) (.text + .data + .bootloader) Das kann doch wohl nicht sein, dass diese popelige Progrämmle (siehe unten)bereits 7% von einem ATmega32 auffrist. Kann mir da einer weiterhelfen, was ich hier definitiv falsch gemacht habe. Beste Grüße Manni /************************************************************** Test Routine for fast atan2 function **************************************************************/ #include "main.h" double fast_atan2 (double y, double x); #define PIBY2 M_PI / 2 int main( void ) { double u, x, y, z1, z2; x = 1.25678; y = 1.25678; z1 = atan2 (y, x); z2 = fast_atan2 (y, x); } /************************************************************** Here's another atan2 function, based on a 50-year old atan approximation due to Hastings. It has an |error| < 0.005, and is 3-5x faster than atan2. **************************************************************/ double fast_atan2 (double y, double x) { double atan; double z; if (x == 0.0f) { if (y > 0.0) return PIBY2; if (y == 0.0) return 0.0; return -PIBY2; } z = y/x; if (fabs(z) < 1.0f) { atan = z/(1.0 + 0.28*z*z); if (x < 0.0) { if (y < 0.0) return atan - M_PI; return atan + M_PI; } } else { atan = PIBY2 - z/(z*z + 0.28); if (y < 0.0) return atan - M_PI; } return atan; }
Manni wrote: > Das kann doch wohl nicht sein, dass diese popelige Progrämmle (siehe > unten)bereits 7% von einem ATmega32 auffrist. Na dann möchte ich Dich mal sehen, wie Du Dir in Assembler einen mit Floating Point Zahlen abbrichst. Wenn Du auf weniger Code kommst und auch alles richtig rechnet, dann kann ich nur sagen "Hut ab !". Peter
Hallo Peter, ja das ist ja der Grund, warum ich für diesen Fall den Assembler verlassen hab, weil ich mir diesen Hut nicht anziehen will (hab' gelegentlich auch noch was anderes zu tun). Aber erklären kann ich mir noch nicht. Wenn ich den Disassembler einschalte/ansehe, sind nur ca. 5% des Codes auf das Programm bezogen. Nach der Anweisung: return atan folgen noch 95% code mit der bemerkung: -----No Source------------- Hier unten eine kurze Kopie. Habe ich etwa die ganze libm.a miteingebunden ? 57: return atan; +000001DB: 8589 LDD R24,Y+9 Load indirect with displacement +000001DC: 859A LDD R25,Y+10 Load indirect with displacement +000001DD: 85AB LDD R26,Y+11 Load indirect with displacement +000001DE: 85BC LDD R27,Y+12 Load indirect with displacement +000001DF: 8B89 STD Y+17,R24 Store indirect with displacement +000001E0: 8B9A STD Y+18,R25 Store indirect with displacement +000001E1: 8BAB STD Y+19,R26 Store indirect with displacement +000001E2: 8BBC STD Y+20,R27 Store indirect with displacement 58: } +000001E3: 8969 LDD R22,Y+17 Load indirect with displacement +000001E4: 897A LDD R23,Y+18 Load indirect with displacement +000001E5: 898B LDD R24,Y+19 Load indirect with displacement +000001E6: 899C LDD R25,Y+20 Load indirect with displacement +000001E7: 9664 ADIW R28,0x14 Add immediate to word +000001E8: B60F IN R0,0x3F In from I/O location +000001E9: 94F8 CLI Global Interrupt Disable +000001EA: BFDE OUT 0x3E,R29 Out to I/O location +000001EB: BE0F OUT 0x3F,R0 Out to I/O location +000001EC: BFCD OUT 0x3D,R28 Out to I/O location +000001ED: 91DF POP R29 Pop register from stack +000001EE: 91CF POP R28 Pop register from stack +000001EF: 9508 RET Subroutine return +000001F0: 5850 SUBI R21,0x80 Subtract immediate +000001F1: 2E19 MOV R1,R25 Copy register +000001F2: D103 RCALL PC+0x0104 Relative call subroutine +000001F3: D001 RCALL PC+0x0002 Relative call subroutine +000001F4: C0E6 RJMP PC+0x00E7 Relative jump +000001F5: 17BA CP R27,R26 Compare +000001F6: 0762 CPC R22,R18 Compare with carry +000001F7: 0773 CPC R23,R19 Compare with carry +000001F8: 0784 CPC R24,R20 Compare with carry +000001F9: 0795 CPC R25,R21 Compare with carry +000001FA: F1B1 BREQ PC+0x37 Branch if equal +000001FB: F488 BRCC PC+0x12 Branch if carry cleared +000001FC: F40E BRTC PC+0x02 Branch if T flag cleared +000001FD: 9410 COM R1 One's complement +000001FE: 2E0B MOV R0,R27 Copy register +000001FF: 2FBA MOV R27,R26 Copy register +00000200: 2DA0 MOV R26,R0 Copy register +00000201: 2E06 MOV R0,R22 Copy register ---- No Source ------------------------------------------------------------------------ ------------ +00000202: 2F62 MOV R22,R18 Copy register +00000203: 2D20 und hier kommen noch ca. 1800 bytes.
OK, verstehe ich ! Dann muss ich mal weiter forschen, wie ich das atan2 Problem anders lösen lösen kann. Hab's mittlerweile auch im Disassembler gesehen, eben die Gleitkommabibliothek. Danke Dir !
@Jörg Hab's gerade erst bemerkt: ist DL8DTL dein AFU Kennzeichen ? Würde mich wundern, da am Ende ein Zeichen zuviel.
Wie Peter schon schrieb, wird es dir sicher schwer fallen, Gleitkomma- arithmetik in anderer Form mit wesentlich weniger Speicherverbrauch zu implementieren. Eventuell beschreibst du ja lieber mal dein Problem. Ja, DL8DTL ist das Afu-Rufzeichen. Suffixe mit 1 Ziffer und 3 Buchstaben sind doch durchaus gängig, und waren praktisch die einzigen, die sie uns seinerzeit hier in Neufünfland übergeholfen haben, als wir unsere Y2-Calls abgeben mussten (obwohl die BRD ja nach wie vor auf dem Block Y2-Y9 gluckt -- man hätte sie also auch ,,biologisch ausklingen'' lassen können, wenn man gewollt hätte). Suffixe mit nur zwei Buchstaben oder das Rückerlangen alter DM-Calls wurden erst später möglich. Aber letzteres hatte ich (gerade so) ohnehin nicht mehr besessen, und außerdem hätte es noch einen Wechsel des Calls bedeutet, das macht man nicht freiwillig.
Wenn du jetzt noch deine Fliesskommazahlen über uart per printf ausgibst, kommt nochmals ein dicker Speicherhappen dazu. Das war es dann aber auch. Alles, was du dann noch anstellst, wird die Codegröße ungefähr linear anwachsen lassen, und das auch im erwarteten Rahmen. Da ist noch viel Platz im Flash. Das Compilerflag -Os ist aber immer hilfreich. Oliver
@Oliver: na das hat's ja ordentlich gebracht: ca. 47% weniger Programm-Bytes. Habe aber noch nicht ausprobiert, was der Einfluß auf's Timing ist: Zitat User Manual: "... at the possible expense of code execution speed". @Jörg: Danke dir für die Eräuterungen zu deinem Rufzeichen. Bin ein bischen aus der Übung gekommen weil mein 3-Element Beam nach dem Umzug in 2004 noch immer im Keller liegt. Diesen Sommer kommt sie aber wieder auf's Dach. Gruß DK4GL
"... at the possible expense of code execution speed". Das mag im PC-Umfeld, im Vergleich zu der Optimierungsstufe -O3 stimmen. Das schöne bei den Atmels ist, daß ein Befehl nur einen Takt dauert (die allermeisten jedenfalls). Weniger Befehle => schneller. Und zwar fast so viel, wie der Code kleiner wird. Oliver
Naja, -O3 macht zuweilen durch loop unrolling, function inlining und solche Dinge wirklich ein paar Takte gut trotz größeren Codes, aber in der Tendenz stimmt es schon: beim AVR ist kleinerer Code oftmals auch schneller.
@Jörg: "Eventuell beschreibst du ja lieber mal dein Problem." Anbei das "Problem", was aber eigentlich gar keines ist, bzw. sein sollte. Nix aufregendes mit einer Abtastrate von ca. 1 Hz. Phasenauflösung soll so bei einem Grad liegen. Da kann man noch vieles nebenbei rechnen lassen. Lookup-Table wäre auch möglich mit 2*360 10bit Werten (also 720 bytes). Hab ich aber noch nicht weiter verfolgt. Vielleicht ist das ja die einfachste Lösung. "-O3": Bei allen verfügbaren compiler flags -O1 bis -Os kommt ungefähr immer die gleiche Codelänge raus, d.h. 40-50% weniger als bei -O0.
Ja, Lookup-Tabelle oder stützpunktbasierte Interpolation, das Ganze möglichst im Integer-Bereich. Andererseits ist die Frequenz wahrscheinlich wirklich gering genug, dass du alle Zeit der Welt zum Rechnen hast, und Programmspeicher hast du auch noch reichlich. Wenn's die Entwicklung des Prototypen schneller macht, ist also die Gleitkommarechnung vielleicht gar nicht so fehl am Platz. Wenn sie's am Ende ohne Einschränkung tut, warum solltest du sie nicht auch einfach benutzen? Schließlich wirst du von Atmel kein Geld zurück bekommen, wenn du Teile des ROMs nicht benutzt. ;-)
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.