SysTick enable führt zu sofortigem Fault

OP #5383699
Lesenswert?

Hallo zusammen,

ich bin gerade mit meinem Latein am Ende, obwohl das Beispiel, das den 
Fehler erzeugt, wirklich minimal ist:

Und zwar landet ein STM32F103RE beim folgenden Beispiel direkt im 
HardFault-Handler, ein STM32F446 fühlt sich dagegen pudelwohl:
1
#define SYSTICK_TIMER_INTERVAL_MS 1
2

3
#ifdef STM32F4XX
4
    #define SYSTEMCORECLOCK 168000000ULL
5
#elif defined( STM32F10x )
6
    #define SYSTEMCORECLOCK 72000000ULL
7
#endif
8

9

10
int main(void)
11
{
12
    // Timer und Interrupt-Prioritaeten einstellen
13

14

15

16
    #if defined( STM32F4XX ) || defined( STM32F10x )
17
        #if defined( STM32F4XX )
18
            #define HIGHSPEED_TIMER_IRQn TIM6_DAC_IRQn
19
        #elif defined( STM32F10x )
20
            #define HIGHSPEED_TIMER_IRQn TIM4_IRQn
21
        #endif
22

23

24
        SystemInit();
25
        SysTick_Config(SystemCoreClock/1000*(SYSTICK_TIMER_INTERVAL_MS));
26
        assert( SystemCoreClock == SYSTEMCORECLOCK );
27

28
        uint32_t savectrl = SysTick->CTRL;
29
        SysTick->CTRL  = 0; // SysTick-IRQ deaktivieren
30
        //NVIC_DisableIRQ(SysTick_IRQn); funktioniert nicht
31

32

33
        // NVIC/ISRs konfigurieren
34
        NVIC_PriorityGroupConfig(0);
35

36
        NVIC_SetPriority(PendSV_IRQn, 2);
37
        NVIC_SetPriority(SysTick_IRQn, 1);
38
        NVIC_SetPriority(HIGHSPEED_TIMER_IRQn, 0);
39

40
        //FIXME: Enablen der IRQs landet am STM32F103RE sofort im Hard Fault Handler - und 
41
        // ich habe keine Ahnung warum
42
        NVIC_EnableIRQ(HIGHSPEED_TIMER_IRQn); 
43
        NVIC_EnableIRQ(PendSV_IRQn);
44

45
        // SysTick wieder einschalten
46

47
        SysTick->CTRL  = savectrl; // <=========  DAAAAAAAAAAA
48

49

50

51
        while(1);
52
    #endif
53
    return 1;
54
}
Die ISRs für PENDSV-Handler, SysTick-Handler und Timer-ISR sind 
definiert, werden aber noch nicht einmal angesprungen.

Was habe ich übersehen?
Viele Grüße
W.T.
Gast #5383718
Lesenswert?

Hast du nur den SysTick mal versucht zum laufen zu kriegen ohne deine 
anderen Timer / Interrupts? Ich hatte den SysTick auf dem F103RE auch 
verwendet und das waren wirklich nur zwei Zeilen oder sowas.

Ich glaub es fehlt noch ein __enable_irq
OP #5383724
Lesenswert?

derjaeger schrieb:
> Hast du nur den SysTick mal versucht zum laufen zu kriegen ohne deine
> anderen Timer / Interrupts?

Ja. Wenn ich die beiden Zeilen mit "NVIC_EnableIRQ();" auskommentiere, 
geht alles.

Ich kann dann auch später mit
TIM_ITConfig(), NVIC_Init() und TIM_Cmd(TIM4, ENABLE) den Timer 
einschalten.

Mich interessiert nur, was hier schief geht, daß ich die beiden IRQs 
nicht vor dem SysTick-Timer einschalten kann, und was in dieser Hinsicht 
den STM32F103 vom STM32F446 unterscheidet.
Gast #5384070
Lesenswert?

ich vermute entweder ein alignment Problem oder (wahrscheinlicher) ein 
Stack Problem (Stack nicht gross genug auf dem kleinen Controller o.ä.). 
Du kannst den Fault Status im SCB genauer analysieren. Erster Punkt zum 
Gucken ist der R13 im Fault Fall. Wo zeigt der hin? Was ist im R14?
Gast #5384083
Lesenswert?

Zudem wird der Systick nicht über den NVIC eingestellt, weil er kein 
Interrupt ist, sondern eine Exception. Kann aber sein, daß die 
API-Routine das im Falle des Systicks dann korrekt auf den System 
Control Block umbiegt, aber da mußt Du Dich mal durch den HAL-Wust 
kämpfen.
Gast #5384105
Lesenswert?

Sicher dass die ISR auf beiden Kontrollen korrekt im ISR Vektor landet? 
Mal das CFSR ausgelesen? Sicher dass es überhaupt der HardFault Handler 
ist und nicht einfach nur dessen ISR der Default Ist? => IPSR auslesen
OP #5384514
Lesenswert?

Nop schrieb:
> Kann aber sein, daß die
> API-Routine das im Falle des Systicks dann korrekt auf den System
> Control Block umbiegt,

Hmm....

core_cm3.h (22. March 2012):
1
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
2
{
3
  if(IRQn < 0) {
4
    SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M  System Interrupts */
5
  else {
6
    NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */
7
}

core_cm4.h (18. March 2015)
1
__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
2
{
3
  if((int32_t)IRQn < 0) {
4
    SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
5
  }
6
  else {
7
    NVIC->IP[((uint32_t)(int32_t)IRQn)]               = (uint8_t)((priority << (8 - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
8
  }
9
}

Es sieht so aus, als seien in der neueren CMSIS für den M4 ein paar 
Angst-Casts hinzugekommen. In der neueren CMSIS für den M3 sind die dann 
auch drin.

Muß ich mal in Ruhe schauen, ob das einen Unterschied ergibt.
#5384562
Lesenswert?

Das Problem ist, wie Jim schon richtig beschrieben hat, die 
NVIC_EnableIRQ. Hier mal Beispielhaft aus der core_cm3.h Version 4.30:
1
__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
2
{
3
  NVIC->ISER[(((uint32_t)(int32_t)IRQn) >> 5UL)] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
4
}

Da wird der IRQn auf uint32_t gecastet, was dann für kleine negative 
Werte zu einer sehr großen positiven Zahl wird (PendSV_IRQn ist -2, 
(uint32_t)(-2) ist 4294967294) und damit landet 
NVIC->ISER[(uint32_t)(-2)] im Nirvana. In neueren Versionen der 
core_cm3.h ist eine if-Abfrage eingebaut um das Problem abzufangen: 
https://github.com/ARM-software/CMSIS_5/blob/master/CMSIS/Core/Include/core_cm3.h#L1503

Die Schuld an den Angst-Casts trägt MISRA:
https://github.com/ARM-software/CMSIS_5/issues/248

PS:
Die if-Abfragen wurden Ende April 2016 eingeführt. core_cmX.h, die älter 
sind, haben die dementsprechend nicht. Gut möglich, dass deine IDE für 
den F446 eine aktuellere core_cm4.h einbindet. Der entscheidende commit 
war wohl hier: 
https://github.com/ARM-software/CMSIS_5/commit/522d83bbd2b21ce062c5189a4d93383ed9fa3360#diff-cd53dfdd878fa5bcf254f5336653e39c

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