Forum: Mikrocontroller und Digitale Elektronik [Cortex-M3/stm32] Interrupt Routine


von Philipp (Gast)


Lesenswert?

Hallo,
ich habe eine Interrupt Routine, die bei Empfang des ersten Zeichens 
funktioniert. Danach wird der Interrupt immer wieder angesprungen (ohne 
Empfang). Was fehlt mir da?
1
void USART1_IRQHandler(void)
2
{
3
    taskDISABLE_INTERRUPTS();
4
5
    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
6
    portCHAR cChar;
7
8
    extern xQueueHandle xQueue;
9
10
    if (USART_GetITStatus( USART1, USART_IT_RXNE ) != RESET)
11
    {
12
        cChar = USART_ReceiveData( USART1 );
13
        xQueueSendFromISR( xQueue, &cChar, &xHigherPriorityTaskWoken );
14
    }  
15
16
    if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
17
    {
18
        // not implemented
19
20
    }
21
22
    /* Clear the USART1 Receive interrupt */
23
    USART_ClearITPendingBit(USART1, USART_IT_RXNE); 
24
    USART_ClearITPendingBit(USART1, USART_IT_TXE); 
25
26
    taskENABLE_INTERRUPTS();
27
    portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
28
}

Ich verwende FreeRTOS, aber das soll angeblich unabhängig sein bei 
Interrupt Routinen ???


Philipp

von Clemens Gerlach (Gast)


Lesenswert?

Finde auch nix in Deinem Code. Sollte eigentlich tun. Das 
USART_ClearITPendingBit(SART1, USART_IT_RXNE) solltest Du dir sogar 
sparen können, da mit dem Lesen des Empfangsregister das RXNE Flag 
gelöscht wird (Du solltest es Dir sogar sparen wegen möglicher 
race-condition).

Das disablen und enablen von Interrupts sollte auch nicht nötig sein 
(ich gehe mal davon aus, dass die Prioritäten FreeRTOS, uart2 richtig 
gesetzt sind).

Bei mir tut das hier:
1
void USART1_IRQHandler(void)
2
{
3
        portBASE_TYPE task_woken = pdFALSE;
4
        char c;
5
6
        if (USART1->SR & USART_SR_RXNE)
7
        {
8
                /* rx data ready */
9
                c = USART1->DR;
10
                /* try to enqueue */
11
                xQueueSendFromISR(serial_queues.uart1_rx_queue, (void *)&c, &task_woken);
12
        }
13
        /* only try to get data from queue if tx register empty
14
         * and int is enabled. if we would not check for int enabled, rx from queue
15
         * would be tried on every rx interrupt since txe is allways set when tx register
16
         * is empty
17
         */
18
        if ((USART1->SR & USART_SR_TXE) && (USART1->CR1 & USART_CR1_TXEIE))
19
        {
20
                /* tx register empty */
21
22
                if (xQueueReceiveFromISR(serial_queues.uart1_tx_queue, (void *)&c, &task_woken))
23
                {
24
                        /* got data from queue, send it */
25
                        USART1->DR = c;
26
                }
27
                else
28
                {
29
                        /* queue empty, disable further ints */
30
                        USART1->CR1 &= ~USART_CR1_TXEIE;
31
                }
32
        }
33
        portEND_SWITCHING_ISR(task_woken);
34
}

Grundsätzlich beim STM32:

In der ST FAQ (http://www.st.com/stonline/faq/user_faqbrowser.php) nach 
"Interrupt re-enters" suchen (FAQ #1224). Grr.. direkter Link geht 
nicht.

Sollte aber bei Dir nicht das Problem sein, da nach dem Löschen des 
Flags (beim Lesen des Registers) ja noch genug passiert vor dem 
Rücksprung.

Gruß
Clemens

von Philipp (Gast)


Lesenswert?

Danke. Ich glaube, daß bei mir die Interrupt Prioritäten nicht passen. 
Das FreeRTOS hängt nach einiger Zeit, aber die Interrupt Routinen 
funktionieren noch. Hast du ein paar Informationen für mich bez. Prios. 
ST und FreeRTOS bin ich eigentlich alles durch - ohne Ergebnis.

von Philipp (Gast)


Lesenswert?

Ach ja, das Problem hat sich seit dem hierher verlagert :-)

Beitrag "STM32 Prioritäten"

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.