Bei dieser Konstellation zeigt der AVR-Studio-Simulator mir im
Überwachungsfenster zwar für die Konstante 'K_AdresseZusatz' den
korrekten Wert an, hat aber keine Lust damit zu rechnen!?
Der ASM-Code dazu ist soweit*) korrekt, also gehe ich davon aus, dass es
im Controller funktioniert(?):
*) Ich habe schon mit Casts um mich geschmissen, konnte aber dem
Compiler nicht abgewöhnen, die Operationen (Bitverknüpfungen, Schieben)
in 16Bit zu machen. Geht das irgendwie? Außerdem: wieso 'asr r25', wenn
alles 'uint8_t' ist?
Bitte Vorschläge, danke!
A. K. schrieb:> Auf PROGMEM Daten kann man nicht direkt zugreifen. Doku lesen.
???
Ralf schrieb:> // const uint8_t K_AdresseZusatz PROGMEM = 48;> // => so funktioniert's (ohne 'Const.c')
Und der erzeugte Assembler-Code ist ja korrekt. So wie man's auch direkt
macht:
Ralf schrieb:> 60: 20 91 26 00 lds r18, 0x0026> 64: 28 2b or r18, r24> 66: 20 93 60 00 sts 0x0060, r18
Ralf schrieb:> Und der erzeugte Assembler-Code ist ja korrekt.
Nicht wirklich. PROGMEM Daten liegen im Flash und das ist
ausschliesslich per (E)LPM erreichbar. Kein LPM => keine korrekten
Daten.
A. K. schrieb:> Kein LPM => keine korrekten Daten.
Genau. Ist mir gerade auch aufgefallen. Das hab ich völlig übersehen.
Die Konstante wird gar nicht berücksichtigt im ASM-Code :-(
Warum dann aber Variante 2 (nicht 'extern') funktioniert, ist mir jetzt
auch klar: die Konstante wird nicht im Flash gespeichert, sondern gleich
an der entsprechenden Stelle in den Code gebastelt. Muss ich mal
'pgm_read' probieren (hoffe das braucht nicht zuviel Code!)
Bleibt noch: Warum 16Bit?
Ralf schrieb:> konnte aber dem> Compiler nicht abgewöhnen, die Operationen (Bitverknüpfungen, Schieben)> in 16Bit zu machen. Geht das irgendwie? Außerdem: wieso 'asr r25', wenn> alles 'uint8_t' ist?
Ich konnt's ihm abgewöhnen :-)
1
AdressePlatine=(((~PINB)&0b11100000));
2
AdressePlatine=AdressePlatine>>5;
3
AdressePlatine|=pgm_read_byte(&K_AdresseZusatz);
Da gibt der Compiler sich richtig Mühe!
Trotzdem: warum erst 16Bit und 'asr r25'?
Ralf schrieb:> Trotzdem: warum erst 16Bit und 'asr r25'?
Weil die C-Definition vorschreibt, daß bei einer Rechenoperation alle
Operanden, die kleiner als int sind, erstmal zu int erweitert werden und
die Rechnung dann in int durchgeführt wird. Der Compiler darf diese
Erweiterung wegoptimieren, aber nur, wenn er garantieren kann, daß in
jedem Fall das Ergebnis dadurch nicht beeinträchtigt wird. Jetzt ist bei
AVR aber die native Wortgröße kleiner als int, und da dieser Fall in GCC
eine Ausnahme darstellt, sind solche Optimierungen da nicht so
umfassend.
Ralf schrieb:> Ralf schrieb:>> konnte aber dem>> Compiler nicht abgewöhnen, die Operationen (Bitverknüpfungen, Schieben)>> in 16Bit zu machen. Geht das irgendwie? Außerdem: wieso 'asr r25', wenn>> alles 'uint8_t' ist?> Ich konnt's ihm abgewöhnen :-)>
1
>AdressePlatine=(((~PINB)&0b11100000));
2
>AdressePlatine=AdressePlatine>>5;
3
>AdressePlatine|=pgm_read_byte(&K_AdresseZusatz);
4
>
> Da gibt der Compiler sich richtig Mühe!>> Trotzdem: warum erst 16Bit und 'asr r25'?
Probier mal
@Rolf Magnus
Sozusagen: Er könnte, wenn er wollte ;-)
@Karl Heinz Buchegger
Ich hatte mir extra den ASM-Code angeschaut, mit meinen Kenntnissen
könnte ich da nichts verbessern (in Assembler hätte ich das genauso
gemacht, außer: r30 gleich als Ziel für lpm zu verwenden, hätte ich mich
nicht 'getraut'):
@Karl Heinz Buchegger
Hatte gestern keine Gelegenheit mehr das zu probieren. Mit deinem
Zweizeiler ist das ganze wieder etwas übersichtlicher.
-----
Karl Heinz Buchegger schrieb:> durch das ~ zwingst du den Compiler, den Wert auf 16 Bit aufzublasen.Rolf Magnus schrieb:> Weil die C-Definition vorschreibt, daß bei einer Rechenoperation alle> Operanden, die kleiner als int sind, erstmal zu int erweitert werden und> die Rechnung dann in int durchgeführt wird.
Kann man sowas als Laie wissen? Dann habe ich das immer überlesen.
Vielleicht, weil es auf dem PC nicht so wichtig ist...
Ralf schrieb:> int main()> {> AdressePlatine=(((~PINB) & 0b11100000) >> 5) | K_AdresseZusatz;> }> [/c]> [...]> *) Ich habe schon mit Casts um mich geschmissen, konnte aber dem> Compiler nicht abgewöhnen, die Operationen (Bitverknüpfungen, Schieben)> in 16Bit zu machen. Geht das irgendwie?
Der Cast muss an der richtigen Stelle sein:
Ralf schrieb:> Kann man sowas als Laie wissen?
In den Büchern über C steht das üblicherweise drin. Aber mehr es dort
reinschreiben geht nicht, lesen muss der Adept es dann schon selber.
Johann L. schrieb:> Der Cast muss an der richtigen Stelle sein:> AdressePlatine = ((((uint8_t) ~PINB) & 0b11100000) >> 5) | K_AdresseZusatz;
Ich glaube, das war die einzige Stelle, die ich nicht probiert habe. So
ein Port hat ja nun sowas von 8Bit...
Aber: 'Wie wir jetzt wissen' ;-)
Karl Heinz Buchegger schrieb:> durch das ~ zwingst du den Compiler, den Wert auf 16 Bit aufzublasen.
Ralf schrieb:> Johann L. schrieb:>> Der Cast muss an der richtigen Stelle sein:>> AdressePlatine = ((((uint8_t) ~PINB) & 0b11100000) >> 5) | K_AdresseZusatz;>> Ich glaube, das war die einzige Stelle, die ich nicht probiert habe.
Freilich geht aus sowas:
1
voidfoo2()
2
{
3
AdressePlatine=(PINB>>5)^K_AdresseZusatz;
4
}
indem du in K_AdresseZusatz die unteren 3 Bits setzt. Ist ja eh ne
Konstante, und da tut das nicht weh :-)
Johann L. schrieb:> Freilich geht aus sowas:void foo2()> {> AdressePlatine = (PINB >> 5) ^ K_AdresseZusatz;> }> indem du in K_AdresseZusatz die unteren 3 Bits setzt. Ist ja eh ne> Konstante, und da tut das nicht weh :-)>
Kann ich nachvollziehen :-)
Das ist natürlich mal was. Wäre ich nie drauf gekommen.