Forum: Compiler & IDEs Ich habe eine Frage zum USI Codebeispiel von A.K.


von BF (Gast)


Lesenswert?

Ich habe eine Frage zum USI-I2C Beispiel aus der Codesammlung von A.K.
( Beitrag "Re: attiny USI Slave Implementierung" )

Da ich nicht will dass die Codesammlung unübersichtlich wird, stelle ich 
meine Frage hier.

Bei meinem ATtiny44 funktioniert das Beispielprogramm bis jetzt 
zuverlässig.

Aktuell sende ich versuchsweise 20Byte an einen einen Master und lese 
2Byte ein.

Wenn ich dass im Beispiel richtig sehe, wird beim Zugriff auf den Sende- 
und Empfangsbuffer der globale Interupt abgeschalten.

Da das Kopieren der Daten und Berechnen der Prüfsumme etwas länger 
braucht, will ich dass diverse Interupts (externe Interupts, 
Timerüberläufe,...) den Koopiervorgang kurz unterbrechen können.
(Sichern der Daten und anfügen eines Zeitstempels.)
Dafür müsste ich die globalen Interupts aktiviert lassen.
Dies würde aber zu race conditionen führen.

Weis jemand wie ich das bewerkstelligen kann?

Ich habe es schon versucht, anstatt mit usi und cli die Interupts global 
zu behandeln, nur die USI Interrups über das Register USICR die Bits 
USISIE und USIOIE ab und anzuschalten.
Doch dass führt zu fem Probem, dass das Senden / Empfangen gelegentlich 
fehlschlägt.

von (prx) A. K. (prx)


Lesenswert?

BF schrieb:

> Wenn ich dass im Beispiel richtig sehe, wird beim Zugriff auf den Sende-
> und Empfangsbuffer der globale Interupt abgeschalten.

Nur für die Antwort an den Master. Bei der Message vom Master hingegen 
nicht.

Die CRC lässt sich doch wohl auch vorher berechnen, so dass für die 
Interrupt-Abschaltung nur die Zeit des Kopierens in den Puffer 
verbleibt.

von BF (Gast)


Lesenswert?

A. K. schrieb:
> Die CRC lässt sich doch wohl auch vorher berechnen, so dass für die
> Interrupt-Abschaltung nur die Zeit des Kopierens in den Puffer
> verbleibt.

Ich hatte den Ablauf aktuell so geplant, dass die Daten laufend in ein 
Datenarray geschrieben werden und dann zum Senden in den Sendebuffer 
kopiert werden.
Wenn ich da den Kontrollwert nicht beim Kopieren in den Sendebuffer, 
sondern vorher errechne, müsste ich die Daten in einen Zwischenbuffer 
schreiben um sicher zu gehen, dass nicht doch ein Wert verändert wird.
Dass würde die Resourcen doch ziemlich strapazieren.
Außerdem gibt es noch dass Problem, dass der Kopiervorgang ca.2/3 der 
Zeit in Anspruch nimmt und die Berechnung des Kontrollewertes nur 1/3.
Dadrurch würde ich durch die Auslagerung der Kontrollwertberechnung 
nichts gewinnen.

Gibt es also keine Möglichkeit für den Kopiervorgang nur den den USI 
abzuschalten?

von (prx) A. K. (prx)


Lesenswert?

Was dann passiert weiss ich nicht, ich habe das nicht getestet.

von (prx) A. K. (prx)


Lesenswert?

PS: Ich hatte diesen Code für Kommunikation in Form von Messages 
vorgesehen. Wenn es sich eher um einen Datenstrom handelt, dann kommt 
vielleicht auch der Atmel'sche Code in Frage.

von BF (Gast)


Lesenswert?

A. K. schrieb:
> Was dann passiert weiss ich nicht, ich habe das nicht getestet.

Wenn man nur die Interrupt-Flags des USI ab- und anschaltet treten bei 
mir bei ca. 5% der Sende- / Empfangsversuche des Masters ein Fehler auf. 
Wie's aussieht reagiert der Slave nicht rechzeitig.
Jedenfalls kann in diesen 5% keine Verbindung hergestellt werden.

Ich muss leider die Daten paketorientiert versenden, da der Master nicht 
von mir ist und dieser nur alle 10 bis 50ms eine Momentaufnahme der 
aktuellen Daten verlangt.
Nur wollte ich bis zum letzten Moment ein aktualisierung der Daten 
zulassen.
Also nur für den Kopiervorgang des einen Wertes den betreffenden 
Interupt abschalten und dann wieder aktivieren.

Denn wenn ich die globalen Interrupts während des gesammten 
Kopiervorgangs abschalte, kommt es zu einer Verfälschung der Messdaten 
zwischen 7 und 10%.
Wenn ich die USI-Interrupts abschalte, bekomme ich zwar immer wieder 
dass Problem mit der Verbindung, dafür beträgt die Verfälschung der 
Messdaten nur 2 bis 3%.

Desswegen bin ich auf der Suche nach einer Möglichkeit die Datenpakete 
zu versenden, ohne die Interupts zu sehr zu beeinträchtigen.

von (prx) A. K. (prx)


Lesenswert?

Probier mal aus, was ohne Abschaltung des Interrupts passiert. Müsste 
eigentlich auch ohne gehen. Erhöht die Wahrscheinlichkeit, dass der 
Master als Antwort nur einen Abort kriegt. Retry seitens des Masters ist 
ohnehin sinnvoll.

von BF (Gast)


Lesenswert?

A. K. schrieb:
> Probier mal aus, was ohne Abschaltung des Interrupts passiert. Müsste
> eigentlich auch ohne gehen.
So wie es aussieht, funktioniert es ganz ohne cli/sei bzw. Abschalten 
der Interrupt's.

Ich habe jetzt. ein paar Tausend Datenpakete übermittelt, und es ist 
kein Übertragungsfehler aufgetreten.
Mal schaun, wie sich dass Ganze unter Realbedingungen verhält.

Die Frage ist jetzt, warum das Abschalten der Interupt's über die Flags 
nicht funktioniert hat, obwohl das ja genau die gleiche Funktion erfüllt 
wie die Verwendung von cli und sei.

von ... (Gast)


Lesenswert?

BF schrieb:
> Die Frage ist jetzt, warum das Abschalten der Interupt's über die Flags
> nicht funktioniert hat, obwohl das ja genau die gleiche Funktion erfüllt
> wie die Verwendung von cli und sei.

Nein, da ist ein gewaltiger Unterschied!
Zwischen cli und sei ist zwar die Ausführung der ISRs abgeschaltet, 
nicht jedoch das Erkennen der entspechenden Ereignisse. Tritt ein 
entsprechendes Ereignis zwischen cli und sei ein, wird die zugehörige 
ISR trotzdem ausgeführt, nur halt verzögert nach dem sei.
Manipulierst Du hingegen direkt die Flags, schaltest Du auch die 
Erkennung der Ereignisse mit ab, d.h. die Ereignisse in dieser Zeit 
gehen komplett verloren.

CU

von (prx) A. K. (prx)


Lesenswert?

... schrieb:

> Manipulierst Du hingegen direkt die Flags, schaltest Du auch die
> Erkennung der Ereignisse mit ab, d.h. die Ereignisse in dieser Zeit
> gehen komplett verloren.

Die IE-Bits haben keinen Einfluss auf die IF-Bits.

von ... (Gast)


Lesenswert?

Auweia, Asche auf mein Haupt.
Da hat A. K. natürlich vollkommen Recht.

Bleibt als Erklärung für das unterschiedliche Verhalten noch ein anderer 
Interrupt, der bei cli/sei mit abgeschaltet wird und über die Flags halt 
nicht.

von BF (Gast)


Lesenswert?

Mir sind nur die Interrupts USISIE und USIOIE im Register USICR beim 
USI-TWI bekannt.

Jedenfalls finde ich im Datenblatt und im Beispielquellcode nur die 
Beiden.

... schrieb:
> Bleibt als Erklärung für das unterschiedliche Verhalten noch ein anderer
> Interrupt, der bei cli/sei mit abgeschaltet wird und über die Flags halt
> nicht.
Genau darum geht's ja.
Aber diese Interupt's haben eigentlich nichts mit dem USI / I2C zu tun.

von ... (Gast)


Lesenswert?

BF schrieb:
> Aber diese Interupt's haben eigentlich nichts mit dem USI / I2C zu tun.

Müssen sie auch nicht. Einmal sind sie mit abgeschaltet (cli/sei) und 
das andere mal nicht (USISIE/USIOIE). Das kann das Timing schon gut 
durcheinander bringen, bei der Flag-Variante sind die USI-ISRs unter 
Umständen wesentlich länger abgeschaltet. Wenn die Gegenseite dann zwei 
Bytes zu schnell nacheinander sendet oder nicht lange genug auf Antwort 
wartet, dann hast Du schon verloren.

von (prx) A. K. (prx)


Lesenswert?

... schrieb:

> Umständen wesentlich länger abgeschaltet. Wenn die Gegenseite dann zwei
> Bytes zu schnell nacheinander sendet oder nicht lange genug auf Antwort
> wartet, dann hast Du schon verloren.

Während des laufenden Transfers sollte das kein Thema sein, da das USI 
auf Clock Stretching konfiguriert ist, d.h. SCL vom Slave hardwareseitig 
solange verlängert wird, bis die Software darauf reagierte. Und in der 
Start Condition ist das sowieso schon Bestandteil der Arbeitsweise des 
USI.

Vorausgesetzt allerdings, dass der Master dieses Clock Stretching auch 
berücksichtigt und nicht davon ausgeht, SCL sei unidirektional und 
ausschliesslich unter seiner Kontrolle.

Ebenso sollte der Master nicht schon nach wenigen Takten die Start 
Condition wieder abbrechen, wenn nicht sofort darauf reagiert wurde. 
Wenn der Master einen Start abbricht und sofort neu initiiert, dann kann 
es bei verzögerter Reaktion im Slave vorkommen, dass der zweite Start 
nicht bemerkt wird.

von (prx) A. K. (prx)


Lesenswert?

Wichtiges zum Ablauf: Es gibt Phasen, in denen der Slave den Master 
gleich vorneweg abwirft, d.h. die Adressierung nicht positiv 
beantwortet. Nämlich dann, wenn der vorherige Request noch in Arbeit 
ist. In dieser Hinsicht unterscheidet sich das Verhalten deutlich von 
den üblichen I2C-Hardwarebausteinen.

Solche Abbrüche sollten nicht als Fehler interpretiert werden, sondern 
sind normaler Teil der Arbeitsweise dieses Codes.

von BF (Gast)


Lesenswert?

Danke.

Du hast mir sehr geholfen.

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.