Forum: Mikrocontroller und Digitale Elektronik Delay in ISR


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Walter T. (nicolas)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

gibt es eigentlich einen Grund, der gegen einen delay in einer ISR 
spricht?
1
void HardFault_Handler(void)
2
{
3
    // Sicheren Zustand herstellen
4
    GPIOA->MODER = 0;
5
    GPIOB->MODER = 0;
6
    GPIOC->MODER = 0;
7
    GPIOD->MODER = 0;
8
9
10
    setOutput(ERRORLED_GPIO, ERRORLED_Pin);
11
12
    while(1) {
13
        ERRORLED_GPIO->ODR ^= (uint32_t) ERRORLED_Pin;
14
        delay_ms(200);
15
    }
16
}

Eigentlich müßte doch beim HardFault-Handler der Drops gelutscht sein 
und mich delays nicht mehr interessieren.

Viele Grüße
W.T.

von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht lesenswert
In diese Fall spricht nichts dagegen, finde ich.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Bewertung
0 lesenswert
nicht lesenswert
Nö, du musst nur zusehen, das der SysTick eine noch höhere Priorität als 
der Hardfault Handler hat, sonst hängts. Nicht, das du das nicht sowieso 
wolltest, aber blinken tuts dann auch nicht.

von dummschwaetzer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sicherer Zustand währe für mich Interrupts sperren, geht da deine 
delay() noch?

von Vincent H. (vinci)


Bewertung
0 lesenswert
nicht lesenswert
Hat der HardFault nicht eine höhere (nicht änderbare) Priorität als der 
SysTick? Falls ja, dann geht das mit Sicherheit nicht.

von Ingo L. (corrtexx)


Bewertung
0 lesenswert
nicht lesenswert
Bei sowas würde ich auch keine delay-Funktion nutzen, die auf andere 
ISRs angewiesen ist. Da würde ich tatsächlich mit roher CPU Gewalt 
Rechenleistung für ein delay alà:
1
void delay ( uint32_t Delaytime ) 
2
{
3
 while ( Delaytime ) Delaytime--;
4
}
verbraten. Timing is hier sowieso nur von geringerer Präzision 
notwendig.

: Bearbeitet durch User
von Peter II (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ingo L. schrieb:
> für ein delay alà:

und hoffen das der Compiler es nicht komplett entsorgt. Da sollte dann 
noch ein volatile oder ähnliches rein.

von Walter T. (nicolas)


Bewertung
0 lesenswert
nicht lesenswert
Die hier funktioniert recht zuverlässig:
1
    #define TUNE_FAC 1.0
2
            
3
4
   #define delay_us(delayval) delay_us_( \
5
          (uint64_t)( (SYSCLK) / 3000000ULL *delayval * TUNE_FAC) )
6
7
  #define delay_ms(delayval) delay_us_( \
8
          (uint64_t)( (SYSCLK) / 3000ULL *delayval * TUNE_FAC) )
9
10
  static inline void delay_us_(uint64_t delayval)
11
  {
12
        if(delayval)
13
            {
14
          asm volatile (\
15
                "L_LOOPUS_%=:     \n\t" \
16
                "subs %0, %0, #1  \n\t" \
17
                "bne  L_LOOPUS_%= \n\t" \
18
                :  "+r" (delayval) );
19
        }
20
        else
21
            {
22
          asm volatile("nop");
23
        }
24
    }

von Ingo L. (corrtexx)


Bewertung
0 lesenswert
nicht lesenswert
Peter II schrieb:
> und hoffen das der Compiler es nicht komplett entsorgt. Da sollte dann
> noch ein volatile oder ähnliches rein.
Kann man ja machen, wenn es nicht auf Anhieb funktioniert...

von Walter T. (nicolas)


Bewertung
0 lesenswert
nicht lesenswert
dummschwaetzer schrieb:
> Sicherer Zustand währe für mich Interrupts sperren,

Warum? Was sollten die ISRs noch anstellen, wenn alle Pins Eingänge 
sind?

von Jim M. (turboj)


Bewertung
0 lesenswert
nicht lesenswert
Peter II schrieb:
> Ingo L. schrieb:
>> für ein delay alà:
>
> und hoffen das der Compiler es nicht komplett entsorgt. Da sollte dann
> noch ein volatile oder ähnliches rein.

Und genau das sorgt bei unterschiedlichen optimierungsstufen für eine 
seeeehr variable Durchlaufzeit. Viele Leute nutzen daher eine simple 
Funktion, die eine passend berechnete Anzahl an __NOP(); für so 1us oder 
10us enthält.

Für den OP noch der Hinweis, das man solche Schleifen im Hardfault gerne 
mal mit Taste unterbrechbar haben will (um z.B. einen Reset auszulösen). 
Dann muss man die 200ms unterteilen (z.B. 1ms Schritte), sonst muss der 
Anwender die Taste lange gedrückt halten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht lesenswert
Walter T. schrieb:
> "L_LOOPUS_%=:     \n\t" \
>                 "subs %0, %0, #1  \n\t" \
>                 "bne  L_LOOPUS_%= \n\t" \

Dafür hat der Gott der Unix-Assembler local labels erfunden:
1
   "1:  subs %0, %0, #1 \n\t" \
2
   "    bne 1b\n\t" \

von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Die Funktion delay_ms() basiert doch nicht auf Interrupts und auch nicht 
auf dem System-Tick (solange es keine Eigenentwicklung ist) - oder habe 
ich da etwas überlesen?

Die Prio vom HardFault und SysTick ist einstellbar.

Ich beziehe mich jetzt auf einen Cortex-M4, denn der verwendete 
Controller wurde nicht genannt.

von Carl D. (jcw2)


Bewertung
0 lesenswert
nicht lesenswert
Walter T. schrieb:
> Hallo zusammen,
>
> gibt es eigentlich einen Grund, der gegen einen delay in einer ISR
> spricht?
>
>
1
> void HardFault_Handler(void)
2
> {
3
>     // Sicheren Zustand herstellen
4
>     GPIOA->MODER = 0;
5
>     GPIOB->MODER = 0;
6
>     GPIOC->MODER = 0;
7
>     GPIOD->MODER = 0;
8
> 
9
.
10
>     setOutput(ERRORLED_GPIO, ERRORLED_Pin);
11
> 
12
>     while(1) {
13
>         ERRORLED_GPIO->ODR ^= (uint32_t) ERRORLED_Pin;
14
>         delay_ms(200);
15
>     }
16
> }
17
>
>
> Eigentlich müßte doch beim HardFault-Handler der Drops gelutscht sein
> und mich delays nicht mehr interessieren.
>
> Viele Grüße
> W.T.

Das ist keine ISR, sondern ein Fault-Handler. Falls der nur eine 
Error-LED blinken lassen soll, warum nicht. Wenn er eine Situation 
behandelt, für die es tatsächlich eine softwaretechinsche Lösung gibt, 
dann würde man sicher kein delay() wollen. Die würde man dann aber eher 
in UsageFault/MemoryManagementFault behandeln, im HardFault ist die 
Fehlerursache gar nicht mehr ablesbar.

Hardfault ist so eine Art letztes Zucken, denn der kommt, wenn andere 
Fehlersituationen nicht oder nicht ohne neu auftretende Fehler behandelt 
werden. Da ist alles erlaubt. Zumal ein Hardfault eine kaum noch zu 
unterbietende Prio hat.

von Walter T. (nicolas)


Bewertung
-1 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Dafür hat der Gott der Unix-Assembler local labels erfunden:

Danke für den Hinweis! ARM-Assembler ist für mich eine Fremdsprache, die 
ich nie ohne Wörterbuch in der Hand anfasse.

von Adam P. (adamap)


Bewertung
0 lesenswert
nicht lesenswert
Adam P. schrieb:
> Die Prio vom HardFault und SysTick ist einstellbar.

Muss mich korrigieren:
HardFault hat Prio. (-1)

von Carl D. (jcw2)


Bewertung
0 lesenswert
nicht lesenswert
Walter T. schrieb:
> Jörg W. schrieb:
>> Dafür hat der Gott der Unix-Assembler local labels erfunden:
>
> Danke für den Hinweis! ARM-Assembler ist für mich eine Fremdsprache, die
> ich nie ohne Wörterbuch in der Hand anfasse.

Die Sprache zu verstehen wäre aber Grundvoraussetzung, um die Auswirkung 
verschiedener C-Konstrukte abschätzen zu können.
Plus so Feinheiten, daß ein Register in dem Befehl nachdem es geladen 
wurde vielleicht noch nicht verfügbar ist und man deshalb besser 2 
"C-Statement" verschränkt ausführt.

von Walter T. (nicolas)


Bewertung
-1 lesenswert
nicht lesenswert
Jim M. schrieb:
> Für den OP noch der Hinweis, das man solche Schleifen im Hardfault gerne
> mal mit Taste unterbrechbar haben will (um z.B. einen Reset auszulösen).
> Dann muss man die 200ms unterteilen (z.B. 1ms Schritte), sonst muss der
> Anwender die Taste lange gedrückt halten.

Meine Reset-Taste benötigt immer gleich lang, egal was im Fault-Handler 
läuft.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Walter T. schrieb:
> ARM-Assembler ist für mich eine Fremdsprache

Wobei die Geschichte der local labels nicht so viel mit der
Architektur zu tun hat, sondern mit der Umgebung.  Der hier verwendete
GNU Assembler hat seine historischen Wurzeln in den Unix-Assemblern,
die haben solche Labels halt seit jeher gekannt.

Die kann man im GNU Assembler dann unabhängig von der Architektur
nutzen, also sowohl auf ARM, AVR oder x86.

Andere ARM-Assembler haben dieses Feature möglicherweise nicht.

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]
  • [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.