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?
Benutzt du denn die ASF Quellen? Bzw. hast du ein passendes ASF Beispielprogram ausprobiert?
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....
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.
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.
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.
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.
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.
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.
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.
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
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?
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!
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.
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
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 ;)
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.