Forum: Compiler & IDEs Bitverarbeitung


von Christian P. (sarstein)


Lesenswert?

Hallo zusammen

Folgende Ausgangssituation:
MCU: ATtiny25, ca. 8Mhz mit internen Oscillator
Winavr:20090313
AVR-Studio: 4.18, SP2, Simulator2

Ich möchte den A/D-Wandler benutzen und das Ende der Wandlung abfragen.
Hier die relevanten Codeschnipsel:

#include  <avr/io.h>
....
init:
ADMUX  = 0b00100000; //left adjust, channel0 select
ADCSRA = 0b00000110; //125KHZ sample rate at 8MHz
....
ADCSRA |= _BV(ADEN); //enable ADC, bit7 of ADCSRA
....
ADCSRA |= _BV(ADSC); //start conversion, bit6 of ADCSRA
loop_until_bit_is_clear(ADCSRA,ADSC); //das geht nicht

alternativ hab ich versucht:
do
{
   tmp = ADCSRA; //tmp ist als lokale uint8_t variable zuvor definiert
   tmp &= 0x40;
}
while(tmp); //geht auch nicht

Folgendes Verhalten:
Im Simulator kann man beobachten, dass das ADSC bit gesetzt wird und 
nach ein paar loops wieder auf 0 geht.
Die SW bleibt aber im makro loop_until_.. hängen.
Im Datenblatt und im AVR-Simulator sind für Register ADCSRA 2 Adressen 
angegeben: 0x6 und 0x26. Im generierten Assemblercode wird 0x26 
verwendet, wogegen man im memory I/O Fenster des AVR-Simulators auf 
Adresse 0x6 die Veränderung des ADSC bit verfolgen kann. Auf Adresse 
0x26 passiert nichts.

Wo steckt da der Wurm?


Es gibt im AVR-Studio noch einen weiteren Punkt der seltsam ist:

In der Konfigurationseinstellung gebe ich 8MHz Takt an, der Simulator 
sagt aber nur 1MHz, im generierten makefile steht aber auch 8Mhz drin. 
Hat das etwa mit der Auswahl der Taktquelle zu tun?

Hat da einer von euch eine Idee die mir hilft? Schon mal danke im 
Voraus.
Christian

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


Lesenswert?

Christian P. schrieb:
> Wo steckt da der Wurm?

Im Simulator?

Schau dir mal an, was im realen Silizium passiert.

Der Unterschied zwischen beiden Adressierungsarten ist eine
grundsätzliche Eigenheit der klassischen (nicht-Xmega) AVRs, darüber
solltest du dich mal im Datenblatt kundig machen, bevor du da
irgendwas mutmaßt.  Offenbar hast du auch die Optimierung
ausgeschaltet.

> im generierten makefile steht aber auch 8Mhz drin.

Das Makefile konfiguriert rein gar nichts, das teilt nur einigen
Routinen bzw. Makros (und zwar denen in <util/delay.h> und
<util/setbaud.h>) mit, von welcher CPU-Frequenz sie bei ihren
Rechnungen ausgehen sollen.  Dass diese CPU-Frequenz eingestellt
ist, darum musst du dich separat kümmern (per Fuses bzw. CLKPR).

von Christian P. (sarstein)


Lesenswert?

Hallo Jörg

Danke für die rasche Antwort. Habe noch kein reales Si.

Von unterschiedlichen Zugriffen auf I/O-Adressen des AVR habe ich schon 
gehört, aber aus dem Datenblatt bin ich da auch nicht wirklich schlauer 
geworden. Der wahre Überblick fehlt mir da noch.
In bin davon ausgegangen, daß der Winavr-Compiler das richtig macht und 
man den Simulator für so einfache Routinen nutzen kann, ehe man die HW 
am Tisch hat.

Die Optimierung habe ich tatsächlich abgeschaltet. Wollte das erst 
während des Projektverlaufes optimieren.

Gibt es keinen Weg das ohne Si zu testen?

Gruß
Christian

von Karl H. (kbuchegg)


Lesenswert?

Christian P. schrieb:

> Gibt es keinen Weg das ohne Si zu testen?

Du kannst im Simulator immer noch händisch auf jedes Bit in jedem 
Register draufklicken und es so von 0 auf 1 bzw. umgekehrt stellen. Dann 
ein paar mal F10, bis das Programm an die Stelle kommt, an der das Bit 
abgefragt wird, und schon sollte die Schose wieder laufen.

Einzig wenn es darum geht, dass irgendein Timer eine PWM generiert und 
daher ein Pin eigentlich bei bestimmten Zählerständen toggeln sollte, so 
hat der Simulator so manchesmal seine liebe Not damit.

von Karl H. (kbuchegg)


Lesenswert?

> alternativ hab ich versucht:

Was ist falscg daran, die ADC Routine aus dem AVR-GCC-Tutorial als 
Ausgangspunkt zu nehmen?

von Christian P. (sarstein)


Lesenswert?

Hallo Karl Heinz

Das Bit setzen & löschen im Sim. geht ja alles, einzig die Warteschleife 
will nicht. Weder der vorgegebene macro, noch die umständliche, 
selbstgestrickte do..while. Das Muster im Tutorial kannte ich nicht, 
probier ich mal.

Übrigens bei eingeschalteter Optimierung (Os anstatt ursprünglich O0) 
steht im Disassembler dann die Adresse 0x6 anstatt 0x26. Funktionieren 
tut das aber trotzdem nicht.

Danke, bis bald
Christian

von Karl H. (kbuchegg)


Lesenswert?

Christian P. schrieb:

> Übrigens bei eingeschalteter Optimierung (Os anstatt ursprünglich O0)
> steht im Disassembler dann die Adresse 0x6 anstatt 0x26.

Da macht der COmpiler den Zugriff anders. Kümmere dich nicht darum.
Im Debugger mit einer optimierten Variante durchzusteppen ist .... mutig

von Christian P. (sarstein)


Lesenswert?

Da bin ich noch mal

Also auch das Beispiel aus dem Tutor mag der Sim. nicht. Mit & ohne 
Optimierung bleibt da die SW in der Schleife
while (ADCSRA & (1<<ADSC) );
hängen. Da kann ich mit dem ADSC bit machen was ich will. Da scheint 
Atmel im Sim. noch einen bug zu haben. Jörg hat auch schon sowas 
angedeutet.

Der "Übermut" resuldiert daher, dass ich nur den code für die Funktion 
herauskopiert habe, um damit mal zu experimentieren.

Wenn ich noch mutiger wäre, würde ich das ganze in assembler schreiben. 
Bei der relativ überschaubaren Aufgabe könnte man das fast wagen. Aber 
es drängt die Zeit und es mangelt an Erfahrung.

Noch mal danke für die Unterstützung.

Christian

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


Lesenswert?

Hast du den "Simulator V2" benutzt?  Den müsste es doch für einen
ATtiny25 geben, oder?  (Sorry, ich habe kein AVR Studio hier.  No
Gates, no Windows.)

Der sollte zumindest den Digitalteil ordentlich simulieren.  Ansonsten
die errata notes zum AVR Studio genau lesen, ich glaube mich zu
erinnern, dass die bekannten Probleme in der Simulation in der Regel
auch dokumentiert worden sind.

Christian P. schrieb:
> Wenn ich noch mutiger wäre, würde ich das ganze in assembler schreiben.

Das bringt dir auch nichts, wenn es nur der Simulator falsch
simuliert.  Du kannst dem bisschen C-Code, das hinter "loop_until_..."
steht schon zutrauen, dass der Compiler das korrekt compiliert.  Da
bringt auch ein ebenfalls korrekt geschriebener Assemblercode keine
Änderung (wenn du ihn erstmal bis zu diesem Punkt hast).

von Christian P. (sarstein)


Lesenswert?

Hallo Jörg,

ja ich hab's mit Sim.V2 probiert, steht auch in meinem 1. thread. Auch 
die Studioversion ist die aktuellste. Der ATtiny25 ist mit dabei. Winavr 
gibt es in einer neueren Version. Bei dem trivialen code kann es 
eigentlich daran nicht liegen.
Die Mühe, vielmehr die Zeit die Atmel error lists durchzulesen habe ich 
mir noch nicht genommen. Vielleicht wird das ja heute meine 
Bettlektüre;-).

Also das mit dem Assembler überleg ich mir auch noch. Wahrscheinlich 
krieg ich da kalte Füsse.

Gruß
C.

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


Lesenswert?

Christian P. schrieb:
> ja ich hab's mit Sim.V2 probiert, steht auch in meinem 1. thread.

Sorry, hatte ich überlesen.  Dann sollte es allerdings auch
funktionieren.

Poste mal vollständigen, compilierbaren Code.

von Christian P. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Jörg

Anbei der auf die ADC-Anwendung reduzierte code.
Ich hab mit allen Optimierungsstufen alle 3 Varianten probiert. Im SimV2 
wird bit ADSC->0, aber er bleibt in der Abfrageschleife hängen.

Gruß
C.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Kann man den ADC (oder andere HW-Komponenten) initialisieren, wenn sie 
nicht aktiviert sind? Auf AVR hatte ich da mal irgendwo ein Problem, daß 
ich nach nem Sleep was konfirgurierte bevor ich das Modul aktivierte. 
UART oder Timer, vielleicht ist es beim ADV ja auch sowas?

von Christian P. (Gast)


Lesenswert?

Hallo Johan

Der ADC wird mit dem Setzen des ADEN bits im ADCSRA Register aktiviert 
und mit dem Setzen von ADSC im selben Register gestartet.
Läßt sich im Simulator nachvollziehen.

Das Problem ist der deadlock bei der Abfrage von ADSC.

Gruß
C.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

init() wird doch vor ENABLE_ADC gemacht. Wie auch immer, wenn's geht ist 
ja ok.

von Christian P. (Gast)


Angehängte Dateien:

Lesenswert?

Korrektur des sourcecodes.
Ich hatte im vorangehenden posting die variable tmp nicht definiert. 
Ohne der funktioniert Version2 der Abfrageschleife nicht.

C.

von Karl H. (kbuchegg)


Lesenswert?

Also:
Der generierte Code sieht richtig aus.
Ich denke das ist ein Fehler im Simulator.
Auf der GUI sieht man zwar, das das Bit gelöscht wird, dem Code wird es 
aber ständig als gesetzt präsentiert.
1
  //3. Version (aus dem tutorial)
2
  ADCSRA |= (1<<ADSC);  // eine ADC-Wandlung 
3
  uint8_t val = ADCSRA;
4
  while (val & (1<<ADSC))
5
    val = ADCSRA; // auf Abschluss der Konvertierung warten
6
}

val hat immer einen Wert von 196 == 0xC6 == ADSC ist gesetzt, unabhängig 
davon ob man händisch den Haken aus dem ADCSRA Register rausmacht oder 
nicht.

von Christian P. (Gast)


Lesenswert?

Servus Karl Heinz

Ich hab jetzt noch mal mehrfach die Initialisierungsreihenfolge 
verändert, aber das Ergebnis bleibt unbefriedigend. Mal sehen wie ich 
das den Atmelkameraden mitteilen kann.

Bleibt nur noch der Test an der realen HW.

Trotzdem euch allen herzlichen Dank für die Mühe und noch einen schönen 
Fußballabend.

Gruß
Christian

von Christian P. (Gast)


Lesenswert?

Bei mir im Sim. ändert sich der Wert im ADCSRA schon von C6 auf 86, aber 
aus der Schleife kommt er trotzdem nicht raus.

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.