Hallo,
ich hab ein kleines Problem an den ich nicht weiterkomme.
Ich habe für mein µC R8C/13 ein Programm geschrieben das ein
X_Timer-Interrupt und ein UART0_RX-Interrupt verwendet.
Der X_Timer hat ein Prioritätslevel von 1.
Der UART0_RX hat ein Prioritätslevel von 6.
1
txic=0x02;//Timer interrupt priority level = 2
2
s0ric=0x06;//UART0 interrupt priority level = 6
Das heißt das der UART0_RX-Interrupt "bevorzugt" wird. Ich habe nun das
Problem, dass ich den UART0_RX-Interrupt zwischenzeitlich auf ein
anderes Level ändern muss.
1
s0ric=0x01;//UART0 interrupt priority level = 1
Wenn ich den interrupt jetzt wieder auf Level 6 zurück ändern will,
funktioniert das ganze aber nicht.
Hast du vor der Zuweisung des neuen IPL das IR Bit getestet, ob noch ein
IRQ ansteht (requested ist)? Wenn das der Fall wäre, würde die Zuweisung
nicht funktionieren. (Hardwaremanual 19.2.6)
Mit dem Holzhammer könntest du diesen IRQ disablen, das IR Bit löschen
und dann die Zuweisung machen und dann den IRQ wieder enablen.
Damit keine Zeichen verloren gehen, könnte man auch anders arbeiten: In
der UART Interruptroutine ein globales Flag aus dem Userprogramm
abfragen, ob die IPL Maske geändert werden soll und entsprechend
reagieren. Zu diesem Zeitpunkt sollte die UART ja mit hoher
Wahrscheinlichkeit leer sein bzw. das IR Bit auf 0 stehen.
Tja was soll ich sagen. Unter debugbarem Code verstehe ich was anderes.
Der Codefetzen eingebettet in ein provisorisches main() konnte
fehlerfrei simuliert werden. s0ric konnte auf 0 bzw. 6 gesetzt werden.
ir_s0ric konnte gelöscht werden.
Interruptinitialisierung und Interruptroutinen fehlen ja, daher war
diese Simulation schnell erledigt :-)
Hast du irgendwo im Programm IPL im FLG Register geändert? Es darf nicht
6 oder 7 sein!
Hallo,
sorry. Ich schicke Dir am besten den kompletten Code sobald ich zuhause
bin. Du hast recht wenn Du sagst, dass man mit so ein paar Codefetzen
nichts anfangen kann.
Gruss
Hallo,
also das alles hat folgenden Hintergrund, vielleicht hast Du ja einen
besseren Lösungsansatz.
Zur Hardwareverschaltung:
Ich hab den R8C/13 über UART an das Bluetoothmodul BTM-222 verbunden.
Der BTM-222 ist über Bluetooth an ein Handy verbunden.
Zur Idee und Programmierung:
Ich habe im Code 2 Interrupts. Ein Time-Interrupt mit Level 2 und den
besagten UART0-Interrupt mit Level 6.
Der Time-Interrupt soll nichts anderes machen als alle 20ms (50 Hz) eine
Variable mit +1 zu Inkrementieren. Damit will ich Zeiten haben, die das
Programm "abbummeln" kann, der Code soll also z.B. 5000 ms warten bis er
den nächsten Schritt ausführt.
Der UART0-Interrupt soll dafür gut sein, dass er eine Funktion ausführt
(Empfangene Daten im Array ablegen), sobald er Daten von den verbundenen
Handy bekommt. Da ich nicht immer weiß wann die Daten kommen, hab ich
mir gedacht dies einfach mit einem Interrupt zu machen. Dieser ist
natürlich "höher gestellt" als der Time-Interrupt, damit mir Daten die
während des Time-Interrupts gesendet werden, nicht verloren gehen. Nun
hatte ich aber, in der Funktion Ueberwachung, folgendes Problem. In der
If-Schleife "Testanruf", habe ich eine Abfrage, nach dem Inhalt im Array
des UART0-Interrupts, und Warteschleifen. Das blöde ist jetzt, das das
Program an der Stelle nicht weitergeht und hängen bleibt. Ich hab
einfach mal den UART0-interrupt ausgeschaltet und es hat ohne Probleme
funktioniert. Ich kann jetzt nicht genau nachvollziehen warum sich das
so verhält, da sich im Array (empfangene Daten) nichts befindet, es
funktioniert aber so.
Daher kommt die Idee den "störenden" Interrupt kurzzeitig abzuschalten.
hast Du vielleicht eine andere Idee wie man das Problem lösen könnte.
Gruss
Mit dem letztens geposteten Codestück konnte ich dein Problem (UART RX
wird nach dem Ändern seines IPLs nicht mehr angesprungen) reproduzieren
aber noch nicht lösen. Das Problem interessiert mich und ich schaue
heute abend weiter danach. Gestern hat das HEW Einrichten und Projekt
aufsetzen die meiste Zeit verschlungen.
Jeder Interrupt hat sein eigenes Interrupt Request Flag, d.h. selbst bei
gleichem Interrupt Prioritätslevel gehen keine Interrupts verloren
wenn keine zwei Interrupts für den gleichen Vektor eintreffen. Wenn A
und B Interrupts bekommen und wenn A vorrangig zu B ist, wird B nach dem
RETI von A aufgerufen. Aber zwei Interrupts für B können eintreffen,
wenn ein (mehrere) vorrangige(r) Interrupt A zu lange abgearbeitet wird.
Bei einem default vorrangigen Timer X alle 20ms der bloß einen Zähler
erhöht gegen eine default nachrangige UART RX mit 19200 BAUD, sehe ich
da keine Gefahr. Das könnte man mal berechnen oder testen.
Dein Code hat auch noch ein Problem mit dem nicht-interruptfesten
Zugriff/Reset des Index i des RX-Datenpuffers wenn der RX-Puffer
entleert wird.
Ok, vielen dank für die Infos. Ich hab schon mehrere Probleme des Codes
gelöst und damit immerwieder neue Probleme ans Tageslicht gebracht. Ich
hba gemerkt, dass man dafür einen langen Atem braucht.
Stefan B. schrieb:> Das Problem interessiert mich und ich schaue> heute abend weiter danach.
Vielen Dank, ich bin mal gespannt. Ich versuche auch noch ein parr
Sachen vielleicht finde ich ja noch was.
Stefan B. schrieb:> wenn ein (mehrere) vorrangige(r) Interrupt A zu lange abgearbeitet wird.
Was heißt den "zu lange" ?
Stefan B. schrieb:> Bei einem default vorrangigen Timer X alle 20ms der bloß einen Zähler> erhöht gegen eine default nachrangige UART RX mit 19200 BAUD, sehe ich> da keine Gefahr. Das könnte man mal berechnen oder testen.
Wie berechnet man den sowas ?
Hast du vielleicht noch eine Idee warum im Eingangpuffer manchmal ein
paar empfange Daten verloren gehen. Wenn ich z.B. "atd0123456" sende,
bekomme ich manchmal nur"atd01" wieder, beim nächsten senden dann "atd"
und vielleicht beim 3. mal bekomme ich komplett auch das wieder was ich
sende. Deswegen habe ich dort eine Schleife eingebaut, die das Senden
sollange wiederholt, bis ich ein "OK" sehe. Damit umgehe ich das Problem
aber nur, vorhanden ist es trotzdem.
Gruss
Peter F. schrieb:> Wie berechnet man den sowas ?
Berechne die minimale Zeit zwischen zwei Zeichen bei 19200. Deine
Timerroutine muss entsprechend schnell abgearbeitet sein, damit kein
Zeichen verloren geht.
gk
So könnte ich mit dem Programm leben. Das zeitweilige Ausschalten des
UART0 RX beim Testanruf funktioniert jetzt IMHO. Eingaben über UART0 RX
während des Anrufes und in den Wartezeiten werden ersatzlos verworfen.
Nach dem Anruf wird der IRQ auch wieder eingeschaltet und weitere
Testanrufe sind über Eingaben über UART0 RX möglich. Ich habe nirgends
echt angerufen sondern mit einem Terminalprogramm simuliert.
Das ist ja schon eine weile her das ich mit dem r8c13 rumgespielt habe.
Aber warum machst du das in deiner Interruptroutine?
//Daten am Empfang (RX) abholen
while (!ri_u0c1);//Warten bis Empfangspuffer voll
Wenn der Interrupt aufgerufen wird dann solle es sichergestellt sein das
du ein Byte aus von deiner Schnittstelle abholen kannst. Dein while ist
also mindestens mal unnoetig. Und eine eventuelle Endlosschleife ist
sowieso schlecht und im Interrupt ist sie doppelt schlecht.
Kann es vielleicht sein das der Interrupt bereits dein Bit zuruecksetzt
und dein while auf das naechste Byte wartet?
Olaf
Peter F. schrieb
> Ui...da hast Du Dir ja richtig Mühe gegeben. Das werde ich natürlich> austesten und Dir Rückmeldung geben. Danke für die Hilfe erstmal.
Jo, ein paar Namen sind aussagekräftiger geworden und manche
auskommentierte Abschnitte aus deinem Original sind rausgeflogen. nicht
wundern bzw. aus dem Backup einpflegen, wenn es gebraucht wird.
Olaf schrieb
> //Daten am Empfang (RX) abholen> while (!ri_u0c1);//Warten bis Empfangspuffer voll>> Wenn der Interrupt aufgerufen wird dann solle es sichergestellt sein das> du ein Byte aus von deiner Schnittstelle abholen kannst. Dein while ist> also mindestens mal unnoetig. Und eine eventuelle Endlosschleife ist> sowieso schlecht und im Interrupt ist sie doppelt schlecht.
U.a. hatte ich mich über das Gleiche gewundert und auch in Olafs Sinn
geändert.
Hallo,
also ich hab das ganze mall ausgetest leider funktioniert der testanruf
nicht. Bzw. nach dem resetn funktioniert das ganze 1x dannach nicht
mehr.
Schade war ein Versuch. Aber bei so einem komplexen Projekt ist es
wahrscheinlich, dass man nicht 100% der Bugs mit dem ersten und einzigen
Schuß erledigt.
Ferndiagnostisch gesehen stehe ich mit
Beitrag "Re: Hardware-Interrupt R8C/13" im unbeleuchteten
Tunnel, Hände auf dem Rücken.
Vielleicht magst du ja die eingebauten Debug- und Simulationshinweise
verwenden, um herauszufinden, ob der R8C das Problemkind ist oder das
von mir nicht berücksichtigte BTM oder das von mir nicht berücksichtigte
Telefon.
Die nächste Maßnahme von mir an deiner Stelle wäre einen UART/RS232
Sniffer anzuklemmen und wenistens die Kommunikation zwischen R8C und BTM
abzuhören und zu loggen.
Hmm, Schade. Ein paar Sachen habe ich übernommen, da ich diese für
ziemlich gut und übersichtlich finde.
Hast Du denn eine Idee warum beim Empfang, der vom BTM gesendeten
Signale, hin und wieder mal etwas verschluckt wird ? Kann es mit den
Time-Interrupt zusammen hängen, so nach dem Motto: Wenn der
Time-Interrupt anspringt und wieder "zurückkommt" hat er in der Zeit ein
Zeichen übersehen. Aber das darf doch eigentlich nicht sein oder, der
Interrupt vom UART0 unterbricht doch eigentlich den Time-Interrupt.
Gruss
Stefan B. schrieb:> Vielleicht magst du ja die eingebauten Debug- und Simulationshinweise> verwenden, um herauszufinden, ob der R8C das Problemkind ist oder das> von mir nicht berücksichtigte BTM oder das von mir nicht berücksichtigte> Telefon.
Das werde ich sowieso mal machen, kann aber ein bisschen dauern.