Hallo, wie kann man das meist global per Makefile definierte F_CPU in einer Assemblerdatei für Berechnungen nutzen? Meist ist es ja per Kommandozeile als -DF_CPU=16000000L oder -DF_CPU=16000000UL definiert. Dumm nur, daß sich daran der Assembler verschluckt, wenn Macros damit rechnen sollen. Nur der Präprozessor versteht das. Gibt es einen Trick, um die Endung L bzw. UL loszuwerden? Im Moment hab ich ein manuell anzupassendes #define. Geht so, ist aber ausbaufähig. Ach ja, es geht um den avr gcc ;-)
Habe gerade das GCC-Manual hoch und runter gewälzt, ob's vielleicht irgendeine local extension gibt, die string processing im Präprozessor machen kann, aber das ist offensichtlich nicht der Fall. Der pragmatischste Weg wäre daher, dass "gas" (der GNU Assembler) die Suffixe von Integerzahlen einfach akzeptiert (aber ignoriert). Das müsste ihm aber jemand beibringen …
Ordentliche Assembler sollten eigentlich zur "Compile/Assembletime" mindestens so viel Arithmetik und mathermatische Funktionen koennen, dass man damit auch zu diesem Zeitpunkt etwas anfangen kann. Assembler fuer DSPs koennen sogar trigonometrische und logarithmische Ausdruecke berechnen, um daraus z.B. Koeffizienten zu bauen. Wenn der Assembler solche "Trivialitaeten" nicht beherrscht, ist das nur traurig. Der gas war und ist scheinbar nur ein Hilfsmittel, um dem Prozesser schlussendlich ein C-Programm unterzuschieben. Auf der Stufe ist er wohl stehengeblieben.
Der Name ist Programm? Es geht nicht um irgendwelche Arithmetik, sondern darum, dass der Suffix "UL" halt nicht Bestandteil der Definition einer Ganzzahl im Assembler ist. Nicht mehr, aber halt auch nicht weniger. Irgendwelche Arithmetik kommt erst danach …
> dass der Suffix "UL" halt nicht Bestandteil > der Definition einer Ganzzahl im Assembler ist Und das ist erst jetzt aufgefallen?
Mein Workaround sieht so aus. Da man so oder so ein paar andere #defines kontrollieren bzw. einstellen muss, ist das OK.
1 | #define F_CPU_T 16000000
|
2 | |
3 | #if F_CPU != F_CPU_T
|
4 | #error F_CPU_T missmatch! Set F_CPU_T == F_CPU here! This is a workaround so far.
|
5 | #error F_CPU_T must be defined as a pure integer without L or UL suffix to work with the assembler
|
6 | #error do not use floating point syntax!
|
7 | #endif
|
Eine direkte Zuweisung per ASM-Direktive geht auch nicht, da meckert der Assembler ebenso!
1 | f_cpu_asm = F_CPU |
Du kannst natürlich F_CPU auch grundsätzlich ohne UL definieren. Bei den üblichen Frequenzen ist sie dann halt automatisch "long", nur nicht "signed". Wer auch immer mit dem Wert rechnet, sollte ihn sowieso tunlichst auf einen passenden Typ casten in C.
Falk B. schrieb: > Meist ist es ja per Kommandozeile als -DF_CPU=16000000L oder > -DF_CPU=16000000UL definiert. Dumm nur, daß sich daran der Assembler > verschluckt, wenn Macros damit rechnen sollen. Ich würde eine Kommandozeile verwenden, die der Assembler auch versteht.
GanzEinfach schrieb: > Ich würde eine Kommandozeile verwenden, die der Assembler auch versteht. Nicht jeder kann und will das. Beim Arduino müßte man da im "Untergrund" was ändern. Geht vielleicht über irgendwelche Config-Files. Beim guten, alten AVR-Studio geht es über manuelle Compilereinstellungen/Modifikationen über die GUI. Kann man machen. Es wäre dennoch wünschensert, wenn es ohne ginge. Geht halt nicht. OK, Thema geklärt.
Falk B. schrieb: > wie kann man das meist global per Makefile definierte F_CPU in einer > Assemblerdatei für Berechnungen nutzen? Meist ist es ja per > Kommandozeile als -DF_CPU=16000000L oder -DF_CPU=16000000UL definiert. Am besten SO garnicht. Die tatsächliche Taktfrequenz ist ja doch vom aktuellen Projekt vorgegeben. Also sollte diese auch in dem zum aktuellen Projekt gehörigen Konfigurationsmodul (sowas wie config.c) stehen und von dort abrufbar sein. Allenfalls auch im zugehörigen config.h. Damit hat man dann die Gewißheit, daß der Wert für die Berechnungen mit den Tatsachen auf der LP übereinstimmt - und nicht von irgend einem Makefile, Kommandozeile etc. Das ist übrigens auch ein oft sträflich mißachteter Grundsatz: Was in einem Projekt relevant ist, hat auch in dessen Quellen zu stehen und nicht ad hoc per Kommandoparameter etc. beigefügt zu sein. W.S.
W.S. schrieb: > Also sollte diese auch in dem zum aktuellen Projekt gehörigen > Konfigurationsmodul (sowas wie config.c) stehen und von dort abrufbar > sein. Das kann aber gut und gern auch ein Makefile sein oder im Falle von Atmel Studio halt deren Projektdatei. Damit ist der Projektzusammenhang genauso hergestellt, das ist also eher kein Argument.
W.S. schrieb: > Damit hat man dann die Gewißheit, daß der Wert für die Berechnungen mit > den Tatsachen auf der LP übereinstimmt - und nicht von irgend einem > Makefile, Kommandozeile etc. Man hat die Gewissheit, dass es mit dem übereinstimmt, was im Headerfile steht, statt in dem, was im Makefile steht. Da sehe ich keinen großen Unterschied, denn der Header passt sich auch nicht auf magische Weise von selber an den verlöteten Quarz an. Beide Files gehören gleichermaßen zum Projekt, und es gibt andere Eigenheiten, die auch über das Makefile konfiguriert werden, wie z.B. welcher µC konkret zum Einsatz kommt und ob bestimmte Module überhaupt gebaut werden sollen. Da kann F_CPU da auch stehen. > Das ist übrigens auch ein oft sträflich mißachteter Grundsatz: Was in > einem Projekt relevant ist, hat auch in dessen Quellen zu stehen und > nicht ad hoc per Kommandoparameter etc. beigefügt zu sein. Ja.
:
Bearbeitet durch User
Beitrag #6516435 wurde von einem Moderator gelöscht.
Ehrlich gesagt, wüßte ich nicht, wozu ich F_CPU in Assemblersourcen überhaupt brauchen sollte. Die UART, Timer usw. kann man doch prima in C initialisieren, da braucht es doch kein umständliches Assembler dafür. Man kann sogar sämtliche Initialisierungen in C schreiben und dann einfach ins Assemblerprogramm springen. Solange das Assemblerprogramm nicht zum Main zurückkehrt, kann man völlig frei alle Assemblertricks machen, z.B. Register als Variablen für Interrupts reservieren usw.
Peter D. schrieb: > Ehrlich gesagt, wüßte ich nicht, wozu ich F_CPU in Assemblersourcen > überhaupt brauchen sollte. Beispielsweise, wenn du in zeitkritischen Teilen halt Delays ausrechnen willst – letztlich das Assembler-Pendant zu <util/delay.h>.
Peter D. schrieb: > Ehrlich gesagt, wüßte ich nicht, wozu ich F_CPU in Assemblersourcen > überhaupt brauchen sollte. Die UART, Timer usw. kann man doch prima in C > initialisieren, da braucht es doch kein umständliches Assembler dafür. Tja, das liegt dann wohl am berühmten Tellerand, über den einige nicht hinaus blicken können oder wollen. Es geht um eine Funktion zur Ansteuerung von intelligen LEDs ala WS2812B & Co. Da braucht man taktgenaues Timing. Masochisten machen das per Inline-Assembler, ich mit einer ASM-Funktion. Beitrag "Re: Frage zu IR-Remote+LED-Strips an AVR"
Jörg W. schrieb: > Peter D. schrieb: >> Ehrlich gesagt, wüßte ich nicht, wozu ich F_CPU in Assemblersourcen >> überhaupt brauchen sollte. > > Beispielsweise, wenn du in zeitkritischen Teilen halt Delays ausrechnen > willst – letztlich das Assembler-Pendant zu <util/delay.h>. Aber das ist ja inline-Assembler, der 16000000ul über der C-Parser liest und offensichtlich versteht. Also streng genommen gar keine Assembler-Source.
Carl D. schrieb: > Aber das ist ja inline-Assembler, sagt wer? Falk schreibt doch, dass er eine separate Assembler-Funktion geschrieben hat, die Delays benötigt und eben nicht als inline-Assembler geschrieben ist. Deshalb kann er auch <util/delay.h> nicht verwenden.
Carl D. schrieb: > Aber das ist ja inline-Assembler, Stimmt übrigens nicht einmal. Ist Inline-C-Code. :-) (Die taktgenaue Verzögerung erledigt der Compiler intern, man muss ihm nur die Anzahl der Takte sagen.)
Jörg W. schrieb: > Carl D. schrieb: >> Aber das ist ja inline-Assembler, > > Stimmt übrigens nicht einmal. Ist Inline-C-Code. :-) (Die taktgenaue > Verzögerung erledigt der Compiler intern, man muss ihm nur die Anzahl > der Takte sagen.) Ok, dann hab ich schon zu lang nicht mehr reingeschaut und ja, ich kenne das Intrinsic für Taktgenaues Zeitverplempern. Aber darüber, das der C-Compiler die 16000000UL verarbeitet, was der sicher kann, sind wir uns einig, oder?
Carl D. schrieb: > Aber darüber, das der C-Compiler die 16000000UL verarbeitet, was der > sicher kann, sind wir uns einig, oder? Ja klar. Allerdings braucht der Compiler das "UL" dafür überhaupt nicht. "long" ist die 16000000 sowieso schon, und in <util/delay.h> wird sie im nächsten Schritt in den äquivalenten double-Wert umgewandelt und mit diesem weiter gerechnet. Die Intention dabei ist, dass man F_CPU dafür auch gleich in einer "natürlicheren" Schreibweise angeben kann, also wenn auf dem Quarz "3.68 MHz" steht, kann man F_CPU zu 3.68E6 definieren und damit arbeiten. Die komplette Rechnung erfolgt ja ohnehin nur im Compiler. 3.68E6 Würde einem natürlich im Assembler noch weniger helfen. ;-) (Allerdings wurde diese Intention später vom Autor von <util/setbaud.h> nicht aufgegriffen; dessen Benutzung setzt eine Ganzzahl-Konstante für F_CPU voraus.)
Beitrag #6517325 wurde vom Autor gelöscht.
Rolf M. schrieb: > Man hat die Gewissheit, dass es mit dem übereinstimmt, was im Headerfile > steht, statt in dem, was im Makefile steht. Da sehe ich keinen großen > Unterschied,... Ich schon. Ich arbeite z.B. eben nicht mit Make. Da entfällt das Makefile quasi ersatzlos. Und wer mit irgend einer IDE arbeitet, hat deren Projektfiles, die wiederum nix mit Makefiles zu tun haben. Wenn du deinen Gedanken zuende denkst, dann kommst du in der totalen Inkompatibilität an: der eine benutzt IDE xyz, der andere IDE abc, der nächste benutzt diesen Compiler, ein andere jenen Compiler und so weiter. Deshalb sage ich: Was dazu gehört, hat in den .c und .h zu stehen. Das ist wenigstens eine Ansage, die für alle Toolchains gelten darf. Wenn man es hingegen so eng sieht, wie du es gerade tust, dann heißt das: "Man benutze nur genau DIE Toolchain, die auch du zu benutzen pflegst", denn nur dann klappt das in allen Dingen. Nun ja, man kann sich auf diesen Standpunkt stellen, aber meiner ist das nicht. W.S.
W.S. schrieb: > ch arbeite z.B. eben nicht mit Make. Da entfällt das Makefile quasi > ersatzlos. Das ist aber rein dein Problem. So gut wie jeder sonst arbeitet mit irgendeinem Buildsystem (gibt ja auch modernere als "make"). > Und wer mit irgend einer IDE arbeitet, hat deren > Projektfiles, die wiederum nix mit Makefiles zu tun haben. Genau daher rührte Falks Ansinnen, denn die IDEs generieren halt aus den Projektdateien genau solche Einstellungen. Damit wiederum gehört das aber inhärent zum Projekt, genauso wie dein config.h (bei mir heißen die übrigens project.h, aber ich tendiere bei solchen Definitionen auch eher zu deiner Variante).
Falk B. schrieb: > Tja, das liegt dann wohl am berühmten Tellerand, über den einige nicht > hinaus blicken können oder wollen. Tja, das ist tatsächlich oft ein Problem. > Es geht um eine Funktion zur Ansteuerung von intelligen LEDs ala WS2812B > & Co. Da braucht man taktgenaues Timing. Nein, dafür braucht man das sehr wahrscheinlich nicht. Es sei denn, dass man mit einer sehr geringen F_CPU hantiert. Unterhalb ca. 3Mhz. Dann wird's wirklich so kritisch, dass es taktgenau sein muss.
Falk B. schrieb: > Es geht um eine Funktion zur Ansteuerung von intelligen LEDs ala WS2812B > & Co. Da braucht man taktgenaues Timing. Einfach mal über den Tellerrand schauen und den C-Code alles ausrechnen und im SRAM ablegen lassen. Den einen Takt mehr für LDS statt LDI kann man ja berücksichtigen.
Jörg W. schrieb: > bei mir heißen die > übrigens project.h Ja Jörg, du weißt doch: Namen sind Schall&Rauch.. und im Prinzip ist es schnurz - solange es eben alles innerhalb des .c und .h Reigens ist. Und bei meinem ohne Makefile hab ich überhaupt kein Problem, läuft alles prächtig. Ich habe allerdings schon so einige Projekte gesehen, wo Leute einiges an Definitionen auf der Kommandozeile dazugegeben hatten - wo ohne dieses der ganze Übersetzungslauf in die Hose geht. Mir ist sogar einer erinnerlich, der nachträglich (!!!) am erzeugten .hex File noch editiert hatte. Irgendwie haben die Leute alle das Bestreben, es anderen so schwer wie nur möglich zu machen. Bellender Egoismus. Noch ne Story: einer meiner Ex-Kollegen meinte mal "wenn ich es über deine Batchdatei bei mir übersetzen lasse, dann geht alles. Aber wenn ich das mit meiner IDE mache, dann übersetzt es nicht...". Laß mal, ist ne Weile her und ich hab mich längst wieder abgeregt. W.S.
Darauf hab ich gewartet, daß die Oberschlauberger ankommen und alles so einfach ist alles mit LINKS! Und nur, um nicht eingestehen zum müssen, das ein F_CPU in einer Assemblerdatei sinnvoll und nötig sein kann. Erbärmlich! Aber macht mal.
Falk B. schrieb: > Darauf hab ich gewartet, daß die Oberschlauberger ankommen War ja nur ein Lösungsvorschlag. Ob Du ihn benutzt, ist mir doch schnurz egal. Kein Grund, sich deswegen aufzuregen.
Peter D. schrieb: > War ja nur ein Lösungsvorschlag. Nein, war es nicht! Es war die reine Arroganz und Bullshit-BINGO! Deine Fähigkeiten und Verdienste hier im Forum und der realen Welt will ich nicht bestreiten, aber es steht auch einem Könner gut zu Gesicht, nicht immer und überall großkotzig und oberlehrerhaft die Leute zu belehren. Du hast nämlich weder das Problem wirklich verstanden noch einen praktikablen Lösungsansatz zubieten und schon GAR NICHT die Details des Problems je in Augenschein genommen! ICH SCHON! Beitrag "Re: Frage zu IR-Remote+LED-Strips an AVR" Und für die Lesefaulen, hier explizit. "Das penible Einhalten der HIGH/LOW Zeiten ist nicht nötig? Dachte ich am Anfang! Nach ersten, schnellen Erfolgen an der LED-Front kam irgendwann die Ernüchterung! Man kann die LEDs zwar ansteuern, aber die Farben stimmen keine Sekunde! Hää? Sind die High/LOW Zeiten wirklich SOOO eng? Scheint so. Also mal fix nen Crashkurs "Wie binde ich Assemblerfunktionen in C ein" und ein paar Stunden später dann die taktgenaue Ansteuerung in Software. Jetzt passen die Farben exakt. Hmmm. Damit ist SPI zumindest raus! Warum? Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560 nicht so ganz schnell ist. D.h. man kann nicht lückenlos hintereinander Daten senden, auch wenn man die Schleife zur Datenausgabe mit nop() taktgenau optimiert. Es bleibt immer eine minimale Lücke von ca. 300ns (5 CPU-Takte), welche nicht unterschritten werden kann." Das geht ganz besonders an den Oberschlaumeier c-hater, dessen Minderwertigkeitskomplexe hier regelmäßig zur Schau gestellt werden! Du tust mir echt leid.
Falk B. schrieb: > Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560 > nicht so ganz schnell ist. D.h. man kann nicht lückenlos hintereinander > Daten senden Daß man für lückenloses Senden eine der UARTs im SPI-Mode benutzt, sollte ja bekannt sein. Die UART hat nämlich den beim halbgaren SPI fehlenden Sendepuffer.
Und warum lässt Du das L bzw. UL nicht komplett weg? Bzw. fügst es doch hinzu, wo es benötigt wird?
:
Bearbeitet durch User
Wilhelm M. schrieb: > Und warum lässt Du das L bzw. UL nicht komplett weg? "Ich" definiere F_CPU nicht, sondern die IDE, sprich AVR-Studio (jaja uralt) oder Arduino. >Bzw. fügst es doch > hinzu, wo es benötigt wird? Man will das im Normalfall nicht überall manuell eintragen, denn das ist aufwändig und fehleranfällig. Also definiert man es einmal zentral in der IDE, welche es dann per Compileroption für die Übersetzung alle Quelldateien nutzt. Man kann es auch in ein zentrales Headerfile schreiben und diese in allen Quelldateien per #include einfügen.
Falk B. schrieb: > Wilhelm M. schrieb: >> Und warum lässt Du das L bzw. UL nicht komplett weg? > > "Ich" definiere F_CPU nicht, sondern die IDE, sprich AVR-Studio (jaja > uralt) oder Arduino. Achsooo ... Arduino >>Bzw. fügst es doch >> hinzu, wo es benötigt wird? > > Man will das im Normalfall nicht überall manuell eintragen, wer hat von manuell gesprochen? ... ich nicht. > denn das ist > aufwändig und fehleranfällig. Also definiert man es einmal zentral in > der IDE, und die komische IDE ergänzt das UL dahinter? > welche es dann per Compileroption für die Übersetzung alle > Quelldateien nutzt. Man kann es auch in ein zentrales Headerfile > schreiben und diese in allen Quelldateien per #include einfügen. Und Du hast bei dieser komischen IDE keinen Einfluss auf das Makefile bzw. die Regeln darin?
Die Freqenz im SRAM ablegen wurde ja schon einmal vorgeschlagen. Würde vielleicht auch eine Konstante, die im C-Code angelegt wird, im Flash als Workaround helfen? Falls der Assembler noch mit der Freqenz zur Compile-Zeit rechnen soll, kann man diese Ergebnisse ja ebenfalls mit in den Flash legen.
Btw: Warum muss dieser Thread eigentlich voll mit „dann mach es ‚richtig‘“-Kommentaren sein?
Falk B. schrieb: > Bei diesem Test musste ich feststellen, daß das SPI vom ATmega 2560 > nicht so ganz schnell ist. D.h. man kann nicht lückenlos hintereinander > Daten senden, auch wenn man die Schleife zur Datenausgabe mit nop() > taktgenau optimiert. Es bleibt immer eine minimale Lücke von ca. 300ns > (5 CPU-Takte), welche nicht unterschritten werden kann." Nur mal rein interessehalber: welche „Schleife zur Datenausgabe“ hast du da wie per nop optimiert, und wann, wie und wo treten da 5 CPU- Takte Pause auf? Oliver
:
Bearbeitet durch User
Wilhelm M. schrieb: >> denn das ist >> aufwändig und fehleranfällig. Also definiert man es einmal zentral in >> der IDE, > > und die komische IDE ergänzt das UL dahinter? Ja. Beide. > Und Du hast bei dieser komischen IDE keinen Einfluss auf das Makefile > bzw. die Regeln darin? Jain. Beim AVR-Studio muss man in den Projektoptionen den generierten Kommandozeilenparameter ändern. Geht, ist halt Aufwand. Und man muss es nach der Änderung der Taktfrequenz in den Projektoption neu machen. Beim Arduino muss man in den Eingeweiden der Konfiguration rumwerkeln, geht vielleicht auch, hab ich aber noch nicht probiert. Ich wollte eine einfache Lösung für jedermann.
Jemand schrieb: > Btw: Warum muss dieser Thread eigentlich voll mit „dann mach es > ‚richtig‘“-Kommentaren sein? Weil die Welt voller Besserwisser ist, die meistens aber keine Bessermacher sind!
Jemand schrieb: > Die Freqenz im SRAM ablegen wurde ja schon einmal vorgeschlagen. Der Vorschlag war aus der Hüfte geschossen und taugt praktisch nicht viel, wenn man mal ein paar RUHIGE Minuten drüber nachdenkt. > Würde > vielleicht auch eine Konstante, die im C-Code angelegt wird, im Flash > als Workaround helfen? Es gibt einen Workaround, ohne Handstände. Einfach ein anderes Symbol ohne UL Endung definieren. Problem solved! > Falls der Assembler noch mit der Freqenz zur Compile-Zeit rechnen soll, Ja logisch! > kann man diese Ergebnisse ja ebenfalls mit in den Flash legen. Braucht keiner! Aber danke für den "Input" . . .
Oliver S. schrieb: > Nur mal rein interessehalber: welche „Schleife zur Datenausgabe“ hast du > da wie per nop optimiert, Die Schleife zum Füttern des SPI. > und wann, wie und wo treten da 5 CPU- Takte > Pause auf? Zwischen den Bytes der SPI-Ausgabe. Das sieht man an den Daten und am Takt. Letztendlich ist sowohl SPI als auch UART im SPI Modus kein sonderlicher Vorteil bei der Ansteuerung von intelligenten LED ala WS2812B & Co. Warum? - Die CPU ist auch mit SPI oder UART zu 100% mit der Datenausgabe beschäftigt, nebenbei kann man keine anderen Dinge erledigen oder Interrupts zulassen, die zerstören das leider sehr knappe Timing einiger diese LEDs, siehe Beitrag. - Die Granularität des Timings ist bei SPI & UART deutlich größer (2 CPU-Takt Auflösung) als bei direkter Generierung per CPU (1 CPU-Takt Auflösung, 3 Takte Mindestbreite) - Bit Banging per CPU kann jedes beliebige IO-Pin nutzen Bestenfalls DMA, wie es die großen 32Bitter (oder die ATX-Megas haben, bringt hier was.
Falk B. schrieb: > Bestenfalls DMA, wie es die großen 32Bitter (oder die ATX-Megas haben, > bringt hier was. Wäre jetzt auch meine Schlussfolgerung gewesen. Andererseits ist DMA gerade mit SPI auch nicht ganz ohne, weil das Select-Handling da oft genug nicht wirklich durch die DMA sinnvoll erledigbar ist. Also doch ein FPGA. :-)) (Wobei: ein kleines FPGA ist tatsächlich billiger als ein ATmega2560.)
:
Bearbeitet durch Moderator
Falk B. schrieb: > Das geht ganz besonders an den Oberschlaumeier c-hater, dessen > Minderwertigkeitskomplexe hier regelmäßig zur Schau gestellt werden! Du > tust mir echt leid. Nun, ich kann WS2812 ansteuern. Und das parallel zu einer 11-Kanal-Audio-Analyse. Siehe Beitrag "Audio Spektrum Analyzer mit ATtiny85" In diesem Artikel findest du übrigens auch einen Link zu einer Analyse (nicht von mir, ich habe sie nur gelesen und angewendet), wie genau es wirklich sein muss bei den WS2812... Nun, mein Ergebnis zeigt wohl überzeugend, dass der Mann mit seiner Untersuchung wohl zu den richtigen Ergebnissen gekommen ist...
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.