Hallo, ich auf meiner Applikation für einen 16 Bit Mikrocontroller einen
Timeout realisieren bzw. implementieren und verwenden.
Ich habe die Möglichkeit einen Timer zu starten und zu stoppen.
An mehreren Codestellen möchte ich nun bei einem Fehlerfall bzw. nicht
Ausführung von bestimmen Codestellen, dass der Timeout zuschlägt. Wie
realisiert man prinzipiell so eine Timeout Funktionalität mit einem
Timer ?
Vielen Dank im Voraus!
> nicht Ausführung von bestimmen Codestellen, dass der Timeout zuschlägt.
Was soll 'zuschlagen' konkret heißen? Wie sehen diese 'bestimmte
Codestellen' aus?
> Wie realisiert man prinzipiell so eine Timeout Funktionalität> mit einem Timer ?
zb so, dass der Timer bei bestimmten Zählerständen oder Zählereignissen
einen Interrupt auslöst. In der zugehörigen ISR kann man dann zb einen
Zähler runterzählen solange der ungleich 0 ist.
An der Aufrufstellt setzt man den Zähler auf einen Wert ungleich 0 und
flechtet eine regelmässige Abfrage auf diesen Zähler in den Code, zb in
Schleifen ein
volatile uint8_t TimoutCounter;
ISR( .... )
{
if( TimeoutCounter > 0 )
TimeoutCounter--;
}
....
int main()
{
....
TimeoutCounter = 5; // maximal 5 Timer ISR AUfrufe
Starte Timer;
while( Ereignis nicht eingetroffen && TimeoutCounter != 0 )
{
mach was
warte
}
Stoppe Timer;
if( TimeoutCounter == 0 )
{
// zu spät. Das war ein Timeout
}
else {
....
Das ist jetzt nur eine Variante. Es gibt noch unzählige andere
Möglichkeiten, je nachdem welche Möglichkeiten du für den Timer hast,
wie schnell der zählt, wie sich das Verhältnis von Timergeschwindigkeit
zu Zeitdauer für den Timeout verhält, etc.
Na, den Timer einfach zählen lassen! Wenn alles sauber läuft, an den
entsprechenden Stellen immer wieder auf '0' setzen. Am
Hauptschleifenende prüfen, ob der kritische Wert überschritten wurde und
das Programm reagieren lassen.
Danke für eure Vorschläge.
Ich möchte allerdings einen Timeout in einem von mir geschriebenen
Klasse einsetzen. In der Main While Schleife will ich nicht auf einen
Timeout warten oder sonst irgendwas. Dies sollte alles in der Klasse
funktionieren.
Leonhard schrieb:> Danke für eure Vorschläge.>> Ich möchte allerdings einen Timeout in einem von mir geschriebenen> Klasse einsetzen. In der Main While Schleife will ich nicht auf einen> Timeout warten oder sonst irgendwas. Dies sollte alles in der Klasse> funktionieren.
Dann wäre zb eine Möglichkeit, dass du eine Callbackfunktion beim Timer
registrierst, die in der ISR aufgerufen wird, wenn die Zeit abgelaufen
ist. Das kann unter Umständen aber etwas tricky werden.
Eine andere Möglichkeit wäre, wenn jede derartige Klasse der
Hauptschleife eine Funktion zur Verfügung stellt, mit der Bitte, dass
die von der Hauptschleife regelmässig aufgerufen werden soll, weil die
Klasse dann ihre ausstehenden Timeouts durchcheckt.
Denk dir was aus. Sei kreativ. In der Programmierung gibt es selten
DAS eine Patentrezept mit dem man alles erschlagen kann. Aber es gibt
Grundideen, Grundgedanken, die man in etwas angewandelter Form auf
Problemstellungen loslassen kann.
Solche Aufgabenstellungen schaffst du im realen Leben mit links, wenn du
8 verschiedene Aufgaben bearbeiten sollst und nur eine einzige Uhr zur
Zeitkontrolle zur Verfügung hast.
Was ist denn ein Timeout? - Wenn man einem Programmteil eine bestimmte
Zeit lässt, ein Ergebnis zu liefern. Wenn in dieser Zeit keine Reaktion
erfolgt, dann will man was unternehmen. Wo das ist, spielt keine Rolle.
Diese Funktionalität kann man genauso einer Klasse zuordnen:
- Timer starten
- kritische Funktion aufrufen
- Timer auf '0' gezählt -> Ereignis auslösen -> kritische Funktion
abbrechen
Wie man das konkret implementieren kann, weißt nur du. Das kommt auf den
Compiler an.
was ist denn die reaktion die du ausführen willst wenns mal länger
dauert? ist es eine überwachung für den unwahrscheinlichen fall das es
mal länger dauert, was aber eigentlich nicht passieren sollte. Oder ist
das länger brauchen einer funktion, ein gewolltes ereigniss das du
bewusst ausnutzen willst?
ungewollt: watchdog verwenden
gewollt: timer zurücksetzen/starten vor der funktion und interrupt
enablen, danach wieder disablen
soll es ohne interrupt funktionieren, dann kann dir wohl nur jemand
helfen der deinen code kennt
Leonhard schrieb:> Hallo Peter,>> danke für den Link. Was hat dies mit meinem Problem zu tun ?
Mit einem 'Multitask' System sind Timeouts relativ banal umzusetzen
for( i = 0; i < 20 && !receivedCharacterFromUart(); i++ )
task_sleep( 10 );
ist zb ein banaler Timeout in einem Thread der auf Zeichen von der UART
wartet. Dadurch dass in der Schleife die Rechenzeit immer wieder an
andere Tasks abgegeben wird, können die weiterlaufen und nach der
angegebenen Zeit (+- ein paar Zeiteinheiten) kriegt der Task wieder die
Kontrolle um nachzusehen, ob an der UART etwas eingetrudelt ist. Wenn
ja, hört er auf zu schleifen. Und wenn die Zeit (definiert durch die
Anzahl der Schleifenwiederholungen mit der Sleep-Zeit) abgelaufen ist,
ebenso.
In einem Singletask System wäre das
for( i = 0; i < 20 && !receivedCharacterFromUart(); i++ )
_delay_ms( 10 );
tödlich, da _delay_ms nur Zeit verbrutzelt. Aber das tut ja task_sleep
nicht. Es wird zwar auch Zeit abgewartet, aber andere Tasks kriegen die
Gelegenheit selbst wieder Arbeit zu machen.
Leonhard schrieb:> danke für den Link. Was hat dies mit meinem Problem zu tun ?
Nun, Du stellst den Callback hinein, daß er nach dem Timeout zuschlägt.
Und bist Du vor dem Timeout fertig, nimmst Du den Callback wieder raus.
Peter
Folgende Angaben habe ich hier nicht erwähnt.
Ich verwende kein Betriebssystem und somit habe ich auch keine
Multitasking Funktionalität.
Ich möchte in der neuen Klasse (objektorientierter Ansi C Code) eine
Timeout-Funktionalität einbauen. Einen Timer kann ich aufsetzen und auch
beenden. Ich hab noch Probleme, wie man geschickt dies Implementieren
könnte.
Leonhard schrieb:> Ich verwende kein Betriebssystem und somit habe ich auch keine> Multitasking Funktionalität.
Deswegen ja auch das 'Multitasking des kleinen Mannes' von Peter.
Leonhard schrieb:> Ich möchte in der neuen Klasse (objektorientierter Ansi C Code) eine> Timeout-Funktionalität einbauen. Einen Timer kann ich aufsetzen und auch> beenden. Ich hab noch Probleme, wie man geschickt dies Implementieren> könnte.
Das stand schon weiter oben.
Du solltest jetzt mal gezielt die ansprechen, die dein Compilersystem
kennen!
Allgemein ist eigentlich alles gesagt.
Leonhard schrieb:> Ich möchte in der neuen Klasse (objektorientierter Ansi C Code) eine> Timeout-Funktionalität einbauen.
Du soltest dir zu allererst einmal darüber klar werden, was du
eigentlich willst. Wozu sollte ein "Timeout" dienen?
Ich nehme mal an, daß du schlichtweg prozedural, also blockierend deine
Programme schreibst:
while (Ereignis noch nicht eingetreten) tu_nix_ausser_trampeln;
Behandle_Ereignis();
Und da du dich mit sowas an jeder Ecke selber blockierst, suchst du nach
einer Möglichkeit, aus solchen Blockaden herauszukommen - ohne zu
begreifen, daß dies ein hausgemachtes Problem ist, das man mit einer
anderen Programmierweise überhaupt nicht hat.
Also: programmiere lieber ereignisorientiert:
if (Ereignis eingetreten) Behandle_Ereignis();
if (was_anderes_gewesen) Reagiere_auf_das_Andere()
if (nochwas) Tu_Nochwas()
usw. immer im Kreise. Es ist schlichtweg die Ereignis-Loop.
Das ist zugleich die Lösung für dein "Timeout-Problem", das du mit einem
simplen systemweiten Uhrcounter erledigen kannst:
Starte_eine_Aktion();
LetzterTermin = Uhrzeit + xxx Millisekunden;
...
...
if (Ereignis eingetreten)
{ Behandle_Ereignis();
LetzterTermin = ungültig;
}
....
if (LetzterTermin < Uhrzeit)
{ Cancele_die_Aktion()
LetzterTermin = ungültig;
}
.. kümmere_dich_um_andere_Ereignisse()...
So etwa. Ich hoffe, du hast das gedankliche Prinzip herausgelesen.
W.S.