Sprung in eine Subroutine von ISR aus!

Gast #3508750
Lesenswert?

1
// Interrupt Service Routine fuer Timer1
2
ISR(TIMER1_OVF_vect) 
3

4
{
5
  TCNT1 = 50000; 
6
  
7
  
8
if ( (!(PIND & (1<<PD1))) || (!(PIND & (1<<PD3))) )
9
{
10
 //Wie springe ich von hier in ein Unterprogramm  
11
}
12

13
else
14

15
{
16
  // tuh was
17
}
18
__________________________________________________ // ISR
19

20
Enter:
21

22
{
23
  
24
PORTD &= ~(1<<PD7);
25
  
26
};

hier soll reingesprungen werden!
_________________________________________________// "Unterprogramm"
Gast #3509644
Lesenswert?

Karl Heinz schrieb:
> Und wieder ein Beispiel für meine These, dass die mit dem scheuslichsten
> Code oft die sind, die die dümmsten Fehler im Code haben.

Hm, eine These die besagt das die mit den geringsten 
Programmierkenntnissen die dümmsten Fehler machen.
Das ist als ob ich sage: Wer noch wenig kann, der kann noch wenig.

In ISRs springt man nicht in 'Unterprogramme'
Man setzt ein flag das die ISR aufgerufen wurde.
In der Main() wertet man das flag aus und setzt es zurück sobald man den 
dazugehörigen Code ausführt.

Eine ISR ist geeignet das komplette System zu blockieren.
Sprünge in der ISR kann man nur erkennen wenn man sich den ISR Code 
anschaut und das ist sch..sse.
Deswegen macht man nur das unbedingst nötigste in der ISR und nicht 
mehr.

Deine 'Unterprogramme' nennt man in C Funktionen.
Da man sinnvoller weise jede Programmfunktion in einer 'Funktion' (daher 
der Name) kapselt stellt sich die Frage nach dem Aufruf von 
Unterprogrammen nicht.
my_function(); ist der Aufruf für eine Funktion der Du keine Daten 
schickst und die auch keine zurück liefert. Von Globalen Variablen mal 
abgesehen.
C Buch lesen, Funktionen verstehen.
#3509659
Lesenswert?

Michael Knoelke schrieb:
> Karl Heinz schrieb:
>> Und wieder ein Beispiel für meine These, dass die mit dem scheuslichsten
>> Code oft die sind, die die dümmsten Fehler im Code haben.
>
> Hm, eine These die besagt das die mit den geringsten
> Programmierkenntnissen

nicht Programmierkenntnisse.
Es gibt durchaus auch Leute, die erst am Anfang ihrer Karriere stehen 
und daher technisch noch nicht viel wissen, für die es aber trotzdem 
selbstverständlich ist, Code ordentlich einzurücken und nicht alle 
Statements an den linken Rand zu quetschen. Für die es 
selbstverständlich ist, im Code nicht zwischen 2 Anweisungen 30 
Leerzeilen reinzuquetschen. Die wenigstens in weiten Teilen ein halbwegs 
konsistentes Klammernschema haben. usw. usw.
Gast #3509699
Lesenswert?

Quack schrieb:
> Den schlimmsten Unsinn produziert immer noch der Fortgeschrittene, nicht
> der Anfaenger. Dein Paradigma ist an dieser Stelle nur irrefuehrend fuer
> den Frager.

Ist das wirklich so schlimmer Unsinn den ich da verbreite ?
Schauen wir uns mal die Originalfrage an:

Thomas H. schrieb:
> Ist es möglich aus einer ISR herraus in eine Subroutine zu springen ?!

Meine Antwort sagt: Möglich ja, aber unsauber.

Wenn das irreführend für jemanden ist der gerade vom Moderator wegen 
seines Code Wirrwarrs abgebügelt wird dann heuchel ich jetzt natürlich 
pflichtschuldig Betroffenheit.
Gast #3509713
Lesenswert?

Michael Knoelke schrieb:
> Thomas H. schrieb:
>> Ist es möglich aus einer ISR herraus in eine Subroutine zu springen ?!
>
> Meine Antwort sagt: Möglich ja, aber unsauber.

Die Antwort ist natürlich genauso unsauber.

Ja, man kann "Subroutinen" aus einer ISR aufrufen. Punkt.

Ob das jetzt unsauber, nicht zu empfehlen, oder ganz prima ist, hängt 
vom Programmaufbau ab. Wie bei eigentlich allem, besonders in der 
MC-Programmierung, muß man nur wissen, was man da tut.

Oliver
#3509768
Lesenswert?

Oliver schrieb:

> vom Programmaufbau ab. Wie bei eigentlich allem, besonders in der
> MC-Programmierung, muß man nur wissen, was man da tut.


Und genau da liegt beim TO das Problem.

Wenn man ihm jetzt auch noch naheliegt, dass er den Funktionsaufruf aus 
Performance Gründen nicht machen soll, dann handelt er sich mehr Ärger 
ein, als wie wenn alle paar Millisekunden mal in der ISR ein paar 
Register zuviel gesichert und wieder hergestellt werden.
Denn: Performance ist in seinem Programm das geringste aller Probleme.

Ich würde das so sehen:
Technisch gesehen hat Michael recht. Unter Berücksichtigung des Levels, 
auf dem der TO momentan operiert, ist es aber ein paar Monate zu früh, 
auf dieses Detail einzugehen. Zumal es in diesem Programm auch in der 
Zukunft sicher nicht zum Problem wird.
#3510318
Lesenswert?

Michael Knoelke schrieb:
> Quack schrieb:
>> Den schlimmsten Unsinn produziert immer noch der Fortgeschrittene, nicht
>> der Anfaenger. Dein Paradigma ist an dieser Stelle nur irrefuehrend fuer
>> den Frager.
>
> Ist das wirklich so schlimmer Unsinn den ich da verbreite ?

Niemand hat gesagt daß du Unsinn verbreitest. Nur daß du dem Frager 
nicht hilfst.

> Schauen wir uns mal die Originalfrage an:
>
> Thomas H. schrieb:
>> Ist es möglich aus einer ISR herraus in eine Subroutine zu springen ?!
>
> Meine Antwort sagt: Möglich ja, aber unsauber.

Nein, das sagt sie nicht.

Und tatsächlich ist die Aussage in dieser Generalität Unsinn. Denn es 
ist ganz normal und möglicherweise sogar sehr guter Stil, Funktionen aus 
einer ISR aufzurufen. Beispiel: ein Programm mit mehreren Modulen, die 
jeweils eine Funktion haben die zyklich aufgerufen werden muß. Noch 
konkreter: ein Gerät das per IRMP ein Fernbediensignal auswertet und ein 
paar lokale Encoder und Tasten abfragt. Dann ist es ganz normal, diese 
Funktionen aus ein- und derselben Timer-ISR aufzurufen.

Andererseits scheint es, als wäre das "Unterprogramm" des TE ein 
einzelnes C-Statement. Das wird der Compiler ohnehin inlinen. Jegliche 
Optimierung auf der C-Code Seite wäre hier rausgeworfen. Erst recht, 
wenn der TE dadurch dann (noch) länger braucht, um überhaupt erstmal 
korrekten Code zu schreiben.


XL
#3510349
Lesenswert?

In diesem Zusammenhang sei mir eine Frage gestattet.

Warum zählt ein handelsüblicher C-Compiler nicht für ein einzelnes 
Modul, wie viele öffnende und wie viele schließende Klammern er im 
Quelltext vorfindet? Das sollte doch eigentlich nicht so schwer sein. 
Und würde womöglich zu besseren, sinnvolleren Fehlermeldungen führen. 
Wir alle kennen ja diese Bildschirmseiten voll mit Meldungen vom 
Compiler, weil ein einzelnes } oder ; oder ) fehlt...

Ich bilde mir ein, Clang/LLVM macht das besser, bin mir aber nicht 
sicher.
#3510383
Lesenswert?

Mark Brandis schrieb:
> In diesem Zusammenhang sei mir eine Frage gestattet.
>
> Warum zählt ein handelsüblicher C-Compiler nicht für ein einzelnes
> Modul, wie viele öffnende und wie viele schließende Klammern er im
> Quelltext vorfindet?

Das tut er im Prinzip ja.
Durch die Grammatik hat er diese implizite Zählung.

> Das sollte doch eigentlich nicht so schwer sein.
> Und würde womöglich zu besseren, sinnvolleren Fehlermeldungen führen.

Warum sollte es?

> Wir alle kennen ja diese Bildschirmseiten voll mit Meldungen vom
> Compiler, weil ein einzelnes } oder ; oder ) fehlt...

Das Problem ist, dass die Dinge nicht eindeutig sind. Der Compiler hat 
sein Regelsystem und er versucht den vorgegebenen Text auf diesem 
Regelsystem abzubilden. Sobald aber der erste Fehler vorliegt (der 
meistens auch ganz gut diagnostiziert wird), passt hinten und vorne 
nichts mehr. Teil des Problems ist es zb auch, dass der Compiler ja 
keine logische Analyse macht, ob das ganze auch Sinn ergibt. Vergisst du 
mitten in einer Funktion eine schliessende }, dann wird ab dieser Stelle 
alles weitere falsch zugeordnet. Irgendwann kommt der Compiler dann zb 
drauf, dass du versuchst innerhalb einer Funktion eine weitere Funktion 
zu definieren. Laut C Regeln ist das nicht erlaubt. Die Fehlermeldung 
des Compilers muss dann lauten "Attempt do define a function inside 
another function." Schon. Aber der eigentliche Fehler ist ein ganz 
anderer. Der eigentliche Fehler besteht darin, dass irgendwo vorher eine 
schliessende Klammer vergessen wurde. Das muss aber nicht die letzte der 
Klammern sein, die die Funktion beendet. Das kann auch die vergessene 
Klammer beim if von vor 50 Zeilen gewesen sein.

Fehler zu detektieren, sinnvolle Fehlermeldungen auszugeben und, auch 
wichtig, zu versuchen nach dem ersten Fehler sich zumindest soweit 
wieder in der Grammatik auf einen möglichen Wiederaufsetzpunkt 
vorzutaste, dass weitercompiliert werden kann, das gehört zu den 
schwierigen Dingen im Compilerbau.
(Weitercompilieren möchte man in der Hoffnung, dass man zumindest soweit 
wieder neu aufsetzen kann, dass man im selben Compilerlauf noch weitere 
Fehler diagnostizieren kann)


Übrigens: die Fehlermeldung muss auch nicht "attempt to define function 
inside function" lauten. Dann das Problem besteht darin, dass der 
Compiler an dieser Stelle überhaupt nicht rausfinden muss, dass es sich 
hier um den Funktionskopf einer neuen Funktion handelt. Für ihn sieht 
die Sache ganz anders aus. Für ihn stellt sich die Frage: Was ist 
innerhaln einer Funktion grammatikmässig erlaubt, was ist laut Grammatik 
überhaupt möglich. Und dann trifft er auf ein Zeichen, das nicht möglich 
ist, eines das laut Grammatik an dieser Stelle gar nicht auftreten darf. 
So, worin besteht da jetzt der Fehler? Was war der Auslöser? Das alles 
weiß der Compiler nicht und das ergibt sich auch nicht aus der 
Grammatik. Alles was er feststellen kann ist: der Text, den ich da habe, 
das nächste Token, das passt auf keines der erlaubten Fortsetzungen.
OK, im Laufe der Zeit haben die Compilerbauer natürlich gelernt, das 
etwas was zunächst wie ein Funktionsprotoyp innerhalb einer Funktion 
aussieht und dann doch nicht mit einem ';' abgeschlossen ist, sondern 
mit einem '{' weitergeht, im Regelfall der Versuch einer 
Funktionsdefinition innerhalb einer Funktionsdefinition ist und das dies 
meist darauf zurückzuführen ist, das vorher ein } vergessen wurde. Die 
Fehlermeldung lautet dann "Attempt to define function inside function. 
Did you miss a previous }?"
#3510484
Lesenswert?

Natuerlich muss man daran denken, dass "nested functions" eine GNU 
C-Erweiterung sind und daher erstmal keinen Fehler darstellen. Eine 
Funktionsdefinition kann ueberall stehen, wo auch eine 
Variablendefinition erlaubt ist.
Also ist die Fehlermeldung aus dem Screenshot die einzig sinnvolle: 
"Hier muss doch noch ne Anweisung kommen, die aktuelle Funktion ist ja 
noch gar nicht fertig, aber die Quelldatei ist zuende"
Gast #3511622
Lesenswert?

Michael Knoelke schrieb:
> In ISRs springt man nicht in 'Unterprogramme'
> Man setzt ein flag das die ISR aufgerufen wurde.
> In der Main() wertet man das flag aus und setzt es zurück sobald man den
> dazugehörigen Code ausführt.

Man springt in ner ISR auf jeden Fall in Funktionen hinein, um 
sequenziel was abzuarbeiten. Ansonsten ist das Progrämmchen recht klein 
oder man macht grundsätzlich was falsch. ^^
Gast #3512607
Lesenswert?

> Enter:
>
> {
>
> PORTD &= ~(1<<PD7);
>
> };
>
> hier soll reingesprungen werden!

Wenn du mit "Unterprogramm" ein Label meinst, dann springt man da mit 
goto hin. Aber bist du sicher, dass du das willst?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren