Forum: Mikrocontroller und Digitale Elektronik Interrruptcode auf Funktionen aufgliedern?


von Karsten (Gast)


Lesenswert?

Hallo

darf ich Code aus der Interruptroutine der Übersichtlichkeit halber auf 
Funktionen aufteilen? Ich bastel mit PIC16/PIC18, dort muß ich ja in der 
ISR auswerten, woher der Interrupt kommt und würde gerne den ISR-Code 
der verschiedenen Quellen auf Funktionen aufteilen. Die paar 
zusätzlichen Takte für die Funktionsaufrufe würden nicht stören.

Quasi:
1
void ISR(void)
2
{
3
  if (ADC_IF)
4
   ADC_ISR();
5
  if (TMR_IF)
6
   TMR_ISR();
7
  ...
8
}

von Peter II (Gast)


Lesenswert?

Karsten schrieb:
> Die paar
> zusätzlichen Takte für die Funktionsaufrufe würden nicht stören.

das nicht, aber es werden dann viel mehr Register gesichert als vorher. 
(zumindest ist es bei GCC und den AVRs so).

von Karsten (Gast)


Lesenswert?

Wird dann beim PIC1x nicht anders sein. Was wär hier "best practice" um 
den Code der ISR übersichtlicher zu gestalten, bzw. den ISR-Code auf die 
entsprechenden Sources der Peripheriekomponenten aufzuteilen?

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hmmm ... wie wärs mit INLINE functions?

von Ralf G. (ralg)


Lesenswert?

Karsten schrieb:
> darf ich Code aus der Interruptroutine der Übersichtlichkeit halber auf
> Funktionen aufteilen?
Mach doch mal eine Minimalanwendung, dann siehst du im Assemblerlisting, 
was dich der Spaß kostet (Zeit, Speicherplatz). Wenn's nicht stört, kann 
man das so machen.

Karsten schrieb:
> Was wär hier "best practice"
Flag setzen und Code in der Hauptschleife abarbeiten.

von Karsten (Gast)


Lesenswert?

Ralf G. schrieb:
>> Was wär hier "best practice"
> Flag setzen und Code in der Hauptschleife abarbeiten.

Wofür dann noch ISR? Dann kann ich ja auch zyklisch in der Hauptschleife 
auf das Interruptflag pollen, vorausgesetzt die Hauptschleife ist kurz 
genug

Bsp:
ADC_ISR: Wert auslesen, in Variable schreiben, nächsten Kanal 
selektieren, Wandlung starten
I2C_ISR: Daten vom Master empfangen, in Array schreiben oder Daten aus 
dem Array an den Master senden
UART_ISR: 1-Wire Kommunikation (TX Byte/Bit, RX Byte/Bit, 
SearchFirst/Next)

In der Hauptschleife mache ich doch schon so langweilige Dinge wie PID, 
Taster abarbeiten, Display beschreiben, ADC-Werte über Lookup in 
Temperaturen/Volumenströme umrechnen, ...

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Karsten schrieb:
> Wofür dann noch ISR?

Die ISR ist beim Empfang normalerweise dafür da, die Daten abzuholen und 
bestanfalls kurz vorzubereiten. Die Weiterverarbeitung findet dann im 
Hauptprogramm statt.
Beim Senden werden vorbereitete Daten in der ISR rausgeschickt, ggf. mit 
Double-Buffer-handling.

Beim Senden oder Empfangen von Daten koppelt man das üblicherweise mit 
einem DMA.

"Best practise" ist mMn. ein System mit (RT)OS:
Die ISR überträgt die empfangenen Daten in den Empfangsbuffer (besser: 
Peripheral -> DMA -> Empfangsbuffer).
ISR bzw. DMA Ready Interrupt setzt dann das Event für die Task, welche 
die Daten verarbeitet, und schaltet ggf. den DMA Buffer um.

Ich bin der Meinung, dass sich ein RTOS auch auf kleinen Systemen lonht, 
da das Hauptprogramm dadurch stark entwirrt wird; der Overhead ist 
vernachlässigbar ggü. dem Gewinn. Bei guter Strukturierung kann der 
Overhead eines RTOS sogar kleiner werden, als die "manuelle" Variante. 
Vor allem wird alles übersichtlicher und deterministischer.

Arbeitet man auf einem Cortex-M, kann man sich im RTOS Viewer grafisch 
anschauen, wie gross die System- bzw. Interruptlast ist.

von Guest (Gast)


Lesenswert?

Random .. schrieb:
> Arbeitet man auf einem Cortex-M, kann man sich im RTOS Viewer grafisch
> anschauen, wie gross die System- bzw. Interruptlast ist.

Ja genau, so ein RTOS Viewer ist sehr praktisch und gibt es z.B bei 
Segger embOS und nennt sich embOSView. Mit embOS geht das nicht nur mit 
einem Cortex-M sondern auch mit PIC16/PIC18.
Gibt's wohl nicht bei KeilRTX.

SCNR ;-)

von Thomas E. (picalic)


Lesenswert?

Um auf die Eingangsfrage zurückzukommen:
Ja, kann man machen, ist schon wegen der Übersicht auch zu empfehlen, 
und "Register-Rett-Orgien" (wie vielleicht beim AVR) gibt es nicht (der 
PIC hat gar nicht so viele Register, die gerettet werden könnten)
Bei den Enhanced Midrange (PIC16F1xxx) rettet die Hardware sowieso schon 
alle Prozessor-Register automatisch beim Interrupt-Eintritt und stellt 
sie bei Rücksprung wieder her..

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

Karsten schrieb:
> Wird dann beim PIC1x nicht anders sein.

Ich war erst geneigt, dem zu widersprechen, weil PICs ja nicht direkt 
viele Register (im herkömmlichen Sinn) haben. Dafür haben sie aber diese 
Unmengen an Pseudo-Registern (FSRx, TBLPTRx) im RAM die eine ISR auch 
nicht überschreiben darf. Ohne statische Code-Analyse müßte der Compiler 
alle diese Register sichern, was die Interrupt-Latenz in unerträgliche 
Höhe klettern ließe. Ein PIC-Compiler muß also etwas ähnliches machen 
wie AVR-gcc - sich die ISR "ansehen" und dann nur die Register sichern, 
die in der ISR auch verändert werden.

Wenn man jedoch Funktionen aus einer ISR aufruft, dann kann der Compiler 
i.d.R. in diese Funktionen nicht "hineinsehen". Dann muß er alle 
Register sichern, die im ABI als caller saved spezifiziert sind.

> Was wär hier "best practice" um
> den Code der ISR übersichtlicher zu gestalten, bzw. den ISR-Code auf die
> entsprechenden Sources der Peripheriekomponenten aufzuteilen?

Verwende Funktionen. Wenn es dann immer noch schnell genug ist, bist du 
fertig. Ansonsten mußt du optimieren. Aber wie immer gilt: optimiere 
erst dann, wenn es notwendig wird.

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.