Hi Leute,
ich versuche 16 bit (unsigned int) Variablen in Register zu speichern.
Es werden keinerlei Bibliotheken oder sonstige eingebunden, die meine
Registerreservierung misachten.
Mit der Registerreservierung klappt das auch ganz gut. Die besagten
Register werden nicht überschrieben, wenn das nicht erwünscht ist.
Allerdings, wenn ich die Variable um bspw. 256 inkrementiere steigt nur
das low Byte um 1 und das high Byte bleibt auf 0 (bzw. dem vorher
definierten Wert)
Kann mir jemand sagen, was ich falsch mache?
So sieht meine deklarierung der Variablen aus:
In Assembler bin ich nicht gerade gut und verstehe auch nicht alles,
aber folgendes habe ich auch probiert: (aber das ist wohl daneben)
1
asm(
2
".DEF byte0 = r6"
3
".DEF byte1 = r7"
4
".EQU registerVariable = 0 ; Definieren der Konstanten"
5
"LDI byte0,LOW(registerVariable) ; Die untersten 8 Bits in R6"
6
"LDI byte1,BYTE1(registerVariable) ; Bits 8 .. 15 in R7"
7
);
Kann mir wer sagen warum das so nicht Funktioniert, bzw was ich daran
ändern muss?
Außerdem habe ich auch versucht ein Array zu speichern. Doch irgendwie
klappt das nur wenn die Array länge maximal 2 ist.
Erst dachte ich es liegt daran, dass der nächsthöhere Index die
nächsthöhere Speicheradresse reserviert und deshalb Probleme entstehen
da eine 16 bit Variable 2 Speicheradressen benötigt.
Doch bei uint8_t erhalte ich den gleichen Fehler ab der Arraylänge 5
Insgesamt will ich 6 Variablen speichern. Bzw. lieber ein Array der
Länge 6.
Ich habe 32 Register zur verfügung und habe auch schon getestet, ob es
Probleme gibt wenn 12 davon reserviert sind.
Es wird eine PWM mit hohen Frequenzen erzeugt.
Wenn die für die ISR notwendigen Variablen in Register gespeichert
werden, können einige Takte eingespart werden.
Die PWM muss in Software gelöst werden, da es sich um 6 verschiedene PWM
mit jeweils unterschiedlichen Frequenzen handelt.
Der µC (ATMega88PA) hat aber nur 3 Timer.
Kaan A. schrieb:> Wenn die für die ISR notwendigen Variablen in Register gespeichert> werden, können einige Takte eingespart werden.
Welche Variablen in Registern gespeichert werden, entscheidet der
Compiler, der das in der Regel ganz gut hinbekommt.
Wenn das nicht ausreicht -- schreib' den Kram in Assembler, statt zu
versuchen, dem Optimierer des Compilers zu helfen.
Rufus Τ. Firefly schrieb:> Welche Variablen in Registern gespeichert werden, entscheidet der> Compiler, der das in der Regel ganz gut hinbekommt.
ich konnte bis jetzt noch nicht beobachten, das eine globale Variable
nur ein Registern vorgehalten wird. In einer ISR werden sie immer aus
dem Ram geladen und wieder Zurückgesichert.
Kaan A. schrieb:> Außerdem habe ich auch versucht ein Array zu speichern. Doch irgendwie> klappt das nur wenn die Array länge maximal 2 ist.Kaan A. schrieb:> Doch bei uint8_t erhalte ich den gleichen Fehler ab der Arraylänge 5
Klingt doch irgendwie logisch:
Das register ist 32 bit gross, kann also maximal ein Array mit 2
uint16_t, oder 4 uint8_t fassen.
Was Du hier versuchst ist allerdings extrem ungewoehnlich.
Hier auf Compiler-bugs zu stossen wuerde mich nicht ueberraschen.
> Allerdings, wenn ich die Variable um bspw. 256 inkrementiere steigt nur> das low Byte um 1 und das high Byte bleibt auf 0 (bzw. dem vorher> definierten Wert)
Zeig mal den Code dazu ! So kann man nur raten.
ZigZeg
Hatten wir da nicht grad einen Thread, in dem seitenweise über Asm v. C
gestritten wurde? Da wär so ein Fall, in dem man mit Assembler besser
dran ist als mit C. Wenn man unbedingt auf AVRs besteht und es mit
Variablen im RAM zu langsam ist.
Eine Kompromiss wäre eine Reservierung der Register in C mit einer ISR
in Assembler. Ist aber trotzdem eine Falle, die irgendwann später mal
zuschnappen kann.
Kaan A. schrieb:> Es wird eine PWM mit hohen Frequenzen erzeugt.> Wenn die für die ISR notwendigen Variablen in Register gespeichert> werden, können einige Takte eingespart werden.> Die PWM muss in Software gelöst werden, da es sich um 6 verschiedene PWM> mit jeweils unterschiedlichen Frequenzen handelt.> Der µC (ATMega88PA) hat aber nur 3 Timer.
Will Du eine einfache Lösung? Nimm einen Mikrocontroller, der genügend
Ressourcen für Deinen Anwedungsfall hat, ohne dass man ihn "bis auf
Anschlag" ausreizen muss.
Ich gehe mal nicht davon aus, dass Du Hunderttausende von Geräten
produzieren willst, so wie es etwa in der Automobilindustrie der Fall
ist. Da schaut man auf jeden Cent, den man sparen kann, und bei solchen
Stückzahlen ist es auch sinnvoll. Ansonsten eher nicht.
Wer an der falschen Stelle spart, zahlt drauf.
Kaan A. schrieb:> Hi Leute,> ich versuche 16 bit (unsigned int) Variablen in Register zu speichern.> Es werden keinerlei Bibliotheken oder sonstige eingebunden, die meine> Registerreservierung misachten.
Gefährlich.
Der Compiler braucht nur einen Funktionsaufruf auf zb eine
Multiplikationsroutine einbauen, die genau dieses Register benutzt und
du bist angeschmiert.
Uwe Bonnes schrieb:> Auf welchem Mikroprozessor?
ATMega88PA. Habe ich ja vorhin schon erwähnt. Sry habe das bei der
Fragestellung vergessen.
Kai S. schrieb:> Das register ist 32 bit gross, kann also maximal ein Array mit 2> uint16_t, oder 4 uint8_t fassen.
Nein es sind 32 8 bit Register.
Habe mal den Code angehängt.
Bitte nicht die genaue Funktion hinterfragen oder so. Die Diskussion
hatte ich schon in einem anderen Thread der jetzt 62 Beiträge lang ist
:/
Beitrag "alternative für for-schleife zeitmangel"
Ja, die Möglichkeit, die ISR im Notfall in Assembler zu schreiben, haben
wir auch in erwägung gezogen.
Nur hab ich halt kaum Erfahrung in Assembler.
Bin ja auch ers seid 6 Wochen am C Programmieren.
Kaan A. schrieb:> Die PWM muss in Software gelöst werden, da es sich um 6 verschiedene PWM> mit jeweils unterschiedlichen Frequenzen handelt.
Wenn Tastverhältnis und Frequenz sich ändern sollen, wirst Du mit
SW-PWM keinen Blumentopf gewinnen. Da kannst Du Dich noch so lange mit
Assembler abstrampeln und wütend auf den Tisch hauen.
Kaan A. schrieb:> Beitrag "alternative für for-schleife zeitmangel"
Da ist ja schon alles gesagt worden.
Kaan A. schrieb:> Nur hab ich halt kaum Erfahrung in Assembler.> Bin ja auch ers seid 6 Wochen am C Programmieren.
Dann sollte man natürlich auf die Ratschläge von Experten pfeifen.
Kaan A. schrieb:> Allerdings, wenn ich die Variable um bspw. 256 inkrementiere steigt nur> das low Byte um 1 und das high Byte bleibt auf 0 (bzw. dem vorher> definierten Wert)
Ich nehme an es geht z.B. um die folgenden Zeilen:
(ich nehme an das uint8_t in pwm_currentphase_Mag0 ist ein Fehelr ?)
Vermutlich ist nur Deine Interpretation von highbyte und lowbyte
vertauscht ?
Der Compiler ist naemlich frei darin zu entscheiden, in welches Register
er das highbyte und in welches er lowbyte ablegt.
Wie hast Du denn geschlossen, dass die Addition das 'falsche' byte
incrementiert ? Debugger ?
Ich wuerde mir uebrigens mal anschauen, was der Compiler so an Asm code
produziert. Koennte auch ein guter Einstieg sein, es selbst in Asm zu
versuchen.
ZigZeg
Kai S. schrieb:> Ich wuerde mir uebrigens mal anschauen, was der Compiler so an Asm code> produziert. Koennte auch ein guter Einstieg sein, es selbst in Asm zu> versuchen.
Es wird wohl eher ein guter Einsteig in die Erkenntnis sein, daß das
alles nichts bringt, und die Aufgabenstellung mit dem Prozessor nicht
lösbar ist.
In Zeiten, in denen ein ArduinoDue oder ein RasPi nicht mehr als zwei
Kästen Bier kosten, gilt erst recht der alte Spruch: Wende nie Gewalt
an. Nimm gleich den großen Hammer...
Oliver
Peter Dannegger schrieb:> Wenn Tastverhältnis und Frequenz sich ändern sollen, wirst Du mit> SW-PWM keinen Blumentopf gewinnen.
Das habe ich bereits gemerkt, ja. Doch so lautet nunmal meine Aufgabe..
Ich versuch enurnoch das Beste daraus zu ziehen.
Einen µC mit 6 Timern habe ich bereits vorgeschlagen.
Peter Dannegger schrieb:> Dann sollte man natürlich auf die Ratschläge von Experten pfeifen.
Auf Ratschläge pfeife ich nicht. Jeder Ratschlag, soweit er nett gemeint
ist, ist mir willkommen. Aber ich kann eben meinen Vorgaben nicht
widersprechen. Das ganze hat ja auch einen Lerneffekt.
@Kai
Ja, es geht um die Zeilen. Insbesondere um die Deklaration.
Kai S. schrieb:> Wie hast Du denn geschlossen, dass die Addition das 'falsche' byte> incrementiert ? Debugger ?
Ich hab mir im Debugger die Registerwerte nach jedem Interrupt
angeschaut und da ich ja weiß, um welchen Wert ich inkrementiere, weiß
ich auch welcher Wert als nächstes drin stehen muss.
> Vermutlich ist nur Deine Interpretation von highbyte und lowbyte> vertauscht ?> Der Compiler ist naemlich frei darin zu entscheiden, in welches Register> er das highbyte und in welches er lowbyte ablegt.
Hmm jetzt wo du es sagst habe ich das Ganze nochmal mit verschiedenen
Inkrementwerten angeschaut. Und anscheinend hast du recht. Danke dir :D
Also gehe ich davon aus, dass meine Deklaration der Registervariablen so
in ordnung ist.
Kann man mir evtl noch erklären, wie ich das als Array verwirkliche?
Ich würde nämlich gerne ein Makro schreiben und diesem jeweils die Nr
der zu bearbeitenden PWM übergeben, um Code zu sparen und dass es etwas
übersichtlicher wird.
Die asm des Compilers werde ich wohl demnächst auch unter die Lupe
nehmen müssen.
Kaan A. schrieb:> Aber ich kann eben meinen Vorgaben nicht widersprechen.
Welche Vorgaben? Wer macht die?
Sofern Vorgaben nicht sinnvoll sind, dann kann man nicht nur, sondern
man MUSS ihnen sogar widersprechen!
Ansonsten betreibt man nämlich Softwareentwicklung auf dem Niveau von
"Konzern macht Outsourcing nach Indien": Die sagen dort zu allem Ja und
Amen. Selbst dann, wenn sich Anforderungen gegenseitig widersprechen,
oder einfach nicht sinnvoll sind. Weil sie es nicht verstehen, die Dinge
zu hinterfragen - das gehört nicht zu ihrer erlernten Kultur. Am Ende
liefern sie dann einen Murks ab, der nicht funktioniert. Been there,
done that.
Kaan A. schrieb:> Kann man mir evtl noch erklären, wie ich das als Array verwirkliche?> Ich würde nämlich gerne ein Makro schreiben und diesem jeweils die Nr> der zu bearbeitenden PWM übergeben, um Code zu sparen und dass es etwas> übersichtlicher wird.
Seit wann spart man mit Makros Code?
Falls Du damit meinst, Quellcode respektive Tipparbeit zu sparen:
Wenn Du sauber definierte und modulare Funktionen hast, in denen
sinnvolle Parameter übergeben werden, ist ein Rumgepfusche mit der
Makro-Textersetzung in 99% aller Fälle weder nötig noch sinnvoll.
Und dass man damit "Code sparen kann" im erzeugten Kompilat, den Beweis
dafür will ich erst mal sehen.
Repeat after me:
In C, macros are not needed for code efficiency.
Quelle: http://users.ece.cmu.edu/~eno/coding/CCodingStandard.html#macros> Die asm des Compilers werde ich wohl demnächst auch unter die Lupe> nehmen müssen.
Nein. Du gehst in ein Geschäft Deiner Wahl, kaufst einen ausreichend
dimensionierten Mikrocontroller, und löst das Problem somit elegant und
professionell.
Du hast jetzt die Erkenntnis gewonnen, dass die vorgesehene Hardware für
die zu bewältigende Aufgabe nicht geeignet ist, da sie zu schwach
dimensioniert ist. Das ist ein vollkommen valides Ergebnis!
Der richtige Weg ist nun, die Hardware entsprechend den Anforderungen an
das Gesamtsystem zu modifizieren. Alles andere ist Rumgepfusche und
Rumgemurkse - das willst Du nicht.
Zitat aus dem anderen Thread:
Kaan A. schrieb:> Weil wir in der Forschung tätig sind und dies die Vorgaben von meinem> "Ausbilder" sind. Wie gesagt 500 Hz sind das Minimum, da in dem Bereich> bis 1 kHz gearbeitet wird. Aber da das zu entwickelnde Board flexibel> und für die zukunftsorientiert (wenn man mit der Frequenz hoch gehen> möchte) einsetzbar sein soll
Bingo. Die Hardware reicht nicht aus, um diese Vorgabe zu erfüllen.
Fertig, aus, Ende.
Kaan A. schrieb:> Kann man mir evtl noch erklären, wie ich das als Array verwirkliche?
Vermutlich wird das vom Compiler nicht unterstützt werden.
Begründung: es gibt in Assembler (zumindest für die mir bekannten
Architekturen) keine Möglichkeit, über einen Index auf Register zu zu
greifen. Für jeden Register Zugriff muss eine andere Instruktion benutzt
werden. D.h. Für ein Array mit x Elementen müsste der Compiler eine
Fallunterscheidung mit x Fällen generieren.
Ich bin eher erstaunt, dass das mit einem Array von uint8_t[4] zu
funktionieren scheint?
Ohnehin ist das, was du mit dem Compiler machst, weit weg von dem, für
das er gemacht wurde. Das scheint Dir nicht bewusst zu sein.
Ich würde mich also eher freuen, dass das, was Du hier machst
funktioniert. Stattdessen willst du noch mehr!
ZigZig
Kai S. schrieb:> Begründung: es gibt in Assembler (zumindest für die mir bekannten> Architekturen) keine Möglichkeit, über einen Index auf Register zu zu> greifen.
Doch, bei AVRs geht das, wenn auch nicht bei allen. Musst nur auf die
Datenadressen 0-31 zugreifen. Bringt allerdings in diesem Zusammenhang
nichts, weil nicht schneller als RAM.
Kaan A. schrieb:> Es werden keinerlei Bibliotheken oder sonstige eingebunden, die meine> Registerreservierung misachten.
1
-ffixed-<reg>
ist dafür gedacht, dem Compiler ein oder mehrere Register zum Tabu zu
erklären. Damit kann man eine Menge Unfug treiben.
GEFÄHRLICH ist das allerdings in jedem Fall. Man muß dann z.B. das
Linken der libgcc (weißt Du, was die macht?) unterbinden bzw. die darin
enthaltenen Routinen selbst bereitstellen.
Als Anfänger sollte man wohl lieber die Finger davon lassen.
Jaja, der akademische Unsinn mal wieder . . .
Warum einfach, wenn es auch umständlich geht.
Was kostet die Arbeitsstunde eines Studenten/wissenschaftlichen
Mitarbeiters?
Was kostet ein uC mit 6 getrennten PWMs in Hardware?
Welcher akademische Wert wird mit einer Softwarelösung geschaffen?
Hmm . . .
Noch eine halbe Softwarelösung.
Beitrag "Re: alternative für for-schleife zeitmangel"
Man nehme einen ATXmega und DMA! Dabei muss man nur die Tabelle
einmal per Software füllen und diese mit einem Timer und DMA auf einen
PORT ausgeben. CPU-Last 0%.