Forum: Mikrocontroller und Digitale Elektronik Modbus funktioniert in RTC Interrupt nicht


von Thomas P. (thomas_p52)


Lesenswert?

Hallo,

Wir haben ein Board basierend auf dem Arduino Mkr Zero Board mit dem 
SAMD21G18 uC entwickelt. Der Arduino-Sketch wurde konvertiert und in ein 
Atmel/Microship-Studio Projekt importiert. Wir verwenden die onboard RTC 
mit der RTCZero lib für zeitbasierte Interrupts um Daten aus der 
Peripherie zu erhalten. Diese Daten stammen von i2c, ADC und so weiter - 
alle basierend auf SERCOM mit SERCOM-Handlern/Interrupts. Das 
funktioniert alles einwandfrei und ohne Probleme.

Nun wollten wir über einen MAX14840 IC und ein UART Interface (mit der 
SERCOM5-Schnittstelle) eine Modbus-Funktionalität hinzufügen. Bei der 
Ausführung in der Schleife (loop()) funktioniert alles einwandfrei, aber 
bei der Ausführung im RTC Interrupt stürzt die read Holding Registers 
Funktion der Arduino Modbus lib ab. Beim Debuggen im Microship Studio 
(break-all) scheint es, als würde der Controller in der 
Uart-Flush-Funktion warten, insbesondere in der while-Schleife. (in der 
originalen Uart.cpp-Datei)
1
void Uart::flush ()
2
{
3
while (txBuffer. available ()); // warten, bis der TX-Buffer leer ist
4
sercom->flushUART ();
5
}

Für mich sieht es so aus, als gäbe es ein Problem mit den Interrupts 
oder der Interrupt-Priorität. Hat irgendjemand ähnliche Probleme schon 
mal beobachtet? Oder eine andere Idee?

Vielen Dank!

Grüße Thomas

von Peter D. (peda)


Lesenswert?

Man sollte sich schon Gedanken machen, ob aller Schrunz wirklich in 
Interrupts gehört. In Interrupts sind natürlich alle anderen Handler mit 
gleichem Level gesperrt.
Typisch macht man daher nur wichtige Sachen in Interrupts, z.B. serielle 
Daten in eine FIFO packen oder aus einer FIFO senden.
Irgendwelche Warteorgien sind in Interrupts ein absolutes NoGo.

von Thomas P. (thomas_p52)


Lesenswert?

Prinzipiell geb ich dir recht, ist auch so gehandhabt, bis auf den einen 
Interrupt aus der RTC. Sodass eben die Messung zum richtigen Zeitpunkt 
stattfindet...

von Peter D. (peda)


Lesenswert?

Ein anderer Interrupt sollte generell nicht auf die UART zugreifen, da 
dann eine 2. Instanz ausgeführt wird. Die UART ist aber nicht reentrant, 
d.h. nur eine Instanz kann sie benutzen.
Vermutlich blockiert also eine Instanz in der Mainloop den Aufruf im 
RTC-Interrupt. Und da der UART-Interrupt nicht mehr ausgeführt werden 
kann, terminiert diese auch nie.
Möglich ist aber auch, der RTC-Aufruf kommt, wenn das vorherige Senden 
noch nicht beendet ist.

von Thomas P. (thomas_p52)


Lesenswert?

Der Zugriff auf die serielle Schnittstelle passiert ja auch erst im RTC 
Interrupt. Also RTC Interrupt kommt (alle 5-60s, je Einstellung), dann 
wird das read gemacht, und danach wird mit der normalen Ausführung 
fortgesetzt.

von Peter D. (peda)


Lesenswert?

Interfaces sind generell nicht reentrant und daher ruft man sie nicht 
aus anderen Interrupts heraus auf. Und da es ja knallt, werden die 
Autoren der Libs das auch gar nicht berücksichtigt haben. Wo es genau 
knallt, ist daher egal.

Man könnte zwar tricksen und dem UART-Interrupt eine höhere Priorität 
zuweisen, aber irgendwann wird es einem doch auf die Füße fallen.
Ich hab sowas schon mal gemacht und mich dann über verstümmelte 
Textausgaben gewundert.

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.