Liste der Anhänge anzeigen (Anzahl: 1)
So.. der Fehler mit hängen bleiben lang tatsächlich an E_INT1.
Kurze Beschreibung dazu: Ich habe eine pcf8583 Uhr am i2c hängen dessen INT Leitung am E_INT1 der Base liegt. Dies ist ansich ein harmloser ADC-Port. Ich möchte deren Alarmfunktion später mal nutzen.
Die Uhr gibt wenn das Register 0 mit 0 beschrieben ist, pro Sek ein Impuls aus. Ich hatte dem Baustein das die Tage abgewöhnt aber irgend ein rumflitzendes Byte auf dem i2c bus hat es zurück gesetzt. Die Base juckt das nicht weiter, für sie ist das nur ein normaler Port an dem jemand klopft. Die Leitung ist aber auch über den XBUS an den INT1 der M32 geführt was ein echter Interrupt ist - und ich nicht bedacht hatte. Dem zu Folge löste die M32 pro Sek ein irq aus wo der Master drauf läuft. Die INT Leitung hat eine höhere Priorität als TWI - daher wurde die TWI immer wieder unterbrochen was zu Timingproblemen und letztlich zum Abbruch des Datenflusses führte.
Für euch interssant ist eigentlich die Info, das wenn man den E_INT1 z.B. als Ausgang nutzt - warum auch immer - ihr damit die M32 quasi ständig in eine ISR schickt. Ich finde das sogar sehr gut durchdacht vom Entwickler... nur darf man das halt nicht vergessen wenns um die Leitung geht. Die E_INT1 ist als Steuerleitung Tabu wenn man eine M32 oder vermutlich auch M128 nutzt. Eigentlich logisch aber man denkt eben nicht immer dran.
Nun zum TWI. Ich hab euch meine aktuellen Files zum Projekt bzw. Dirks modifiziertes Testprogramm zusammen mit der TWI in ein Zip gepackt. Damit können jetzt auch mehr Leute mal versuchen wie es klappt. Achtet bitte auf Pfade und Abhänigkeiten im makefile und kommentiert die defines zum lcd und das lcd.h aus wenn ihr kein i2c lcd mit pcf Baustein habt. Benötigt zum testen mit Dirks Programm werden die Base, eine M32 sowie ein M32Display.
I2CTWI_isBusy() (bit_is_set(TWI_statusReg,STR_isr))
#define I2CTWI_needAction() (bit_is_set(TWI_statusReg,STR_needAction) && bit_is_clear(TWI_statusReg,STR_isr))
#define I2CTWI_waitAction() (bitset(TWI_statusReg,STR_needAction))
#define I2CTWI_doneAction() (bitclr(TWI_statusReg,STR_needAction))
#define I2CTWI_NACKonAction() bitset(TWI_statusReg,STR_NACKonAction)
#define I2CTWI_ACKonAction() bitclr(TWI_statusReg,STR_NACKonAction);bitclr(TWI_ statusReg,STR_needAction)
Das hier sind Befehle, die für die Ablaufsteuerung relevant sind. Sie fragen oder setzen alle Flags ab die die ISR steuert.
I2CTWI_isBusy() ist gesetzt wenn die ISR ein Datagram überträgt. Egal ob als Master oder Slave, vom Start bis zum Stop.
Achtung, die Befehle
I2CTWI_requestRegisterFromDevice
und
I2CTWI_readRegisters
bestehen je aus 2 Einzelbefehlen in denen die ISR zwischendurch "Frei" meldet was zur Ausführung nachfolgend wartender TWI Befehle führen kann. Dafür muss ich noch eine Lösung stricken. Alle anderen TWI-Befehle sind Einzelbefehle, da sollte das Problem nicht auftauchen.
I2CTWI_needAction() prüft ob die Slave Register beschrieben wurden was mit einem gesetzten Bit angezeigt wird. Wenn ja, sollte der Slave als Zeichen das er die Daten verarbeitet hat immer I2CTWI_doneAction() ausführen was das Bit zurück setzt. Der Master hat dazwischen keine Schreibmöglichkeit und wird geblockt (was der natürlich auch über I2CTWI_isBusy() merken kann). Will man den Master ohne vorherige Schreiboperation zwingen zu warten (was eigentlich nur für mich zum testen relevant ist) nutzt man I2CTWI_waitAction() was das schreiben der Register simuliert. Soll der Master immer schreiben können (Verhalten wie bisher, führt zum überschreiben von Registern) nutzt man I2CTWI_ACKonAction(), mit I2CTWI_NACKonAction() blockt der Slave wieder das überschreiben.
Das Blocken geschiet durch senden von NACK wäred der Master ein Datenbyte auf ein bereits beschriebenes Registerset schreiben will, was wiederum mit einen neuen Anlauf der Übertragung mündet bis er erfolgreich war. Quasi eine Endlosschleife. Das Beschreiben des Adressbytes müsste aber noch gehen so lange der Master keine Daten mitsendet. Zur Not könnte der Master also auch noch darüber dem Slave was mitteilen. Morsen sozusagen... Vielleicht eine Möglichkeit für weitere Master zu signalisieren, wenn sie Daten haben und der Slave gefälligst die Register frei zu geben hat.... aber das ist dann schon leicht abgedreht und scheitert noch an fehlender Busarbitierung :). Derzeit ist der Bus belegt wenn der Slave nackt und ein 2.ter Master müsste den ersten von der Leitung schubsen um reden zu dürfen, wobei sich der erste vermutlich dann gehörig verschluckt. Bildlich gesprochen...
I2CTWI_waitAction() werde ich vermutlich wieder entfernen da es für euch kaum Sinn macht. I2CTWI_(N)ACKonAction() wird bleiben.
Die Variablen
I2CTWI_genCallCMD
I2CTWI_dataWasRead
I2CTWI_dataReadFromReg
I2CTWI_readBusy
I2CTWI_writeBusy
sind obsolet, I2CTWI_genCallCMD tut es eh nicht weil gencalls derzeit garnicht gehen, die anderen 4 Vars machen quasi das gleiche wie I2CTWI_isBusy() und I2CTWI_needAction() mit der Ausnahme das sie nun auch zu gebrauchen sind und den Ablauf am TWI beeinflussen.
Konfiguriert wir die Anwendung mit twi_target.h, sie ist selbsterklärend, jedes Projekt hat sein eigenes File. Es gelten die üblichen Vorgaben für TWI.
Flags wie DEBUG, XDEBUG können kommentiert wreden (//) dabei bedeutet:
TWISLAVE=Slave & Master
TWIMASTER=Master
TWILOW=(Slave & Master | Master) & TWILOW
Ich glaube, es geht nichts kaputt wenn man TWISLAVE und TWIMASTER setzt aber es ist doppelt gemoppelt. TWILOW sind Bascom ähnliche Funktionen die - wenn genutzt - das Handling auf dem TWI erlauben ohne das die ISR dazwischen funkt. Dazu müssen die Funktionen ein paar Dinge berücksichtigen, insbesondere das Ausschalten des TWI Interrupts und das Einschalten wenn man fertig ist. Gedacht ist das zum debuggen eigener Devices/Hardware, man kann sich natürlich auch kompexe Funktionen daraus basteln die mit der ISR koexistieren. Damit ist jedoch kaum Slave Betrieb möglich oder man müsste wie blöde TWI-Register pollen, daher nur einfache Masterfunktion.
Im Base Programm sitzt noch ein vagabundierender extINT Befehl, der kann/muss raus... und einige Kommentare wo ich am basteln war.. kann auch raus.
Ich bin mir noch nicht sicher wie die TWI auf Busarbitation reagiert, grundsätzlich können und dürfen am Bus mehrere Master laufen. Evtl. stürtzt aber die aktuelle TWI ab bzw. baut Mist. Aber es geht nichts kaputt.
Wer möchte, kann also Dirks Programm so umbauen das auf beiden Prozessoren Master und Slave laufen und die sich gegenseitig Daten zuwerfen und abfragen.... schlimmstenfalls bleiben die Programme nur nach einigen Bytes hängen. Nur hätte ich den Source dann bitte gern am Montag da ich dann auch die Arbitation in Angriff nehmen kann. :) Sonst muss ich mir das erst selbst schreiben.
Das sind mal grob alle wichtigen Infos zusammen gepackt.
Sonst schaut auch mal in die .h und .c files ... die beissen nicht...
Der compilerlauf mit gcc klappt hier, wenn was nicht klappt, bitte zuerst in der twi_target prüfen. Dirks Programm testet alle 4 Teilfunktionen der TWI, also MR/MT/SR/ST und sollte damit auch in eigenen Projeken funktionieren. Alles weitere findet sich auch im Thread hier.
Ich hab am WE keine Zeit und werde mich erst Montag wieder intensiv darum kümmern, ihr habt also die Möglichkeit damit zu spielen bevor ich wieder alles auf den Kopf stell. :) Es werden noch weitere Veränderungen und Betatests kommen, insbesondere Fabian sollte mit der Lösung und Remotrol aber schon arbeiten können. Sonst fragt einfach hier, ich werde sicher mal reinschauen am WE.
LG Rolf
Liste der Anhänge anzeigen (Anzahl: 1)
6502 ? nettes Teil... auch einer der mit ner Brotkiste angefangen hat? :) Mein erster war ein ZX81 :) Hach ja die alten Zeiten ... :)
Aber zur TWI. Ich war unzufrieden, das der IRQ mir die Daten auf dem i2c zerbröselte - auf Grund der Sache mit der Uhr - und hab eine Lösung gefunden. Einfach aber effektiv. Die ISR wird zukünftig (steuerbar über twi_target.h) im Eingang ein cli(); ausführen und im Ausgang ein sei(); , das verhindert nach nun 24h lang laufenden Dauertests absolut zuverlässig die Unterbrechung und Abbruch trotz sekündlichen Uhrenticks. Wird in der nächsten Release drin sein.
Dann freut es mich erst mal sehr, das Du reproduzierbar stabile Funktion berichten kannst. Zu Deiner Frage, nun wenn Du dich nicht um das "Protokoll" kümmern willst, kannst Du mit I2CTWI_ACKonAction() kurz nach der Initialisierung das so einstellen, das der Master nicht behindert wird.
I2CTWI_init()
I2CTWI_ACKonAction();
...
Programmlauf
...
Wenn aber dein Programm auf der Base sowas wie ein Handshake braucht, (Fabians Remotrol braucht das z.B. zwingend) oder verhindert werden muss das der Master Daten überschreibt (weil Befehlssequenzen übertragen werden, kommst Du um eine Verarbeitung der Daten/Befehle und letztlich auch einem Handshake.. nicht rum. Da bietet sich die default Einstellung bzw. I2CTWI_NACKonAction(); und dann endsprechendes bearbeiten mit I2CTWI_needAction() und I2CTWI_doneAction() an.
Es kommt also ein wenig auf deine Anforderungen an das Programm an, es gibt keine ja/nein Antwort dazu. Man kann überlegen, die Defaulteinstellung auf I2CTWI_ACKonAction zu setzen was dem alten Verhalten entspricht, ohne ein Handshake ist allerdings eine gesicherte Datenübertragung nicht möglich. Vergleich es mit den RTS/CTS Leitungen und dem Software Protokoll XON/XOFF, es würde auch keiner eine stabile UART ohne die Leitungen betreiben können und wenn doch, so muss zumindest das Softwareprotokoll XON/XOFF vorhanden sein. I2C hat kein RTS/CTS bzw. XON/XOFF, also braucht es da was anderes, die ACK/NACK Signale sind quasi eine Mischumg aus beidem und ohne die klappt so gut wie nix wirklich sicher auf dem Bus - der alte Treiber welcher alles ACKte, ist bester Beleg dazu. Natürlich muss man sich als Programm... nein.. man muss nicht, man kann... sich drum kümmern... und sicher stellen das die Daten korrekt verarbeitet werden. Aber es gibt auch Anwendungen wo das nicht so wichtig ist. Das entscheidest letztlich Du als Programmierer bzw. die Aufgabenstellung.
Man kann grundsätzlich das Ganze in ein Task packen und mit einem
If I2CTWI_needAction() task_do_i2c();
erledigen, wo dann halt in task_do_i2c alles verarbeitet wird. Incl. einem I2CTWI_doneAction(); am Taskende. Die Libs und Examples liefern dazu reichlich Beispiele. Das hatte ich in deinem Programm auch schon im Kommentar irgendwo angemerkt. Ich werde dazu am Montag ein kleines Beispiel bauen, denke aber das ihr da jetzt schon mit klar kommt.
Eigentlich reicht für das genannte Programm also:
while (true)
{
die_üblichen_System_Tasks();
If I2CTWI_needAction() task_do_i2c(); //Receiver bedienen (Daten kopieren wie im Slavebeispiel)
Master_task();//Selber aktiv werden, so wie in dem Masterbeispiel
}
Das ist echt nicht kompliziert, Du hast bereits alles geschrieben da was wir da brauchen...
LG Rolf
PS: Ich hab noch was für Dich Dirk, extra eben noch geknipst :) Du wirst sie erkennen, für die anderen: Eine 6502 CPU von MOS aus dem Jahr 1983 aus meiner Grabbelkiste. Hier noch bissel Text dazu. http://de.wikipedia.org/wiki/MOS_Technology_6502
Die 6509 war ein direkter Verwandter und wurde im CBM610 z.B. verbaut. http://www.zock.com/8-Bit/D_CBM610.HTML Ich hatte auch mal einen. Und nicht zu vergessen die allseits berühmte 6510 CPU aus dem C64 und die 6508 aus dem NES :) Eine Z80 CPU aus der Generation hab ich auch noch, und hüte sie wie Dagobert Duck sein ersten Taler :)
EDIT: Ich hab über die Handshake Geschichte nachgedacht und stelle fest, das es da noch einiges zu verbessern gibt. Z.B. kann der Masterzugriff bisher nicht beeinflussen was bei einem NACK passiert, bzw. ist einem hängendem Slave quasi ausgeliefert. Das ist unschön und wird demnächst behoben. Beide Seiten werden also steuern können, ob und wie sie mit NACKS umgehen. Dazu wird die ISR ein weiters Flag bekommen, das mit 1 oder 2 Funktionen/Macros steuerbar ist.
Liste der Anhänge anzeigen (Anzahl: 1)
Ich hab mir scheinbar doch was am SDA Pin der CPU zerstört.
Hier eine kurze Diganoseanleitung, alles natürlich OHNE angebaute Teile am I2C Bus mit dem Oszi und einem Multimeter geprüft!
SDA verhält sich so als wenn kein Pullup (R32) da wäre, der ist aber gewechselt und mehrfach getetet. Darauf hin habe ich die Ports SCL und SDA als Ausgang geschaltet und volle Rechteckflanken gemessen, schaute also gut aus. Als Ausgang ist das ok. Hier der Code dazu.
Code:
while (true) {
DDRC |= (SCL | SDA);
PORTC |= SCL;
PORTC |= SDA;
mSleep(100);
PORTC &= ~SCL;
PORTC &= ~SDA;
mSleep(100);
}
Dann SDA und SCL als Eingang geschaltet und den Prozessor die Werte ansagen lassen.
Code:
PORTC &= ~SCL;
PORTC &= ~SDA;
DDRC &= ~SDA;
DDRC &= ~SCL;
while (true) {
writeString_P("SCL / SDA -> ");
writeInteger(PINC & SCL , BIN);writeString_P(" / ");
writeInteger(PINC & SDA , BIN);writeChar('\n');
mSleep(500);
}
Ergebnis war, das beide Pins zunächst logisch 1 hatten, der SDA aber manchmal auf 0 kippte. Mit einer Brücke konnte ich beide Pins gegen GND auf 0 ziehen, was ok ist, SCL sprang danach sofort auf 1. SDA kippelte zwischen 0 und 1. Gemessen habe ich am SDA dabei 1,4v statt der erwarteten 4v wie am SCL. Das erklärt das kippeln, ein Verhalten wie bei fehlendem R32 nur das dann 0,7 statt 1,4v zu messen sind.
Also noch mal R32 ausgebaut, gemessen, anderen besorgt, eingebaut... immer das gleiche. SlyD gab mir dann den Tip, mal einen Diodentest zu machen.
Zitat:
Was misst Du mit dem Multimeter im Diodentest (gegen GND und VDD bei beiden I2C Pins in allen Kombinationen also Rot/Schwarzes Kabel auch tauschen)? Das sollte bei beiden Pins identisch sein. (0,7V 0,6V 1,6V 1,7V sowas in der Richtung je nachdem wie mans polt)
Der Diodentest zeigt eine Auffälligkeit.
Mit - am SDA/SCL gegen gnd gemessen 0,5v, gegen vdd 1,5v
Mit + am SCL gegen gnd gemessen 1,7v, gegen vdd 0,6v
Mit + am SDA gegen gnd gemessen 1,2-1,0v, gegen vdd 0,4-0,3v und schwankt ein wenig
Meine Folgerung daraus ist, das der Port SDA als Eingang in der CPU einen Schaden hat. Ich glaube nicht an einen Fehler durch den Dauertest oder beschädigung durch Software, vermutlich eher statische Entladung oder der defekten Slave. Es wäre aber auch denkbar das der Slave dabei mit zu Bruch ging (was bedeuten kann, das die M32 auch im Eimer ist). Werde ich gleich noch per Diodentest durchmessen.
Da ich mir nicht zutraue, die CPU selbst zu wechseln, werde ich den RP6 wohl zur reparatur einschicken müssen und mit dem TWI Treiber länger pausieren.
Ich hänge meine letzte aktuelle TWI-Version noch an, sie müsste so ziemlich laufen, testen kann ich sie leider nicht mehr. Wichtigste Änderung ist die Umstellung aller Masterfunktionen auf asyncronen Betrieb da es immer wieder zu Problemen kam, wenn man syncrone und asyncrone Funktionen mischte. Man kann die Befehle aber quasi syncronisieren wenn man nach dem TWI-Befehl sofort task_I2CTWI aufruft, ein folgender TWI-Befehl würde das auch tuen. Es ist also nur für den ersten/letzten in einer Kette von Befehlen sowie bei I2CTWI_requestRegisterFromDevice und I2CTWI_readRegisters relevant, welche aus Mehrfachinstruktionen für die TWI bestehen - sowie für die Fehlerprüfung die auch dort abgewickelt wird. Anders ausgedrückt, es wird immer erst ein Befehl ausgeführt wenn ein weiterer abgeschickt wird oder mit task_I2CTWI nachgeholfen wird. Das ist in zeitkritischen Situationen wie Abfragen eiens SRF zu bedenken. Es erlaubt aber die einstufige Entkoppelung einer TWI Aktion wenn man selbst zeitkritische Dinge zu erledigen hat, die nichts mit dem TWI zu tun haben. Jede Medaille hat eben 2 Seiten. Die Idee dafür stammt übrigends aus SlyDs TWI Version wo es dann manchmal (für den User zuweilen schlecht nachvollziehbar) zu verzögerten TWI-Reaktionen kam, ich habe das nun auf alle Funktionen umgesetzt, damit das Verhalten eindeutig ist.
Wer oft syncrone Funktionen braucht, kann sich mit einem Macro Set ala #define SyncTWIBEFEHL TWIBEFEHL;task_I2CTWI(); für jeden Befehl ähnlich der LCD-Macros in twi_target.h oder einige Macros in RP6I2CTWI.h das Ausführen direkt hinten dran klatschen. Allerdings spart das (noch) nicht den Aufruf von task_I2CTWI(); in der Idle-Loop ein. Ich hatte vor, das später per twi_target.h einstellbar zu machen ob generell sync oder async gearbeitet werden soll.
LG Rolf
Liste der Anhänge anzeigen (Anzahl: 1)
Sooo... wieder mal neues vom TWI.
Folgendes... der Treiber ist BETA und noch nicht fertig. Ich kann ihn noch nicht zur allgemeinen Nutzung frei geben. Er funktioniert aber schon mal soweit, das man es sehen kann und ich denke, zum betatesten langts auch schon mal.
Basis zum testen ist weiterhin Dirks Programm, was ich leicht modifiziert habe. Beide Programme (Base/M32) sind beigefügt, incl. der dazugehörenden TWI_TARGET.H
Es sind einige Optionen hinzu gekommen in twi_target, ansich sind sie aber dort jeweils kurz erklärt.
Was passiert da jetzt genau?
Nun auf beiden CPUs läuft jeweils ein masterfähiger Slave. Die beiden werfen sich Daten zu, die sie umkopieren so das die wieder abgeholt werden können. Die Ergebnisse werden vom Master verglichen und wenn Fehler auftauchen, werden diese erkannt und ausgegeben.
Starten tuen die jeweiligem Mastertasks z.Z. nur auf verlangen, das heisst beim drücken der Bumpertasten bzw. Key 1 auf der M32. Das habe ich deshalb gemacht, weil die sich z.Z. noch gegenseitig überrennen würden, wenn aber nur je einer sendet, klappts. Kann man einfach testen indem man auf beiden Boards die Taster drückt. Ziel wird sein, das beide auch dauerhaft senden können. Dafür ist das System jedoch noch nicht robust genug. Daher auch Beta. Derzeit dürften es die beiden Funktionen I2CTWI_request* nicht tuen.... also nicht wundern. Auch ein Grund für Beta.
Es gibt neben dem normalen Debug nun ein Debug für eine State Engine, diese überwacht ob ein kompletter Transport erfolgte (incl. Stop) sowie eine allgemeine Ausgabe für Bufferüberläufe.
Es gibt da noch ein paar ungereimtheiten im Timing, ich hoffe aber das beseitigen zu können. U.a. gehen ab und zu Daten verloren bzw. ist der Slave der Meinung, das Daten reinkamen obwohl die Register noch nicht beschrieben wurden. Je mehr Befehle in der ISR ausgeführt werden - und sich damit das Clocksignal streckt - um so seltener werden die Fehler. Es macht dabei z.B. einen Unterschied ob man die Stateengine einschaltet oder nicht. Das sind vielleicht 20 Maschinenbefehle mehr als sonst... also keine wirklich langen Zyklen. Mir ist aber nicht klar warum das so ist. Es gehen aber bis auf dieses kleine Problem keine Daten flöten, der Master macht bis zu 10 neue Anläufe mit je 5ms Pause dazwischen (alles einstellbar), der Slave nackt wenn er Busy ist und so kommen normal auch alle Daten zielsicher an.
Viel Spass beim testen
LG Rolf
EDIT: Einen längeren Test über mehrmalig je 1-2 Std. überstanden mein reparierter RP6 und der 2.te damit auch schon. Also keine Sorge. Übrigends sind seid der Reparatur komischer Weise ALLE Buserrors weg.
Edit: Weitere Änderung, ich hatte nicht bedacht, das bei Dirty Regs der Host (Slave) zwar ein weiteres Schreiben mit I2CTWI_doneAction(); frei geben muss, der Client (Master) aber die Regs bisher auslesen kann wärend der Slave sie ändert bzw. bearbeitet - was vor allem auf der schnelleren M32 zu Fehlern führt. Daher muss man die case TWI_STX_DATA_ACK gegen Folgende austauschen. Dies verhindert dann ein Auslesen wenn der Client noch nicht so weit ist - auch wenn kein Registerpointer geschrieben wird.
Code:
case TWI_STX_DATA_ACK: // 0xB8 TW_ST_DATA_ACK Data byte in TWDR has been transmitted; ACK has been received
if (TWI_statusReg.needAction && TWI_statusReg.NACKonAction) { //if Registers dirty, now send nacks
#ifdef DEBUG
logmyaction(TWI_STATUS,"/ STX_(ADR|DATA)_ACK NACK (Slave busy)");
#endif
TWI_statusReg.SendNACK=1; //dead end, master must retry, I2CTWI_doneAction/TWINIT will reset this
} else {
if (current_register < I2CTWI_SLAVE_READ_REGISTERS) {
TWDR = I2CTWI_readableRegisters[current_register++];
TWI_statusReg.SendACK=1;
#ifdef DEBUG
logmyaction(TWDR,"<- STX_DATA_ACK -> ACK (data)");
#endif
} else {
#ifdef DEBUG_MISC
writeString_P("Register read boundary violation\n");
TWI_statusReg.SendNACK=1;
#else
TWDR = 0;
TWI_statusReg.SendACK=1; // THIS should not happen... count your Regs please...
#endif
}
}
break;
Dieser Fix ist für eine Anwendung wie in dem RP6-Slave weniger wichtig, in Dirks Programm jedoch, wo sich beide CPU's mit Daten bewerfen und requesten spielt es eine gewichtige Rolle.
Damit macht nun auch ein weiterer Befehl in der RP6I2CTWI.h Sinn.
#define I2CTWI_doAction() TWI_statusReg.needAction=1
was quasi den Slave jederzeit in die Lage versetzt, dem Master anzuzeigen das er grade keine Daten kriegt, was man aber durch
I2CTWI_doneAction(); auch wieder freigeben sollte. Dabei sind die Retrys und der Timer in twi_target.h zu berücksichtigen.
Der Slave sollte also nur max so lange die Regs blockieren wie sich aus den beiden Zahlen Millisekunden + Reserve ergeben.
Leider liefern die asyncronen Funktionen ja kein echten Errorcode zurück, sonst könnte man das besser abfangen.
Kleine Änderung für TWI_MRX_ADR_NACK, bisher wurde hier ein Error initiiert, dies sollte durch ein Restart ersetzt werden. Zum einen entscheidet der Retrycode ob und was ein Error ist, zum anderen ist ein NACK auf Grund von "Device Bussy" ja kein Grund, den ganzen Transport abzuwürgen. Die case TWI_MRX_ADR_NACK wird daher ersetzt mit:
Code:
case TWI_MRX_ADR_NACK: // 0x48 TW_MR_SLA_NACK SLA+R has been transmitted and NACK received
#ifdef DEBUG
logmyaction(TWDR,"<- MRX_DATA_NACK RESTART (busy)");
#endif
TWI_STATUS_state = TWI_STATUS;
TWI_statusReg.SendStop=1;
TWI_old_operation = I2CTWI_NEED_RESTART;
break;
Das System verhält sich damit bei einem NACK im Master Receive (MRX) Mode genau so wie im Master Send (MTX) Mode und versucht es erneut bis die Retry Defaults aus twi_target.h erreicht sind.
EDIT:
Ich habe ein weiters Problem gefixt, der Slave war zu früh der Meinung, das der Transport fertig ist wesshalb teilweise Daten nur halb ankamen bzw. zu früh verarbeitet wurden. Die Änderungen im Code sind zu verstreut als das ich sie hier posten kann, es wird also demnächst wieder eine Beta geben. Ich suche z.Z. aber noch ein Fehler, der dann zu Stande kommt wenn beide CPUs quasi zeitgleich senden. Das ist ein Laufzeitproblem und hat wohl noch nichts mit Arbitierung zu tun.
Liste der Anhänge anzeigen (Anzahl: 2)
Es gibt mal wieder eine neue Beta.
Einige Fehler sind gegenüber der vorherigen Version behoben. Achtung, die TWI Einstellungen stehen z.Z. auf debug. Die Version läuft recht stabil und macht nur Probleme wenn beide Seiten gleichzeitig senden, da bleibt der Slave code dann wohl irgendwie hängen ohne das es zur arbitation käme.
In dem Code stecken mehrere "Verriegelungen" damit z.B. der Master nicht das Senden anfängt so lange der Slavecode noch empfängt. Ich hab das nun schon drei mal umgeschrieben aber da ich mich an viele Vorgaben des alten Treibers halte, gelingt es mir bisher nicht, gewisse Probleme wasserdicht zu lösen.
Die Version ist also wie die vorherigen eine Beta bzw. "Zwischenstand".
Um den Master zu aktivieren muss man hier T1 auf der M32 oder die Bumper auf der Base auslösen, ansonsten befinden sich die Boards im slave mode.
LG Rolf
EDIT: Für Leute die mal testen wollen ohne das Projekt zu bauen leg ich mal noch die hex-Files bei. Wie gesagt... Debug aktiv -> viel Textausgabe auf Console... Benötigt werden die Base, eine M32 und ein Display an der M32