Hi Leute, mal wieder ein kleines Problem. Habe 2 globale Variablen (als volatile deklariert), die ich in der Header zum zweiten *.c-File mit extern volatile .... einbinde. Nun möchte ich die beiden globalen Variablen allerdings gerne dauerhaft in einem Register stehen haben. Mit register uint8_t bla asm("r2"); kann ich dem Compiler ja sagen, dass diese Variable in r2 stehen soll (mehr oder weniger). Nun weiß ich aber nicht, wie ich das mit dem extern machen soll. Mit extern uint8_t bla; heißt es "undefined Reference", mit extern register uint8_t bla; sagt der Compiler "multiple storage classes ....". Was mache ich falsch? Oder geht das überhaupt? Gruß, ERDI - Soft.
Nein, das geht nicht. extern impliziert, daß das Objekt auf jeden Fall im Speicher steht.
> Oder geht das überhaupt?
Die Benutzung einer globalen Registervariablen verlangt, dass du
letztlich in allen Übersetzungsmodulen die gleiche Definition benutzt,
denn nur so weiß der Compiler ja darüber, dass dieses Register für
einen bestimmten Zweck vorbelegt ist.
Damit hast du auch das grundlegende Dilemma solcher Variablen auf dem
Tisch: auch die Bibliotheksmodule müssten letztlich ebenfalls mit
einer (deiner!) derartigen Deklaration compiliert werden, damit sie
nicht auf die Idee kommen, das Register selbst zu nutzen.
Mit einem ,,niedrigen'' Register (also r2, r3, ...) ist die Chance
einer Kollision mit der Bibliothek zwar gering, aber wir (also die
Ersteller der Bibliothek) überwachen nicht, welche Register der
Compiler tatsächlich verwendet. Es könnte gut auch künftige
Bibliotheksmodule geben, die auch die niedrigen Register nehmen
(denkbar ist bspw. dass der Compiler auf sowas zurückgreift, falls mal
jemand eine 64-bit-Gleitkomma-Bibliothek baut).
Schön und gut, aber global kann ich nicht einfach register uint8_t bla; schreiben, da ihm sonst was fehlt. Würde das ja wirklich sehr gerne dem Compiler überlassen. Witzigerweise ist das aber in der Funktion (z.B. in der main) ohne weiteres möglich. Fragen wir mal anders: Gibt es ne Möglichkeit, ne globale Variable in einem Register anzulegen und diese auch anderen Modulen bekannt zu machen, ohne explizit ein Register anzugeben? Bei diesem Projekt benutze ich keine externen Bibliotheken, von dem her sind solche evtl. Kollisionen ausgeschlossen. Aber ich sehe schon, ich muss das doch in Assembler schreiben, sonst komm ich mit der Geschwindigkeit nicht hin (sofern ich nicht noch irgendwo ne Optimierungsmöglichkeit finde). Aber danke schonmal für eure Antworten. Gruß, ERDI - Soft.
Frank Erdrich wrote: > Schön und gut, aber global kann ich nicht einfach register uint8_t > bla; schreiben, da ihm sonst was fehlt. Nein, aber du kannst (und sollst) in jedem Modul register uint8_t bla asm("r2"); reinschreiben. > Witzigerweise ist das aber in der Funktion (z.B. in der main) ohne > weiteres möglich. Das ist aber nur eine andere Variante von "auto"-Variable. Daher stammt das "register"-Schlüsselwort, damit wurde früher dem Compiler ein Hinweis gegeben, diese Variable vorzugsweise in einem Register zu halten. Heute brauchen die Compiler solcherlei Hinweise nicht mehr, damit ist das Schlüsselwort praktisch bedeutungslos. Mit einer Registerbindung hat das nichts zu tun. > Fragen wir mal anders: Gibt es ne Möglichkeit, ne globale Variable > in einem Register anzulegen und diese auch anderen Modulen bekannt > zu machen, ohne explizit ein Register anzugeben? Nein. > Bei diesem Projekt benutze ich keine externen Bibliotheken, von dem > her sind solche evtl. Kollisionen ausgeschlossen. OK, wenn du nicht mal memcpy() & Co benutzt > Aber ich sehe schon, ich muss das doch in Assembler schreiben, sonst > komm ich mit der Geschwindigkeit nicht hin (sofern ich nicht noch > irgendwo ne Optimierungsmöglichkeit finde). Das bringt was, wenn du 20 oder 30 % daneben liegst, aber nicht, wenn du 100 % daneben liegst (es sei denn, es handelt sich nur um eine kurze zeitkritische Schleife oder sowas).
Na ja, es handelt sich um ne (eigentlich) simple PWM für ne RGB-LED. Problem dabei ist, dass es auf Batterie laufen soll, d.h. Taktfrequenz so klein wie möglich. (Bei derzeit 1MHz passt es gerade mit nem Timer-Zyklus von knapp 80µs. bei 100µs fängts schon leicht an zu flimmern. -> 128bit PWM) Der Timerinterrupt macht prinzipiell nicht weiteres, als ne Variable auf max. zu prüfen und evtl. auf 0 setzen und ne 2. Variable wird gesetzt. Der Rest wird in der Main erledigt. Allerdings bläht mir GCC die ISR gewaltig auf. Derzeit hab ich noch etwa 5-6 Taktzyklen Spielraum, um die letzte Option, die Geschwindigkeit, zu implementieren. Prinzipiell könnte ich natürlich auch nen Controller mit Hardware-PWM benutzen, z.B. den tiny25. Nächstes k.O.-Kriterium ist allerdings der Preis. So billig als möglich. Deshalb werde ich das wohl oder übel sowieso in ASM nochmal umsetzen müssen, da der tiny11 (der günstigste) ja nicht vom GCC unterstützt wird. Nu ja, seis drum. Ich werd mal noch ein wenig mit der ISR experimentieren. Vielleicht kann ich da noch ein wenig Code hin auslagern. Oder mir fällt noch was ganz anderes ein. :-)
Naja, für sowas kann sich eine reine Assemblervariante noch lohnen, das ist ja überschaubar. Die 128-bit-PWM ist gut. :-) (Ist das ein "long long long int"?) Billigster (also uralter) Controller und niedriger Stromverbrauch beißen sich natürlich als Forderungen. Du bist dir auch dessen gewahr, dass du den ATtiny11 nur HV-programmieren kannst und dass die Stabilität dieses uralten RC-Oszillators unter aller Sau ist, ja? Eine Frequenzvariation von 1:2 zwischen voller und leerer Batterie dürfte dort normal sein. Vielleicht ja einen etwas moderneren Controller, ihn auch bissel höher takten, dafür aber weitgehend schlafen legen? Da die LED sowieso kräftig Strom zieht, sollte der idle-Strom des Controllers nicht so schwer ins Gewicht fallen. Ich würde wahrscheinlich eher zu einem ATtiny13 greifen. Der verbraucht aktiv bei 1 MHz gerade mal so viel wie ein ATtiny11 idle bei 1 MHz (oder er braucht bei 5 MHz so viel ein ein ATtiny11 bei 1 MHz).
Hast ja Recht, ist ne 7 bit PWM. :-D Die Controllerwahl ist noch nicht getroffen. Usprünglich war der tiny12 geplant. Hab grad eben mal schnell nach Preisen geguckt, und da wäre der tiny11 der günstigste. Hatte aber wohl doch nen Grund, dass ich mir damals den tiny12 ausgesucht habe. Nu ja, die Entscheidung ist nicht dringend, bin ja schon froh, dass ich sanfte Farbübergänge habe. Trotz allem Danke für deine Hilfe.
Naja, der ATtiny12 scheint mir ein ATtiny11 mit ISP zu sein, ansonsten aber genauso alt und entsprechend miserabel in den Daten. Der '13 kostet nur paar Cent mehr und ist deutlich moderner. Der hat ja sogar ein CKLPR, da könntest du den Takt on the fly zum Rechnen hochschrauben.
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.