2016-06-28 23 views
1

Ich habe diesen Code, der unter KEIL funktioniert, aber nicht unter GCC und ich weiß nicht, warum das passiert. Es testet einige der RTX-Betriebssystemfunktionen.Warum wechselt mein Programm nicht in den Handler-Modus unter GCC?

Handler:

void GenWait_IRQHandler (void) { 

    switch (ISR_ExNum) { 
    case 0: Stat_Isr = osDelay (10); break; 
    #if (osFeatureWait) 
    case 1: Stat_Isr = osWait (10); break; 
    #endif 
    } 
} 

Der obige Code wird durch die Einstellung anhängige IRQ von Haupt eingegeben:

... 
ISR_ExNum = 0; /* Test: osDelay */ 
NVIC_SetPendingIRQ((IRQn_Type)SWI_HANDLER); 
ASSERT_TRUE (Stat_Isr == osErrorISR); 
... 

Das Problem ist, dass diese ASSERT_TRUE() schlägt fehl, weil Stat_Isr nicht gleich osErrorISR ist, die es sein sollte als Aufruf osDelay() ist nicht erlaubt von Handler-Modus:

osStatus osDelay (uint32_t millisec) { 
    if (__get_IPSR() != 0U) { 
    return osErrorISR;       // Not allowed in ISR 
    } 
    return __svcDelay(millisec); 
} 

Wie ich schon sagte, wenn es unter KEIL kompiliert wird, funktioniert es gut, aber wenn es unter GCC kompiliert wird, schlägt es fehl. Es sieht aus wie IPSR nicht aktualisiert wird, wenn Handler eingeben und osDelay() nicht weiß, sollte es Fehler zurückgeben. Irgendeine Idee warum passiert das?

SWI_Handler ist Software-Handler, und ich rufe GenWait_IRQHandler() in es.

EDIT:

Dies ist Implementierung verfügbar von KEIL Packs als RTX Validierung, ich versuche nur, um es auf dem Chip funktioniert mit denen ich arbeite. Es sollte also funktionieren, auch wenn ich Funktionen von ISR anrufe.

Außerdem, wie ich in Kommentar schrieb:

(von www.keil.com):

Interrupt-Service-Routinen (ISR) können einige CMSIS-RTOS Funktionen aufrufen. Wenn eine CMSIS-RTOS-Funktion nicht aus dem ISR-Kontext aufgerufen werden kann, lehnt sie den Aufruf ab.

Und dann:

Funktionen, die nicht von einer ISR aufgerufen werden können, sind die Überprüfung der Interrupt-Status und Rückkehr, falls sie von einem ISR-Kontext genannt werden, den Statuscode osErrorISR. In einigen Implementierungen könnte diese Bedingung unter Verwendung des HARD FAULT-Vektors abgefangen werden.

EDIT2:

von O3 Reduzierung Optimierung -o1 isse behoben, aber ich weiß immer noch nicht, warum es wurde wie diese optimiert und wie ich leicht Compiler tut dies verhindern kann. Ich weiß, dass die einfachste Antwort darin besteht, ein paar "volatile" hinzuzufügen, aber das ist in diesem Fall nicht so einfach, denke ich.

+3

Sind Sie sicher, dass Sie OS-Funktionen in einem Interrupt-Handler aufrufen können? – EOF

+0

Ich bin mir ziemlich sicher, dass es so ist, wie ich es erwarte Fehler zurückzugeben. –

+1

Suchen Sie nach Unterschieden in der von den Compilern generierten Assembly. Sind 'ISR_ExNum' und' Stat_Isr' als flüchtig deklariert? Sind Compiler-Optimierungen für beide Werkzeugketten deaktiviert? – kkrambo

Antwort

1

Danke @kkrambo für den richtigen Weg. Das Problem war mit Anweisungen Reihenfolge. Hinzufügen von flüchtigen Stoffen zu Stat_Isr war nicht genug, aber das Hinzufügen Speicherbarriere machte diese Arbeit für mich:

... 
ISR_ExNum = 0; /* Test: osDelay */ 
NVIC_SetPendingIRQ((IRQn_Type)SWI_HANDLER); 
__DMB(); 
ASSERT_TRUE (Stat_Isr == osErrorISR); 
... 

Es geschah, weil Code Optimalisierung ISR nach ASSERT_TRUE (Stat_Isr == osErrorISR); aufgerufen werden gemacht. Ich denke, das ist jetzt klar.