Forum: Mikrocontroller und Digitale Elektronik ATSAM4S TWI Master


von Andreas M. (amesser)


Lesenswert?

Ich habe gestern Abend das TWI Modul vom ATSAM4S in Betrieb genommen und 
bin dabei über etwas gestolpert was mich doch sehr wundert. 
Grundsätzlich ist das TWI Modul im ATSAM4S ja wirklich gut gemacht, aber 
wenn man einen Read macht, dann finde ich das doch sehr komisch gelöst:

Mir ist am Oszilloskop zunächst aufgefallen, das obwohl ich das Program 
im Debugger angehalten habe, weiter dauerhaft Takt auf der SCL Leitung 
war. Habe mit dann das Manual nochmal angesehen und ein bischen 
herumprobiert. Ergebnis ist, dass das TWI Master Modul im Read Modus 
tatsächlich kontinuierlich Daten liest. Erst wenn man eine STOP 
Bedingung per Kontrolregister auslöst hört das auf. Dabei werden dann 
sogar die zuletzt empfangen Daten überschrieben, so dass wenn das 
Programm nicht kontinuierlich den Status pollt und entsprechend die 
Daten aus dem RX Transferregister holt, die Daten sogar verloren gehen. 
Ich vermute im Moment das die einzige Möglichkeit, die Daten ohne 
Verlust zu bekommen, ist einen entsprechenden DMA aufzusetzen. Weitere 
Folge davon ist, das tendenziell immer mehr Daten gelesen werden als man 
eigentlich braucht, da man ja nicht immer sofort den STOP auslösen kann. 
Ob damit alle TWI Slaves zurecht kommen? Man kann den Code der TWI macht 
dann auch gar nicht wirklich Debuggen wenn man keinen DMA macht, denn 
sobald man während eines TWI Transfers die ARM anhält sind die Daten 
Müll. Höherpriore IRQs als TWI sind dann auch so eine Sache und 
Interrupt Locks sowieso. Man ist also letzlich gezwungen den DMA zu 
benutzen.
Im Master Modus verhält sich der TWI laut Datenblatt anscheinend anders. 
Hier wird wirklich nur dann geschrieben wenn man auch Daten in das TX 
Transferregister schreibt.

Ich frage mich wirklich was man sich bei ATMEL dabei gedacht hat, als 
man dieses Modul entwickelt hat. Bei den AVRs ist das in meinen Augen 
wesentlich sinniger zu bedienen.

Hat jemand mit dem TWI vom ATSAM4S schonmal gearbeitet? Habe ich 
eventuell was übersehen?

von CPP (Gast)


Lesenswert?

Benutzt du denn die ASF Quellen? Bzw. hast du ein passendes ASF 
Beispielprogram ausprobiert?

von Andreas M. (amesser)


Lesenswert?

Ich habe mir die read() Funktion aus dem asf kopiert und wollte die dann 
eigentlich modifizieren. Bei dem Chip den ich ansprechen möchte 
enthalten die ersten Bytes der Daten die Länge der noch folgenden Daten. 
Ich habe dann erst mal mit dem Debugger durchgesteppt um zu verstehen 
wie das funktioniert. Dabei ist es mir dann aufgefallen das der ohne 
Unterbrechung liest und die Daten im RX Transferregister überschreibt 
wenn man sie nicht abholt. Sieht man ganz gut wenn man direkt nach dem 
Auslösen der Start-Condition einen Haltepunkt setzt. Ist halt doof, da 
mann entweder eine Interruptsperre um den Funktionsaufruf machen muss 
oder den DMA verwenden muss. Sonst kann es passieren das man Daten 
verliert, z.B wenn die Funktion länger durch Interrupte unterbrochen 
wird. Möglicherweise habe ich etwas übersehen, aber die Timing-Diagramme 
im Manual untermauern meine These eigentlich. Bedeutet für mich mehr 
Aufwand, aber wenn es nicht anders geht....

von M. K. (sylaina)


Lesenswert?

Andreas M. schrieb:
> Ergebnis ist, dass das TWI Master Modul im Read Modus
> tatsächlich kontinuierlich Daten liest. Erst wenn man eine STOP
> Bedingung per Kontrolregister auslöst hört das auf.

Das wäre doch auch richtig.  Nur weil du das laufende Programm mittels 
Debugger anhälst muss das doch nicht heißen, dass das der Hardware-TWI 
stoppt, dass der bis zu Stop-Condition weiter liest wäre jetzt aber auch 
meine Erwartung gewesen.

Andreas M. schrieb:
> Dabei werden dann
> sogar die zuletzt empfangen Daten überschrieben, so dass wenn das
> Programm nicht kontinuierlich den Status pollt und entsprechend die
> Daten aus dem RX Transferregister holt, die Daten sogar verloren gehen.

Und auch das ist jetzt nicht außergewöhnlich, wenn der Sender nicht 
schaut ob der Empfänger bereit ist sendet der einfach weiter.

Andreas M. schrieb:
> Hier wird wirklich nur dann geschrieben wenn man auch Daten in das TX
> Transferregister schreibt.

Na wenn im Transferregister nix steht, was sollte dann gesendet werden? 
Auch das ist doch logisch.

von Marco H. (damarco)


Lesenswert?

Das das verhalten lässt sich beim einstellen. Schau mal in der 
Beschreibung der Register irrend wo lässt sich das beeinflussen was beim 
Debuggen passiert.  Das gleiche Prinzip wird auch beim watchdoog 
verwendet der würde ja einen Reset auslösen wenn du das Programm anhält.

von Andreas M. (amesser)


Lesenswert?

M. K. schrieb:
> Das wäre doch auch richtig.  Nur weil du das laufende Programm mittels
> Debugger anhälst muss das doch nicht heißen, dass das der Hardware-TWI
> stoppt, dass der bis zu Stop-Condition weiter liest wäre jetzt aber auch
> meine Erwartung gewesen.

Ich erwarte auch gar nicht das der TWI Master anhält wenn ich Debugge, 
ich erwarte aber, das der TWI Master anhält, wenn er merkt das noch 
keiner, in diesem Fall das Programm, die übertragenen Daten abgeholt hat 
statt sie einfach zu überschreiben. Jeder andere TWI Master 
Implementierung die ich kenne, verhält sich so, z.B. AVR8, PSoC, 
STM32... Das Problem ist ja auch nicht auf das Debuggen begrenzt. Die 
Routine kann ja auch z.B. von Interrupten unterbrochen werden.

> Und auch das ist jetzt nicht außergewöhnlich, wenn der Sender nicht
> schaut ob der Empfänger bereit ist sendet der einfach weiter.

Der Sender der Daten ist in diesem Fall der Slave. Nur sendet der Slave 
beim TWI gar nicht aktiv, sondern er wartet auf Taktflanken des Masters 
und schiebt bei den Flanken die Daten einfach raus. Bei anderen TWI 
Master Implementierungen ist das normalerweise so gelöst, das der Master 
nur Taktsignal generiert, wenn die Daten auch abgeholt werden, d.h. es 
werden 8 Datentakte + 1 Acktakt generiert, das empfangene Byte in einem 
Register abgelegt und dann der Takt abgeschaltet. Erst wenn das 
Applikationsprogramm auf Masterseite dieses Datenbyte gelesen hat, 
werden die nächsten 9 Takte generiert. Manchmal gibt es noch eine FIFO 
die das ganze ein wenig puffern kann.

Hier ist das aber anders, hier wird einfach stupide getaktet und darauf 
gehofft, das das Programm auf dem Mikrocontroller oft genug bzw. schnell 
genug auf das Datenregister schaut. Das funktioniert aber nur dann wenn 
sichergestellt ist, das die TWI Routine nie unterbrochen wird. 
Normalerweise habe ich aber auch noch eine ganze Menge  Interrupte im 
System, wenn ich ein RTOS einsetze dann wird das noch Schlimmer. 
Möglicherweise kommt die Task die TWI machen soll für zweistellige 
Millisekunden gar nicht dran, weil eine andere, höher priorisierte Task 
gerade irgendwas zeitaufwändiges macht. Und dann bekomme ich 
irgendwelchen Datenmüll vom TWI

Momentan sehe ich es so, das ich beim SAM4S zwingend mit DMA arbeiten 
muss um sicher in jeder Betriebssituation garantieren zu können, das die 
vom TWI gelesenen Daten gültig und ohne Lücken sind.

von M. K. (sylaina)


Lesenswert?

Andreas M. schrieb:
> Ich erwarte auch gar nicht das der TWI Master anhält wenn ich Debugge,
> ich erwarte aber, das der TWI Master anhält, wenn er merkt das noch
> keiner, in diesem Fall das Programm, die übertragenen Daten abgeholt hat
> statt sie einfach zu überschreiben. Jeder andere TWI Master
> Implementierung die ich kenne, verhält sich so, z.B. AVR8, PSoC,
> STM32... Das Problem ist ja auch nicht auf das Debuggen begrenzt. Die
> Routine kann ja auch z.B. von Interrupten unterbrochen werden.

Ich hab die Tage für ein OLED mit i2c was geschrieben. OK, das OLED ist 
ein Slave, aber: Man kann es nur beschreiben, nicht aber lesen. Ich 
bekomme also gar nicht mit, wenn ich dem OLED Daten schicke, ob es 
seinen Puffer schon geräumt hat. Ich muss darauf vertrauen, dass das so 
ist.
Daher die Frage: Woher sollte denn der Master wissen, dass der Slave 
bereit ist, das nächste Byte aufzunehmen? Dann müsste er ja nach jedem 
Byte in den Read-Modus wechseln. So ist sicher nicht jeder Master 
aufgebaut, es ist durchaus nicht unüblich einem Slave mehrere Bytes 
hintereinander zu schicken. Bei dem OLED ist da auch so ein Beispiel, da 
gibts Befehle die einen oder mehrere Parameter haben und das OLED 
erwartet auch, dass die Parameter nach dem Befehlsbyte kommen. Da geht 
also der Slave davon aus, dass der Master schon die richtige Sequenz 
sendet und der Master muss hier schlicht davon ausgehen, dass der Slave 
auch seinen Empfangspuffer rechtzeigt geräumt hat (es sei denn natürlich 
es gab die Stop-Bedingung). Der Master wartet hier nicht nach jedem Byte 
und schaut ob der jeweilige Slave auch seinen Empfangspuffer frei 
gemacht hat. Das kann man so machen, muss man aber nicht so machen.

von Andreas M. (amesser)


Lesenswert?

M. K. schrieb:
> Ich hab die Tage für ein OLED mit i2c was geschrieben. OK, das OLED ist
> ein Slave, aber: Man kann es nur beschreiben, nicht aber lesen. Ich
> bekomme also gar nicht mit, wenn ich dem OLED Daten schicke, ob es
> seinen Puffer schon geräumt hat. Ich muss darauf vertrauen, dass das so
> ist.
> Daher die Frage: Woher sollte denn der Master wissen, dass der Slave
> bereit ist, das nächste Byte aufzunehmen? Dann müsste er ja nach jedem
> Byte in den Read-Modus wechseln. So ist sicher nicht jeder Master

Nein, der Slave kann Clock-Stretching benutzen um den Master zu 
bremsen/anzuhalten. Bei TWI werden die Leitungen ja mit Pull-Up 
Widerständen versehen und alle Busteilnehmer haben 
OpenCollector/OpenDrain Ausgänge. Wenn nun der Slave von dem Master ein 
Byte empfangen hat und noch nicht bereit ist ein nächstes zu empfangen, 
dann kann er einfach die Clock Leitung weiterhin auf Low Pegel halten um 
zu verhindern das der Master weiter Daten senden kann.  Der Master muss 
den wirklichen Logikpegel auf den Leitungen überwachen und darf das 
nächste Bit erst dann auf die Datenleitung legen wenn die Taktleitung 
wieder High-Pegel erreicht hat. Über diesen Weg kann ein Slave 
theoretisch sogar die Taktfrequenz des TWI Busses an seine Bedürfnisse 
anpassen, indem er jeden Takt verlängert.

Die Empfangslogik auf Masterseite funktioniert bei den einfachen TWI 
Mastern im übrigen genauso. D.h. sobald ein Byte empfangen wurde wird ja 
normalerweise irgendein "Ready" Bit gesetzt. Dieses Bit ist 
hardwareseitig mit der Taktlogik verschaltet, so dass die Taktleitung 
auf Low-Pegel gehalten wird, bis die Applikation die Daten gelesen hat 
und dann eventuell noch explizit das Bit löscht. Beim AVR8 ist dieses 
Bit im übrigen direkt das Interrupt Flag welches den Interrupt auslöst. 
Erst wenn dieses Interruptflag gelöscht wird, liest der TWI Master das 
nächste Byte vom Slave ein.

von M. K. (sylaina)


Lesenswert?

Andreas M. schrieb:
> Wenn nun der Slave von dem Master ein
> Byte empfangen hat und noch nicht bereit ist ein nächstes zu empfangen,
> dann kann er einfach die Clock Leitung weiterhin auf Low Pegel halten um
> zu verhindern das der Master weiter Daten senden kann.

Und wie soll das dein Slave machen wenn du den mittels Debugger 
angehalten hast? Oder anders gesagt: Das sind Funktionen, die halt auch 
implementiert sein müssen.

von Andreas M. (amesser)


Lesenswert?

M. K. schrieb:
> Andreas M. schrieb:
> Und wie soll das dein Slave machen wenn du den mittels Debugger
> angehalten hast? Oder anders gesagt: Das sind Funktionen, die halt auch
> implementiert sein müssen.

Ich debugge nicht den Slave sondern den Master. Es geht hier auch gar 
nicht um den Slave sondern um das merkwürdige Verhalten des Masters im 
SAM4S. Mal abgesehen davon ist es der TWI Peripherieeinheit völlig 
wurscht ob die CPU steht oder nicht, deswegen ist es ja eigenständige 
Hardwareunit geworden.

von Klaus (Gast)


Lesenswert?

Andreas M. schrieb:
> Ergebnis ist, dass das TWI Master Modul im Read Modus
> tatsächlich kontinuierlich Daten liest. Erst wenn man eine STOP
> Bedingung per Kontrolregister auslöst hört das auf.

Da fehlt mir etwas: die gelesenen Bytes müssen jeweils mit ACK quitiert 
werden bis auf das letzte. Das braucht ein NAK. Das muß man aber 
berücksichtigen, bevor man das Lesen des letzten Byte startet. Das Stop 
am Ende ist eigentlich weniger wichtig, ich kenne einige Slaves, die 
ohne NAK beim letzten Byte trotz STOP dauerhaft hängen.

MfG Klaus

von M. K. (sylaina)


Lesenswert?

Andreas M. schrieb:
> Mal abgesehen davon ist es der TWI Peripherieeinheit völlig
> wurscht ob die CPU steht oder nicht, deswegen ist es ja eigenständige
> Hardwareunit geworden.

Und woher weis die, dass die CPU den Empfangspuffer gelesen hat?
Das Problem ist meiner Ansicht nach, dass du eine Vorstellung hast, wie 
TWI funktionieren muss, und so hat es deiner Meinung nach schon immer 
funktioniert und jetzt funktioniert es nicht so was dich schwer 
verwundert (würde es mich auch). Aber diese Funktionalität, die du dir 
vorstellst, muss halt auch explizit implementiert sein.
Du hast ja selbst geschrieben: Der TWI ist es egal was die CPU macht. 
Warum also z.B. sollte die TWI den Clock anhalten wenn du die CPU 
anhälst?

von Andreas M. (amesser)


Lesenswert?

Klaus schrieb:
> Andreas M. schrieb:
> Da fehlt mir etwas: die gelesenen Bytes müssen jeweils mit ACK quitiert
> werden bis auf das letzte. Das braucht ein NAK. Das muß man aber
> berücksichtigen, bevor man das Lesen des letzten Byte startet. Das Stop
> am Ende ist eigentlich weniger wichtig, ich kenne einige Slaves, die
> ohne NAK beim letzten Byte trotz STOP dauerhaft hängen.

Genau so sehe ich es auch. Beim ATmega oder beim PSoC ist das auch genau 
so gelöst. Der SAM4S macht das Nak automatisch wenn man den STOP 
auslöst. Aber ein ATmega liest halt genau ein Byte und wartet dann 
solange bis ich in meinem Programm sage Ack/Nack und weiterlesen oder 
nicht und genau das tut der SAM nicht.

M. K. schrieb:
> Andreas M. schrieb:
> Und woher weis die, dass die CPU den Empfangspuffer gelesen hat?

na vielleicht deswegen weil die CPU einen Lesezugriff auf das 
Empfangsregister der TWI macht? Meinst Du nicht das der TWI Einheit 
merkt wenn etwas auf Ihre Register zugrifft?
Was denkst Du denn wie in deinem PC die Grafikkarte oder der 
Festplattencontroller mitbekommt wenn die CPU was von ihm will? Ich 
verrate es Dir: Genau so wie der TWI oder jede andere Peripherieeinheit 
in einem
Mikrocontroller das mitbekommt.

Du hast wirklich die faszinierende Fähigkeit einem jedesmal das Wort 
völlig sinnentfremdet im Mund zu verdrehen!

von M. K. (sylaina)


Lesenswert?

Andreas M. schrieb:
> Du hast wirklich die faszinierende Fähigkeit einem jedesmal das Wort
> völlig sinnentfremdet im Mund zu verdrehen!

Öhm, meine Fragen/Antworten haben nicht den Sinn dir das Wort im Mund zu 
verdrehen. Es tut mir leid wenn du das so verstanden hast.

Warum Frage ich dich, wie der TWI mitbekommt, dass die CPU das 
Empfangsregister ausgelesen hat? Nun, ich habe dieser Tage, wie schon 
gesagt, am Atmega328 mit dem i2C gearbeitet. Ich habe bisher noch nicht 
gesehen wie der TWI mitbekommen haben soll, dass die CPU auch das TWDR 
ausgelesen hat. Ich hab hier aber sich auch noch einiges zu lernen.

von Klaus (Gast)


Lesenswert?

Andreas M. schrieb:
> Der SAM4S macht das Nak automatisch wenn man den STOP
> auslöst.

Dann ist aber das letzte Byte schon längst durch und hat damit schon 
längst ein ACK bekommen.

Andreas M. schrieb:
> Aber ein ATmega liest halt genau ein Byte und wartet dann
> solange bis ich in meinem Programm sage Ack/Nack

Von den PICs kenne ich das so, daß man am Anfang des Lesens sagen muß, 
ob mit ACK oder NAK geantwortet werden soll. Also so etwa: Read with ACK 
oder Read with NAK.

MfG Klaus

von M. K. (sylaina)


Lesenswert?

Klaus schrieb im Beitrag #4840493
> Von den PICs kenne ich das so, daß man am Anfang des Lesens sagen muß,
> ob mit ACK oder NAK geantwortet werden soll. Also so etwa: Read with ACK
> oder Read with NAK.

Ist bei den Atmmegas auch so wenn ich das recht gesehen hab ;)

von Andreas M. (amesser)


Lesenswert?

M. K. schrieb:
> Warum Frage ich dich, wie der TWI mitbekommt, dass die CPU das
> Empfangsregister ausgelesen hat? Nun, ich habe dieser Tage, wie schon
> gesagt, am Atmega328 mit dem i2C gearbeitet. Ich habe bisher noch nicht
> gesehen wie der TWI mitbekommen haben soll, dass die CPU auch das TWDR
> ausgelesen hat. Ich hab hier aber sich auch noch einiges zu lernen.

Ja Da hast Du Recht. Bei den Atmels muss man glaube ich immer das 
Interruptbit schreiben damit er weiter macht. Ist aber schon länger her 
das ich mit denen was gemacht habe. Ich wundere michh halt das es beim 
SAM4S so anders funktioniert. Bei anderen SAMs gibt es wohl auch noch 
weitere Lösungen.
Ich hatte gehofft noch etwas bei der Bedienung falsch zu machen, denke 
aber das das Verhalten von Atmel tatsächlich so gedacht ist. Für meinen 
Anwendungsfall wird vermutlich trotzdem funktionieren.

von Andreas M. (amesser)


Lesenswert?

Nachtrag:

Es ist tatsächlich so, dass der TWI beim SAM4S im "Read"-Modus stupide 
die Daten liest ohne darauf zu warten, das die CPU die Daten aus dem 
Empfangsregister holt. D.h. wenn man den TWI im Read-Modus benutzt muss 
man entweder sicherstellen das die Leseroutine niemals unterbrochen wird 
(Interrupte, Debugger) oder aber den Peripheral DMA Controller (PDC) 
nutzen. Andernfalls, kann es passieren, das Daten verloren gehen. Der 
PDC holt die empfangenen Daten sofort ab und schreibt diese an einen 
beliebigen Speicherbereich im RAM. Glücklicherweise ist der PDC sehr 
einfach zu konfigurieren, im Unterschied zum Datenblatt konfiguriere ich 
jedoch immer die volle Datenlänge in den PDC und nicht minus 1/2 Bytes, 
sonst hätte ich bei den letzten Bytes das gleiche Problem wieder. Es 
werden dann natürlich immer mehr Bytes aus dem Slave Chip abgefragt als 
eigentlich notwendig, diese landen dann halt im Nirvana, der Slave Chip 
darf sich daran nur nicht stören. Wichtig ist, das man nach dem 
Lesevorgang noch einmal das TWI_RHR Register manuell ausliest, ansonsten 
bekommt man beim nächsten TWI Read als erstes dieses Datenbyte in seinen 
Puffer geschrieben.

Eventuell noch interessant zu wissen: Der TWI unterstützt kein Restart, 
man kann also (ohne Trick) nicht erst Write und dann Read machen ohne 
eine Stop-Condition dazwischen zu veranlassen. Ein erneuten Start zu 
machen, bei dem die Transferrichtung wechselt ist also nicht möglich. 
Manche Slave-Chips brauchen das aber. (Meiner :-) Mit einem kleinen 
Trick kann man jedoch einen Write-Read Transfer machen, wenn man nur bis 
zu drei Bytes im Write machen muss: Man kann dem TWI bis zu drei Address 
Bytes geben, die er, bevor der eigentliche Transfer stattfindet, per 
Write Transfer schreibt. Dabei macht er dann automatisch brav einen 
Restart mit Wechsel der Transferrichtung.

Andreas

von CPP (Gast)


Lesenswert?

Andreas M. schrieb:
> Es ist tatsächlich so, dass der TWI beim SAM4S im "Read"-Modus stupide
> die Daten liest ohne darauf zu warten, das die CPU die Daten aus dem
> Empfangsregister holt.

Kann ich leider nur genau so bestätigen. WTF

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.