Ist das ein Bug?
Schreibt man Werte in das Register (?) DAC, wird wohl zuerst das
High-Byte, dann das Low-Byte geschrieben. Bei einem Sprung von 255 auf
256 ist am Ausgang des DAC entweder 0V oder VREF zu messen.
Schreibt man den Wert manuell in das DACL und DACH Register,
funktioniert alles wunderbar.
K. Ahnung schrieb:> Ist das ein Bug?>> Schreibt man Werte in das Register (?) DAC, wird wohl zuerst das> High-Byte, dann das Low-Byte geschrieben.
Sieh im Assembler Output nach.
Wenn dem tatsächlich so ist, dann wird das wohl ein Bug sein.
Das hat historische Ursachen:
Timer 16 Bit lesen:
- low byte (high wird gelatcht)
- high byte
Timer 16 Bit schreiben:
- high byte (high wird gelatcht)
- low byte + high latch
ADC 10 Bit lesen:
- low byte (high wird gesperrt)
- high byte
ADC 8 Bit lesen:
- high byte
Bis hierher kann der Compiler das alles gleich machen.
Und nun kommts:
DAC 10 Bit schreiben:
- low byte (low wird gelatcht)
- high byte + low latch
DAC 8 Bit schreiben:
- high byte
Also genau andersrum. Das läßt sich daher nicht mehr als 16 Bit vom
Compiler machen. Man muß es zu Fuß machen.
Oder jemand macht nen Compiler-Patch dafür.
Peter
Peter Dannegger schrieb:> Oder jemand macht nen Compiler-Patch dafür.
Geht praktisch nicht. Der Compiler hat absolut keine Ahnung, ob das
Registerpaar nun zu einem DAC oder Timer oder sonstwas gehört. Alles,
was er darüber noch weiß, ist eine Speicheradresse, an der das Register
angesprochen wird.
Der Bug ist also im ATmega16M1 selbst. Wird natürlich ganz sicher
nicht mehr behoben werden.
Peter Dannegger schrieb:> Bis hierher kann der Compiler das alles gleich machen.> Und nun kommts:>> DAC 10 Bit schreiben:> - low byte (low wird gelatcht)> - high byte + low latch>> DAC 8 Bit schreiben:> - high byte>> Also genau andersrum.
Bei manchen Sachen fragst du dich schon, ob die bei Atmel pennen.
> Bei manchen Sachen fragst du dich schon, ob die bei Atmel pennen.
Ich denke fast, das es Tagesformabhägig ist. Mo. Mi. und Fr. machen sie
es so, Di. Do. dann halt andersrum :)
Gut, wollte nur darauf hinweisen - workaround ist dann halt die SFRs
einzeln zu beladen. Geht ja auch.
Der Fehler fällt halt nicht so schnell auf und ohne debugWIRE hätte ich
mir wahrscheinlich einen Wolf gesucht.
Karl Heinz Buchegger schrieb:> Bei manchen Sachen fragst du dich schon, ob die bei Atmel pennen.
Wahrscheinlich ist der DAC von irgendwas anderem dann da als Block
importiert worden, und daran, den 16-bit-Zugriff den bislang
vorhandenen AVR-Konventionen anzupassen, hat dann einfach keiner
gedacht.
Karl Heinz Buchegger schrieb:> Bei manchen Sachen fragst du dich schon, ob die bei Atmel pennen.
Ne, die haben sich schon was dabei gedacht.
Das ist, damit man nicht auch das low-Byte schreiben muß, wenn man nur
einen 8Bit-DAC (DACH) braucht.
Ich kann mir gut vorstellen, das andere Compiler oder Bascom das richtig
machen.
Man muß ja nur einen 2. Typ 16Bit-Register definieren, der reverse
zugegriffen wird.
Peter Dannegger schrieb:> Karl Heinz Buchegger schrieb:>> Bei manchen Sachen fragst du dich schon, ob die bei Atmel pennen.>> Ne, die haben sich schon was dabei gedacht.> Das ist, damit man nicht auch das low-Byte schreiben muß, wenn man nur> einen 8Bit-DAC (DACH) braucht.
Man hätte eine Analogie zum ADLAR vom ADC machen können.
Dann wäre man wieder in der 'wie werden 16 Bit Register beschrieben'
Schiene gewesen.
Karl Heinz Buchegger schrieb:> Man hätte eine Analogie zum ADLAR vom ADC machen können.
Hat man:
Bit 2 – DALA: Digital to Analog Left Adjust
Ändert aber nichts daran:
8Bit-ADC: nur high Byte lesen
8Bit-DAC: nur high Byte schreiben
Peter
Peter Dannegger schrieb:> Karl Heinz Buchegger schrieb:>> Man hätte eine Analogie zum ADLAR vom ADC machen können.>> Hat man:> Bit 2 – DALA: Digital to Analog Left Adjust>> Ändert aber nichts daran:> 8Bit-ADC: nur high Byte lesen> 8Bit-DAC: nur high Byte schreiben
Ach Mist, jetzt hab ich mir selbst ein Bein gestellt.
Beim schreiben muss ja normalerweise mit dem Low abgeschlossen werden.
:-)
Dann eben ein 'reverse ADLAR' bei dem nur das Low-Byte gilt.
Wie funktioniert das eigentlich jetzt im GCC.
Weiß der explizit, das er auf 16 Bit Pseudo-Register in dieser
Reihenfolge zugreifen muss, oder ergibt sich das implizit, weil er auf
16 Bit Werte immer in dieser Reihenfolge zugreift?
Weiß das wer?
an die richtige stelle.
Der schwere Teil ist dann, die GCC-Maintainer zu überzeugen, dass das
eine Gute Idee™ ist, und unbedingt implementiert gehört ;)
Karl Heinz Buchegger schrieb:> oder ergibt sich das implizit, weil er auf> 16 Bit Werte immer in dieser Reihenfolge zugreift?
Genauso ist es. Bei normalen Speicherstellen ist es ohnehin egal,
und für alle anderen gibt es bislang halt eine Schreibreihenfolge
und eine Lesereihenfolge.
Für diesen $%!§ DAC müsste man dann eine zweite einbauen.
Εrnst B✶ schrieb:> Der schwere Teil ist dann, die GCC-Maintainer zu überzeugen, dass das> eine Gute Idee™ ist, und unbedingt implementiert gehört ;)
Naja, es betrifft ja nur den AVR-Teil, insofern muss "nur" Johann
davon überzeugt sein, dass das den Aufwand wert ist ... außerdem muss
die avr-libc dann noch Verrenkungen machen um festzustellen, ob der
benutzte Compiler das Attribut versteht oder nicht.
Aber ja, auf ungefähr sowas würde es wohl hinauslaufen. :-/
Jörg Wunsch schrieb:> Und jetzt "nur" noch bitte die Definition für _SFR_MEM16_R, Peter! :-)
Das sollte doch für nen Compilerbauer ein Klacks sein :-)
Zumindest sollte man beim AVR-GCC diese Zeilen unbedingt streichen:
1
#define DAC _SFR_MEM16(0x91)
2
#define DACW _SFR_MEM16(0x91)
Lieber ne Fehlermeldung ausgeben, als still falschen Code erzeugen.
Vielleicht kann mal jemand prüfen, ob die anderen Compiler (IAR, ICC,
Codevision) oder Bascom das richtig machen.
Peter
Ja, wer will, mag einen avr-libc-Bugreport schreiben dafür.
DACW ist ohnehin Humbug. Da hat einer stur ADCW "portiert": diesen
Namen gibt es nur der Benutzungsmöglichkeit im Assembler zuliebe,
bei dem "ADC" ein Befehlsname ist und daher mit einem Registernamen
ADC ollidieren würde.
Peter Dannegger schrieb:> Lieber ne Fehlermeldung ausgeben, als still falschen Code erzeugen.
Seh ich auch so.
>> Vielleicht kann mal jemand prüfen, ob die anderen Compiler (IAR, ICC,> Codevision) oder Bascom das richtig machen.
Davon würde ich mal ausgehen.
Die ganze Sache ist nicht so problematisch, wenn man den Compiler unter
alleiniger Kontrolle hat und auch ein gewisser Marktzwang dahinter
steckt. Beim gcc kommt halt dazu, dass er eine Art Universalcompiler ist
und dass man jemanden, den man nicht durch so schnöde Dinge wie Geld
'erpressen' kann, davon überzeugen muss, dass sich das lohnen würde.
(Denn: natürlich geb ich dir recht. Sooo problematisch ist so eine
Erweiterung dann auch wieder nicht, wenn ich Schlüsselwörter (oder
Attribute) erfinden darf ohne erst bei einem Gremium vorstellig werden
zu müssen)
Jörg Wunsch schrieb:> Εrnst B✶ schrieb:>> Der schwere Teil ist dann, die GCC-Maintainer zu überzeugen, dass das>> eine Gute Idee™ ist, und unbedingt implementiert gehört ;)>> Naja, es betrifft ja nur den AVR-Teil, insofern muss "nur" Johann> davon überzeugt sein, dass das den Aufwand wert ist ...
Ist er aber nicht ;-)
Wenn die Atmel-Kopisten meinen, per Copy-and-Paste oder Drag-and-Drop
ihr Verilog oder VHDL oder was auch immer vom XMEGA zu den klassichen
Cores zu kopieren ohne eine Sekunde darüber nachzudenken — bitte.
Wie wär es denn, das entsprechende SFR aus den AVR-Libc Headern
rauszuwerfen? Oder ein poison? Ein Attribut ist übrigens zu schwach:
1
#include<avr/io.h>
2
3
externvoiduse_dac(volatileuint16_t*);
4
5
voidfoo(void)
6
{
7
use_dac(&DAC);
8
}
Es ginge per Built-in, aber das ist Käse denn mit Inline-Assembler geht
das dann viel einfacher. Benutzbarkeit? Nicht berauschend.
Oder per Address-Space:
Johann L. schrieb:> Wie wär es denn, das entsprechende SFR aus den AVR-Libc Headern> rauszuwerfen?
Ja, sollte man tun, es möge jemand einen Bugreport dafür schreiben.
Ich bin erstmal paar Tage nicht greifbar.
> #define SUCK_MY_DAC (* (uint16_t __sucking_dac volatile *) &DAC)
Naja, man könnte das ja freundlicher formulieren ;-), und dann gleich
für die verschiedenen Varianten von 2- und 4-Byte-Zugriffen die
jeweilige Reihenfolge codieren. Die jetzige Reihenfolge im GCC ist
ja auch eher zufällig entstanden und dann später nochmal korrigiert
worden, nachdem klar war, dass die 16-bit-Registerzugriffe sonst
nicht passend funktionieren.
Der Nachteil ist, dass dann die avr-libc wieder von der passenden
GCC-Version abhängt.