www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Funktion innerhalb von ISR aufrufen


Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie ruft man innerhalb einer ISR eine andere Funktion auf, so dass mit 
dem Funktionsaufruf die ISR auch wieder geschlossen wird?

z.B. empfange ich über die serielle Schnittstelle neue Daten -> 
interrupt ISR wird aufgerufen -> weitere funktion soll innerhalb der ISR 
aufgerufen werdne, um die empfangenen Daten zu verarbeiten. Gleichzeitig 
soll mit diesem Aufruf die ISR geschlossen werden, so dass neue 
Interrupts erkannt werden können.

Oder geht man mit Interrupts etc. anders um?

Bernd

Autor: 2922 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, man geht anders um. Lese in der ISR die Daten vom UART und speichere 
sie ine einem buffer, und setzte eine Boolean fuer das main, sodass der 
buffer naechstens bearbeitet wird.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd Schuster wrote:
> Hallo,
>
> wie ruft man innerhalb einer ISR eine andere Funktion auf, so dass mit
> dem Funktionsaufruf die ISR auch wieder geschlossen wird?

Du machst den Aufruf.
Wenn die Funktion zurückkommt, kommt sie wieder im ISR raus,
der dann seinerseits irgendwann zu Ende ist. Und erst dann
ist die ISR Abarbeitung abgeschlossen.

>
> z.B. empfange ich über die serielle Schnittstelle neue Daten ->
> interrupt ISR wird aufgerufen -> weitere funktion soll innerhalb der ISR
> aufgerufen werdne, um die empfangenen Daten zu verarbeiten.

Wie aufwändig ist diese 'weitere Verarbeitung'.
Generell: In einer ISR so viel wie unbedingt notwendig aber so wenig
wie möglich machen.

> Gleichzeitig
> soll mit diesem Aufruf die ISR geschlossen werden, so dass neue
> Interrupts erkannt werden können.

Das könnte man zwar machen, einfach sei() aufrufen.
Wenn man aber nicht genau weis was man tut, kann das in
Chaos ausarten.

> Oder geht man mit Interrupts etc. anders um?

Ja.
Eine übliche Vorgehensweise sind Jobflags.
In main() gibt es die Hauptendlosschleife. Die überprüft
ständig, ob ein Jobflag gesetzt ist und bearbeitet einen
Job, wenn dem so ist. Die ISR sichert einfach nur die dazu
notwendigen Daten in globalen Variablen und setzt das entsprechende
Jobflag.

Bsp. Du hast einen ADC im System. Der ADC ist so eingestellt,
dass er bei fertigem Wandlerergebnis einen Interrupt auslöst.
Das Wandlerergebnis muss jetzt beispielseweise noch umgerechnet
werden und auf einem LCD ausgegeben werden. Sowohl Umrechnung
als auch Ausgabe beanspruchen relativ viel Zeit und du möchtest
die Interrupts während dieser Zeit nicht gesperrt haben (weil
zb eine UART ebenfalls über Interrupts empfängt).

Also setzt der ADC-Interrupt nur ein entsprechendes Jobflag und
sichert das Wandlerergebnis. Mehr nicht
volatile uint16_t ADC_Result;
volatile uint8_t  ADC_Job;

ISR( ADC_FIN_vect )   // keine Ahnung ob der wirklich so heist
{
  ADC_Result = ADCW;
  ADC_Job = 1;
}

Die Haupschleife in main wartet ständig darauf, dass ADC_Job
irgendwann 1 wird und bearbeitet dann den Messwert
int main()
{

  ...
  ADC_Job = 0;

  while( 1 ) {
    ...

    if( ADC_Job == 1 ) {
      Result = KomplizierteBerechnung( ADC_result );
      Put_On_LCD( Result );

      ADC_Job = 0;
    }

    ...
  }
}

Auf diese Art sind die Interrupts nur minimal gesperrt. Der µC
bearbeitet das ISR Ergebnis, sobald Zeit dazu ist.

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Oder geht man mit Interrupts etc. anders um?

Geht man. Das Wesen einer ISR ist, daß sie völlig losgelöst vom üblichen 
Programmablauf abläuft.

Die ISR sollte nur die wirklich zeitkritischen Dinge tun, also z.B. 
Daten aus dem Hardware-Buffer abholen, dann z.B. ein Flag setzen, und 
sich beenden. Das Flag und die Daten werden dann im normalen 
Programmablauf ausgewertet.

Oliver

Autor: Gregor B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich setzte in meinen ISRs nur Flags/Variablen, wie irgenwo in main() 
angefragt werden.

bsp:

main(void) {
  while (1) {
    if (flag_isr == gesetzt) {
       flag_isr = zurückSetzen;
       tuWasWegenISR();
    }
  }
}

ISR(INT0oderSonstwas) {
  flag_isr = gesetzt;
}

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst in ISRs normale Funktionen aufrufen. Vorbehaltlich notwendiger 
Sonderbehandlung solcher Funktionen bei Maschinen, die sich wie 
beispielsweise PIC16 und 8051 mit Stacks schwer tun und daher u.U. 
irgendwas wie "reentrant" benötigen.

Allerdings wird diese Funktion ganz normal in die ISR zurückkehren und 
erst von dort aus geht es ins normale Programm zurück. Direkt aus der 
aufgerufenen Funktion henaus geht das nicht.

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok - das hab ich soweit verstanden...

d.h. man pollt auch bei der Verwendung von Interrupts - ob ein 
bestimmtes Ereignis eingetroffen ist (in diesem Fall so ein Flag gesetzt 
wurde).


D.h. aber im Umkehrschluss doch auch, dass man so einen Interrupt gar 
nicht installieren muss, wenn die Berechnungen im Anschluss eh durch 
Polling + Flagbit setzen durchgeführt werden, sondern man z.B. einfach 
den Inhalt eines Registers ständig pollt (wenn das möglich ist).

Bernd

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd Schuster wrote:

> D.h. aber im Umkehrschluss doch auch, dass man so einen Interrupt gar
> nicht installieren muss, wenn die Berechnungen im Anschluss eh durch
> Polling + Flagbit setzen durchgeführt werden, sondern man z.B. einfach
> den Inhalt eines Registers ständig pollt (wenn das möglich ist).

Korrekt. Wenn der Interrupt wirklich nur ein Flag setzt, dann kann man 
sich das ersparen und statt dessen das entsprechende Interrupt-Flag 
abfragen (und ggf. zurücksetzen).

Meist passiert in Interrupts jedoch ein kleines bischen mehr als das.

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
d.h. im ISR selbst macht man

- Flag setzen für main Routine
- Buffer (z.B. USART) in internen / externen Speicher schreiben
- Register zurücksetzen damit neue Interrupts empfangen werden können


welche Sachen werden ansonsten noch in einer ISR erledigt?

Bernd

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Kaiser wrote:
> Bernd Schuster wrote:
>
>> D.h. aber im Umkehrschluss doch auch, dass man so einen Interrupt gar
>> nicht installieren muss, wenn die Berechnungen im Anschluss eh durch
>> Polling + Flagbit setzen durchgeführt werden, sondern man z.B. einfach
>> den Inhalt eines Registers ständig pollt (wenn das möglich ist).
>
> Korrekt. Wenn der Interrupt wirklich nur ein Flag setzt, dann kann man
> sich das ersparen und statt dessen das entsprechende Interrupt-Flag
> abfragen (und ggf. zurücksetzen).
>
> Meist passiert in Interrupts jedoch ein kleines bischen mehr als das.

Zb. In Bernds Fall könnte der UART Receive Interrupt das
empfangene Zeichen in einem Buffer hinten anfügen und bei
Empfang eines '\n' das Jobflag setzen um der main() Loop
anzuzeigen, dass eine komplette Zeile empfangen wurde.
In main() braucht man sich dadurch nicht mehr mit einzelnen
Zeichen herumzuschlagen, sondern hat einen kompletten String
zur Verfügung. Das Job Flag zeigt dann den exakten Zeitpunkt
an, an dem dieser String (die empfangene Zeile) zur Verarbeitung
ertig empfangen wurde.
char ReceiveBuffer[80];
uint8_t ReceiveCnt;
uint8_t UART_Job;

ISR( UART_RX_vect )
{
  char c = UDR;

  if( c == '\n' ) {
    ReceiveBuffer[ReceiveCnt] = '\0';
    UART_Job = 1;
  }
  else
    ReceiveBuffer[ ReceiveCnt++ ] = c;
}

int main()
{
  ....

  while( 1 ) {
    if( UART_Job == 1 ) {   // eine komplette Zeile wurde
                            // von der UART empfangen
       .... zb.
       strcpy( Command, ReceiveBuffer );  // damit die UART gleich wieder
                                          // empfangen kann
       UART_Job = 0;

       if( strcmp( Command, "Help" ) == 0 ) {
         // bearbeite Help Kommando
       }
       ....
     }
   }
}

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und den berühmten buffer overflow gibt's gratis. Eine Überprüfung von 
ReceiveCnt sollte schon noch rein.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Andreas Kaiser wrote:
> Und den berühmten buffer overflow gibt's gratis. Eine Überprüfung von
> ReceiveCnt sollte schon noch rein.

:-)
Ist schon klar (mir zumindest).
Die Fehlerbehandlung hab ich absichtlich weggelassen um das
wesentliche, den Zusammenhang zwischen Arbeit in der ISR und
Arbeit in der main(), nicht zu verschleiern.

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ist es eigenltich eleganter mit Hilfe von define ein solches Flag zu 
setzen, oder mit einer unsigned char variable?

Die Fehlererkennung gehört dann auch in die ISR - und die Bearbeitung 
der Fehler je nach Größe in die ISR oder in eine andere Funktion, die 
von main aufgerufen wird.

Bernd

Autor: JensG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spring doch einfach, nachdem die Funktion zurückkommt, aus dem ISR raus 
(vorher Variablen restoren, wenn nötig - beim PIC zumindest immer nötig 
für W und STATUS).
Oder statt einer Funktion aufzurufen, kannste auch mit GOTO hinspringen 
- dann gibt's keine Probleme mit dem direkten Verlassen der ISR direkt 
in der "Funktion"
Du kannst auch in der Funktionen sowas wie einen RC zurückgeben (beim 
PIC in assembler z.B. retlw x), so daß im ISR dann abhängig vom RC der 
Funktion aus dem ISR rausgesprungen werden kann, oder auch nicht.
In der Funktion selbst einfach den ISR verlassen würde ich nicht, denn 
ich glaube, dann bleibt der Stack so stehen, wie er im ISR als letztes 
gesetzt wurde beim Funktionsaufruf (ich glaube, beim PIC wird der 
Stackpointer nicht gesichert). Wenn dann irgendwann in der main irgendwo 
zurückgesprungen wird (weil z.B. der ISR mitten in einer von der main 
aufgerufenen anderen Funktion reinfunkte), landet der Return dann nach 
dem Funktionsaufruf im ISR statt irgendwo im main.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd Schuster wrote:
> ist es eigenltich eleganter mit Hilfe von define ein solches Flag zu
> setzen, oder mit einer unsigned char variable?

Weder noch.
#define und die Deklaration von Variablen sind 2 völlig
verschiedene Dinge.
Die Frage ist genausowenig beantwortbar, wie die Frage ob
bei Halsweh Apfelsaft oder ein Atomkraftwerk besser ist :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
JensG wrote:
> Spring doch einfach, nachdem die Funktion zurückkommt, aus dem ISR raus
> (vorher Variablen restoren, wenn nötig - beim PIC zumindest immer nötig
> für W und STATUS).

Deine Empfehlungen fallen so ziemlich alle in die Kategorie:
"Wie schiesse ich mir selbst möglichst elegant ins eigene Bein"

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok :-)

einfache char variable und fertich

Bernd

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> int main()
> {
>   ADC_Job = 0;
>
>   while( 1 ) {
>     ...
>
>     if( ADC_Job == 1 ) {
>       Result = KomplizierteBerechnung( ADC_result );
>       Put_On_LCD( Result );
>
>       ADC_Job = 0;
>     }
>   }
> }

Erm... da koennen Dir allerdings dann wegen Synchronisationsprobleme 
Ereignisse verloren gehen, das ist Dir klar...?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael G. wrote:
> Karl heinz Buchegger wrote:
>> int main()
>> {
>>   ADC_Job = 0;
>>
>>   while( 1 ) {
>>     ...
>>
>>     if( ADC_Job == 1 ) {
>>       Result = KomplizierteBerechnung( ADC_result );
>>       Put_On_LCD( Result );
>>
>>       ADC_Job = 0;
>>     }
>>   }
>> }
>
> Erm... da koennen Dir allerdings dann wegen Synchronisationsprobleme
> Ereignisse verloren gehen, das ist Dir klar...?

Ja, ist mir klar. (Ich hoffe dem Bernd auch).

OK. Etwas weiter ausgeholt:
Man muss natürlich darauf achten, dass das JobFlag nicht zulange
blockiert wird. Weiters sollte die ISR mglw. auch noch prüfen, ob der
zuletzt angestossene Job schon bearbeitet wurde.

ISR( ADC_fertig )
{
  if( ADC_Job == 0 ) {
    ADC_Result = ADCW;
    ADC_Job = 1;
  }
}

int main()
{
  ADC_Job = 0;

  while( 1 ) {
    ...

    if( ADC_Job == 1 ) {
      // den ADC Job möglichst schnell wieder freigeben
      Tmp = ADC_Result;
      ADC_Job = 0;

      Result = KomplizierteBerechnung( Tmp );
      Put_On_LCD( Result );
    }
  }
}

Auch jetzt können immer noch Ereignisse verloren gehen. Das
liegt dann aber daran, dass die Auswertung der Daten zu lange
dauert. Dagegen kannst du dann allerdings nichts machen. Wenn
die Daten in Packeten ankommen, könnte man sie in der ISR in
eine FIFO stellen und in der main() sukzessive abarbeiten.
Aber letztendlich wird es immer Fälle geben, wo der µC einfach
mit der anfallenden Arbeit nicht mehr mitkommt und Ereignisse
unter den Tisch fallen. Sowas muss im Einzelfall entschieden werden.

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl,

das war jetzt eher weniger gemeint, sondern dass der Zugriff auf die 
gemeinsam genutzte Variable nicht synchronisiert ist. Tritt der 
Interrupt nun direkt nach Put_On_LCD() auf, setzt der ISR sein Flag auf 
eins und will damit signalisieren dass es was zu tun gibt. Dummerweise 
wird das Hauptprogramm aber mit dem Befehl  ADC_Job = 0; fortgesetzt und 
Dein Flag ist geloescht.

Das Problem dass die Bearbeitung zu lange dauert und Interrupts somit 
nicht mehr abgearbeitet werden koennen ist nochmal ein ganz anderes.

Du wirst hier den Part, wo das Flag im Hauptprogramm modifiziert wird, 
atomar machen muessen. Die ISRs selber sind per Std ja schon nicht 
unterbrechbar, das Hauptprogramm allerdings schon. Das hilft Dir, dass 
keine Ereignisse verloren gehen, wenn Zeit vorhanden ist, sie 
abzuarbeiten...

Michael

Autor: JensG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Karl heinz Buchegger (kbuchegg)
>Deine Empfehlungen fallen so ziemlich alle in die Kategorie:
>"Wie schiesse ich mir selbst möglichst elegant ins eigene Bein"

Begründung ?

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest in ner ISR ueberhaupt keine Funktionen aufrufen, wenn es 
nicht einen verdammt guten Grund dafuer gibt...

Autor: Torben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Du wirst hier den Part, wo das Flag im Hauptprogramm modifiziert wird,
>atomar machen muessen.

@Michael G.

Hättest Du ein Beispiel?

Autor: JensG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Michael G. (linuxgeek)
> Du solltest in ner ISR ueberhaupt keine Funktionen aufrufen, wenn es
> nicht einen verdammt guten Grund dafuer gibt...

sorry, aber das klingt mir immer noch nur nach rein formeller 
Begründung, ohne jegliche fachliche Begründung.
Das einzige, worauf man aufpassen muß, ist das Problem, daß ohne 
weiteres sowas nicht reentrant ist, was zum Überschreiben von Variablen 
führen kann.
Das ist aber für mich jetzt erstmal kein Showstopper, denn für ISR's 
benutze ich eigene Funktionen. Und die erlaubt Stacktiefe muß man im 
Blick behalten.
Andere fachliche Begründungen?

Das kann aber eigentlich  Karl heinz Buchegger (kbuchegg) wohl nicht 
gemeint haben, denn um 06.11.2007 14:49 hat er noch nix gegen Funktionen 
in ISR's gehabt . Oder doch ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein.
Aber ich habe ein Problem damit, wenn anstelle von Funktions-
aufrufen mit GOTO gearbeitet wird um in Funktionen hinzukommen,
nur damit der Stack (hoffentlich) so steht, dass aus der
Funktion heraus die ISR beendet werden kann. Dazu dann noch
irgendwelche Registermanipulationen (W bzw. STATUS sind doch
irgendwelche PIC Register, oder nicht), und das Chaos ist fertig.

Meine Meinung: In dem Moment, in dem man sich Gedanken darüber
machen muss, ob der Stack jetzt noch richtig ist, ist irgendetwas
faul im Staate Dänemark.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael G. wrote:
> Hallo Karl,
>
> das war jetzt eher weniger gemeint, sondern dass der Zugriff auf die
> gemeinsam genutzte Variable nicht synchronisiert ist. Tritt der
> Interrupt nun direkt nach Put_On_LCD() auf, setzt der ISR sein Flag auf
> eins und will damit signalisieren dass es was zu tun gibt. Dummerweise
> wird das Hauptprogramm aber mit dem Befehl  ADC_Job = 0; fortgesetzt und
> Dein Flag ist geloescht.

Da hast du recht :-)
Daran hab ich jetzt wiederrum nicht gedacht.

> Du wirst hier den Part, wo das Flag im Hauptprogramm modifiziert wird,
> atomar machen muessen.

Jep.

Für Torben:

   if( ADC_Job == 1 ) {
     cli();
     Tmp = ADC_Result;
     ADC_Job = 0;
     sei();
     .... und weiter gehts
   }

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael G. wrote:

> Du solltest in ner ISR ueberhaupt keine Funktionen aufrufen, wenn es
> nicht einen verdammt guten Grund dafuer gibt...

Das halte ich in dieser Konsequenz für ziemlich übertrieben. Man sollte 
da zwar keine grösseren lang andauernden Aktivitäten veranstalten, aber 
auf saubere Programmstruktur muss man deshalb nicht verzichten.

Wenn man also beispielsweise ein Funktion hat, die ohne zu blockieren 
ein Byte in den Empfangsspeicher einer seriellen Schnitstelle steckt, 
warum diese nicht verwenden?

Und wenn man es mit Controllern ohne vektorierte Interrupts zu tun hat 
(z.B. PIC18, ADuC7000), dann geht das kaum anders.

Autor: JensG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl heinz Buchegger (kbuchegg)
deswegen hatte ich das Wörtchen Funktion in Gänsefüßchen gesetzt, weil 
ich nicht wirklich eine Funktion meinte, sondern ganz einfach ein Stück 
Code, wo ich hinspringe, und aus dem ich dann einfach mich aus der ISR 
ausklinken kann. Stacks manipulieren will ich nicht, und braucht man 
nicht.
W und STATUS sind PIC register - das ist richtig, und die muß man 
sichern, wenn man in die ISR springt. Das ist einfach eine Notwendigkeit 
beim PIC. Ist also keine Registermanipulation in Hacker-Manier. 
Zumindest, wenn man die Sache in Assembler schreibt - wie es bei C 
aussieht, weiß ich nicht, ob da der Compiler das irgendwie gleich 
automatisch mit erledigt
(um welchen µC/Sprache es geht, ging aus der Initialbeschreibung nicht 
hervor)
Abgesehen vom Mißverständnis, was das Wörtchen "Funktion" + GOTO 
verursachte, sehe ich meine Vorschläge nicht gerade als 
Kamikaze-Vorschlag an.

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger wrote:
> Da hast du recht :-)
> Daran hab ich jetzt wiederrum nicht gedacht.
>
>> Du wirst hier den Part, wo das Flag im Hauptprogramm modifiziert wird,
>> atomar machen muessen.
>
> Jep.
>
> Für Torben:
>
>    if( ADC_Job == 1 ) {
>      cli();
>      Tmp = ADC_Result;
>      ADC_Job = 0;
>      sei();
>      .... und weiter gehts
>    }

Genau so isses ;)
Das mit den Funktionsaufrufen ist vielleicht etwas uebertrieben aber Du 
musst schon aufpassen, wenn man bekannte Gewaesser betritt duerfte es ja 
kein Problem sein aber so kurz wie moeglich halten, das wurde aber ja 
schon gesagt.

Mit Interrupt-Programmierung handelt man sich typische 
Multiprogramming-Probleme ein, selbst auf ner Single-Tasking-Architektur 
,)

Michael

Autor: Bernd Schuster (mms)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
welche Funktion haben die Funktionen cli() und sei()?

Hab die jetzt schon öfter gesehen, aber immer ohne jeglicher Defintion 
im Programmcode.

Bernd

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interrupts global ein bzw. ausschalten. Da wird letztlich ein Bit im 
GICR-Register gesetzt... Datenblaetter koennen bei sowas recht 
aufschlussreich sein btw ,)

Autor: Torben (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, aber wieso wird hier mit cli(); und sei() gearbeitet? Müssen alle 
Interrups gesperrt werden oder reicht es nicht nur den ADC Interrupt 
abzuschalten?

Nochmal zum eigentlichen Thema zurück, man sollte Funktionsansprünge 
vermeiden, weil das auch einige Instructions mehr sind (sprungbefehle)

Autor: Michael G. (linuxgeek) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast Recht im Prinzip wird es reichen den ADC-Interrupt auszuschalten 
also dort wo schreibend auf das Korpus delikti zugegriffen wird. Ich 
weiss jetzt ad-hoc nur nicht wie man einzelne Ints abschaltet und 
sicherstellen kann dass sie noch vorgemerkt werden, muesstest mal ins 
Datenblatt schauen... oder es weiss jemand hier ;)

Wenn Du aber sowieso nur einen Interrupt-Handler installiert hast isses 
Hund wie Katz...

Autor: JensG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Torben
>Nochmal zum eigentlichen Thema zurück, man sollte Funktionsansprünge
>vermeiden, weil das auch einige Instructions mehr sind (sprungbefehle)

grundsätzlich stimmt es, daß dies ein paar zusätzliche Instructions 
bedeutet, die dabei ausgeführt werden, aber deswegen würde ich nie die 
Strukturierung meines Programms einfach so hintenanstellen (vor allem, 
wenn ich dabei nur den Call und den Return der Funktion einsparen würde)
Funktionssprünge bedeuten schließlich auch kompakteren Code, und 
effizienterer Speicherverbrauch. Wenn mir wirklich aus Timinggründen die 
paar zusätzlich ausgeführten Instructions weh tun, dann sollte man 
vielleicht doch langsam auf einen etwas performanteren Prozessor 
ausweichen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael G. wrote:
> Du hast Recht im Prinzip wird es reichen den ADC-Interrupt auszuschalten
> also dort wo schreibend auf das Korpus delikti zugegriffen wird. Ich
> weiss jetzt ad-hoc nur nicht wie man einzelne Ints abschaltet und
> sicherstellen kann dass sie noch vorgemerkt werden, muesstest mal ins
> Datenblatt schauen... oder es weiss jemand hier ;)

Ich denke für die Vormerkung muss nichts spezielles gemacht werden.
In den Statusregistern gibt es ja immer ein Bit welches anzeigt,
dass das entsprechende Ereignis aufgetreten ist.

Den spezifischen Interrupt abschalten wäre natürlich schöner :-)
Allerdings ist mir das 'zuviel Aufwand' im Vergleich mit sei()/cli()
Und die paar Takte Verzögerung, wenn es denn wirklich mal zu
einer zeitlichen Überschneidung kommen sollte, habe ich normalerweise
allemal.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.