Bug? DAC im ATmega16m!

Gast #2886987
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.
#2887040
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
Moderator Persönliche Seite #2887088
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.
Gast #2887173
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.
#2887274
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
#2887285
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.
#2887305
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.
#2887326
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 ;)
Moderator Persönliche Seite #2887338
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. :-/
#2887340
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
Moderator Persönliche Seite #2887351
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.
#2887443
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)
Persönliche Seite #2888239
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.
Moderator Persönliche Seite #2888254
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren