Delay in ISR

OP #5195152
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.
#5195184
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.
OP #5195196
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
    }
#5195208
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.
#5195212
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.
#5195218
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.
#5195240
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.
OP #5195246
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.
Moderator Persönliche Seite #5195249
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

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