Forum: Compiler & IDEs uint16 Variable in Hardwareregister speichern


von Kaan A. (deranfaenger)


Lesenswert?

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:
1
register volatile uint16_t registerVariable asm ("r6");
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
1
register volatile uint16_t registerArray[3] asm ("r6");
2
register volatile uint8_t registerArray2[5] asm ("r6");
Hier die Fehlermeldung:
1
data type of 'registerArray' isn't suitable for a register
2
data type of 'registerArray2' isn't suitable for a register
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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Kaan A. schrieb:
> ich versuche 16 bit (unsigned int) Variablen in Register zu speichern.

Warum?

von Kaan A. (deranfaenger)


Lesenswert?

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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Uwe Bonnes (Gast)


Lesenswert?

Kaan A. schrieb:
> Hi Leute,
> ich versuche 16 bit (unsigned int) Variablen in Register zu speichern.

Auf welchem Mikroprozessor?

von Kai S. (zigzeg)


Lesenswert?

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

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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.

von Kaan A. (deranfaenger)



Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Kai S. (zigzeg)


Lesenswert?

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:
1
register volatile uint16_t pwm_currentphase_Mag1 asm ("r8");
2
3
pwm_currentphase_Mag1 += mag[1].pwm_step;
(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

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

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

von Kaan A. (deranfaenger)


Lesenswert?

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.

von Mark B. (markbrandis)


Lesenswert?

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.

: Bearbeitet durch User
von Mark B. (markbrandis)


Lesenswert?

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.

von Kai S. (zigzeg)


Lesenswert?

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

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

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.

von Markus F. (mfro)


Lesenswert?

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.

von Falk B. (falk)


Lesenswert?

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 . . .

von Falk B. (falk)


Lesenswert?

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%.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.