Mal wieder: Zwangsdatenübertragung zwischen zwei µCs
von
am 09.03.2017 um 13:07 (5303 Hits)
Wie in früheren Blogeinträgen geschrieben, sollen Daten, die in einem µC anfallen, zu einem anderen µC, der als Schnittstellenumsetzer zu einem Flashspeicher zur dauerhaften Speicherung fungiert, übertragen werden.
Dazu habe ich früher schon verwendete Routinen modifiziert und jetzt eine Sende- und eine Empfangsroutine soweit fertig, daß sie anscheinend zuverlässig und schnell funktionien. Die beiden Routinen sind mit BASCOM in Maschinensprache für ATtiny861 und ATtiny25 geschrieben und im Augenblick in, per UART zu bedienendes Testprogrammen eingebettet. Die Testprogramme sind im Anhang zu finden und dienen wirklich nur zum Testen der Übertragung; Eingabefehler zB werden nicht abgefangen.
Beide µCs verfügen über einen "High Frequency PLL Clock", der den Systemtakt über den internen Oszillator auf 16Mhz bringt.
Die beiden µCs sind über zwei "Compelled Data Lines" (CDL0 und CDL1) und 1k Seriensicherheitswiderständen miteinander verbunden; gemeinsamer GND natürlich. Erster µC CDL0 - 1k Widerstand - zweiter µC CDL0. CDL1 - 1k - CDL1.
Datenübertragungsrate etwa 400kBit pro Sekunde und schneller.
Daten sind, bis sich etwas anderes als sinnvoll erweist, in Blöcken organisiert. Die ersten drei Bytes eines Blocks sind "Overhead". Das erste Byte des Overheads enthält ein Schreib-/Lese-Bit, das anzeigt, ob Daten zum Flash geschrieben oder gelesen werden sollen. Die übrigen 7 Bits geben die Blocklänge einschließlich der Overheadbytes an. Maximale Blocklänge also gleich 127. Im Test ist die Blocklänge = 11. Die Verwendung der folgenden beiden Overhead-Bytes ist im Augenblick noch offen, werden aber schon mal mit übertragen. Es folgen die Datenbytes, im Testprogramm sind es 8 Bytes. Ist ein Block komplett übertragen, beginnt ein neuer Block mit Overhead Bytes.
Die drei Overhead Bytes sollen am Stück übertragen werden. d.h. wenn der Sender/Master begonnen hat, die Overhead Bytes zu übertragen, sollte er nichts anderes machen, als nur die Übertragung. Später könnte er durch dringende Interrupts eventuell unterbrochen werden. Der Empfänger/Slave empfängt in einem Interrupt und bleibt in der ISR so lange, bis der Master eine "Übertragungspause" sendet oder ein Block vollständig übertragen wurde. In der Übertragungspause kann der Slave eigene Aufgaben anpacken wie zB Daten aus seinem Buffer zum Flash schicken - hoffentlich
Nach den drei Overheadbytes können die Datenbytes einzeln oder in Gruppen von mehreren Bytes byteweise, nicht bitweise, übermittelt werden. Wenn die Blocklänge noch nicht erreicht ist, wird eine Übertragungspause gesendet. Am Ende eines Blocks ist keine Übertragungspausesignal notwendig, da das Ende durch die Blocklänge im ersten Overheadbyte bestimmt ist.
Durch dieses Protokoll, bei dem jedes übertragene Bit quittiert wird, soll der Master in der Lage sein, die Übertragung jederzeit zu unterbrechen um andere äußere Ereignisse zu bearbeiten und dann die Übertragung wieder aufzunehmen. Der Empfänger/Slave wird bei Anlegen eines Bits vom Master über Interrupt "scharf" gestellt und kann notfalls sogar über eine Verzögerung der Quittung, den Master aufhalten. Einzig das neu eingeführte Signal zur Übertragungspause ist zeitkritisch. Hier muß man dem Empfänger genug Zeit geben, es zu erkennen.
Wahrscheinlich könnte man hier auch eins der herkömmlichen Methoden wie I2C, SPI, UART etc. verwenden. Bei dieser hier erwarte ich weniger Timingproblem und da selbst geschrieben einen besseren Debug-Durchblick Das selbst geschriebene Protokoll ist nur per Software implementiert, außer dem Interrupt vielleicht.
Und noch ein paar Screenshots
1. Übertragung der drei Overhead Bytes in ca. 57,20µs mit Übertragungspause am Ende
Zu Beginn sind CDL0 und CDL1 auf high Potential
Master zieht CDL1 (Oszi-Channel 2) auf low um eine "1" zu senden.
Slave geht in einen Interrupt und reagiert mit low auf CDL0 (Oszi-Channel 1)als Quittung.
Details besser in den nächsten Screenshots zu sehen.
2. Übertragung der Ziffer 1 in ca 20µs mit Übertragungspause am Ende
Master zieht CDL0 (Oszi-Channel 1) nach low um eine "0" zu übertragen.
Slave geht in einen Interrupt und reagiert mit low auf CDL1 als Quittung.
Darauf hin legt der Master wieder high auf CDL0
Der Slave nimmt die Quittung weg und CDL1 (Oszi-Channel 2) ist auch wieder auf high.
Der Master sendet das nächste Bit; Wieder eine "0" mit low auf CDL0 (Oszi-Channel 1).
Slave ist immer noch in der ISR und reagiert mit Quittung auf CDL1 (Oszi-Channel 2).
usw.
Da bei der Ziffer 1 das letzte Bit eine "1" ist, wird vor der Übertragungspause (Sender legt CDL0 und CDL1 "gleichzeitig" auf low) vom Master zuerst CDL1 (Oszi-Channel 2) auf low gezogen und vom Slave auf CDL0 (Oszi-Channel 1) quittiert.
Zum Schluß noch das Übertragungspause-Signal, da der Block noch nicht komplett übertragen ist.
3. Übertragung der Ziffer 1 in ca 19µs ohne Übertragungspause (letztes Byte im Block)
Wie unter 2. Hier ist das übertragene Byte das letzte im Block. Deshalb fehlt das Übertragungspause-Signal.
4. Übertragung der Ziffer 1 und 2 hintereinander in ca 38,8µs mit Übertragungspause am Ende.
Hier werden zwei Bytes ohne Pause übertragen. Es sind nicht die letzten Bytes im Block; deshalb noch das Übertragungspause-Signal am Ende.