Forum: Compiler & IDEs Bug? DAC im ATmega16m!


von K. Ahnung (Gast)


Lesenswert?

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.

von Sauger (Gast)


Lesenswert?

Moin,

habe ich was verpasst? seit wann hat ein Mega16 einen DAC

MfG

von Karl H. (kbuchegg)


Lesenswert?

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.

von Sauger (Gast)


Lesenswert?

Moin

sorry habe das M übersehen, das ! sollte wohl eine 1 werden. Dieser hat 
natürlich ein DAC.

MfG

von Peter D. (peda)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von K. Ahnung (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.
1
#define ADC _SFR_MEM16(0x78)
2
#define DAC _SFR_MEM16_R(0x91)


Peter

von Karl H. (kbuchegg)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:

> Man muß ja nur einen 2. Typ 16Bit-Register definieren, der reverse
> zugegriffen wird.
>
1
> #define ADC _SFR_MEM16(0x78)
2
> #define DAC _SFR_MEM16_R(0x91)
3
>

Und jetzt "nur" noch bitte die Definition für _SFR_MEM16_R, Peter! :-)

Du hast das Problem noch gar nicht verstanden ...

von Karl H. (kbuchegg)


Lesenswert?

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?

von Εrnst B. (ernst)


Lesenswert?

Jörg Wunsch schrieb:
> Und jetzt "nur" noch bitte die Definition für _SFR_MEM16_R, Peter

Die ist vermutlich noch einfach.
Copy&Paste, ein
1
 __attribute__((__avr_reversed_16_bit_access_for_chips_designed_on_mondays__))
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 ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:

> Zumindest sollte man beim AVR-GCC diese Zeilen unbedingt streichen:

Die sind gar nicht im AVR-GCC drin. :-)

>
1
> #define DAC _SFR_MEM16(0x91)
2
> #define DACW _SFR_MEM16(0x91)
3
>

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.

von Karl H. (kbuchegg)


Lesenswert?

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)

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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
extern void use_dac (volatile uint16_t*);
4
5
void foo (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:
1
#include <stdint.h>
2
3
#define SUCK_MY_DAC (* (uint16_t __sucking_dac volatile *) &DAC)
4
5
extern void use_dac (volatile uint16_t __sucking_dac*);
6
7
void foo (void)
8
{
9
    SUCK_MY_DAC = 0;
10
    use_dac (&SUCK_MY_DAC);
11
}
 
Wie praktikabel das wäre und wie hoch das Kosten/Nutzen-Verhältnis, möge 
jeder für sich bewerten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

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.