Forum: Mikrocontroller und Digitale Elektronik STM32F4 und NRF24L01: Frage zu Interrupts


von Christian J. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

vielleicht weiss ja jemand auf dem Stehgreif heraus, warum ich folgenden 
Effekt habe:

Der Aufruf

RF_SendPaypload((uint8_t*)&rf_data,PAYLOAD_SIZE)

aus dem Hauptprogramm heraus läuft so wie er soll, Datenpaket geht raus, 
in dem Falk kommt kein ACK und im Status Struct steht MAX_RT = True.

Rufe ich es aber aus dem Interruthandler heraus auf, unmittelbar nachdem 
ich ein Paket empfangen habe bleibt das programm in der Senderoutine bei 
der Abfrage der Flags hängen. Weder TD_DS noch MAX_RT wird jemals 1.

Der Interrupt wird vom INT Pin des Funkmoduls angesteuert.

Ich kann mir das so nicht erklären :-(

Source Code is angehängt.

von Christian J. (Gast)


Lesenswert?

Sorry, nun eingeloggt:

Geht um die Stelle hier:
1
/* Rückmeldung senden */
2
    GPIO_SetBits(TM_DISCO_LED_PORT,LED_BLUE);
3
    if (RF_SendPaypload((uint8_t*)&rf_data,PAYLOAD_SIZE) == ERROR)
4
        RF_FlushTX();
5
    GPIO_ResetBits(TM_DISCO_LED_PORT,LED_BLUE);

Wenn etwas im Main läuft, dann sollte es das doch auf in einer ISR, 
wobei ich es tunlichst vermieden habe, da irgendwelche Delays 
reinzubringen, die ihrerseits wieder Interrupt Basiert sind und 
"einfrieren", weil globale Ints gesperrt sind, solange die ISR läuft. 
Keine Funktion die im INT aufgerufen wird, wird sonstwo im Main 
aufgerufen. Ich denke der Compiler weiss, dass er da dann Maßnahmen 
treffen muss Reentranz zu verhindern.

von pitschu (Gast)


Lesenswert?

In der ISR rufst du erst ganz am Schluss 
EXTI_ClearITPendingBit(EXTI_Line1) auf. Das ist problematisch, da die 
Anbindung der Peripherie beim STM32F4 etwas langsam ist. Das Rücksetzen 
des Flags erfolgt erst verspätet, so dass beim Verlassen der ISR das Bit 
noch gesetzt sein kann und die ISR sofort wieder auslöst. Setz den 
Aufruf mal an den Anfang unterhalb des ersten if().

pitschu

von Christian J. (Gast)


Lesenswert?

pitschu schrieb:
> In der ISR rufst du erst ganz am Schluss
> EXTI_ClearITPendingBit(EXTI_Line1) auf. Das ist problematisch, da die
> Anbindung der Peripherie beim STM32F4 etwas langsam ist.

Was hat das denn mit dem Status Byte des SPI Gerätes zu tun? Das Gerät 
löst den Int aus, indem es einen Pin hochnimmt. Ob das Funkmodul 
wirklich sendet ist nicht ermittelbar, nur der Umstand dass es keinen 
Status liefert ist auffällig. Wobei die unteren 3 Bit ok sind, also 
antwortet es aber es setzt nicht die Bits "Sendung ging raus". Da es das 
aber ganz sicher macht, wenn die Routine aus Main aufgerufen wird muss 
die Routine ja ok sein.

Wie wird das überhaupt gehandhabt, wenn eine Routine sowohl im Interrupt 
aufgerufen wird, aber auch im Hauptprogramm? Setzt der Compiler da 
automatisch Blocker, damit keine Rekursion auftritt?

von Dieter Graef (Gast)


Lesenswert?

Christian J. schrieb:
> Ich kann mir das so nicht erklären :-(

Da kann sich auch der NRF chip vertüddeln.Schau mal bei den mbed Leuten 
die lesen so:
int nRF24L01P::read(int pipe, char *data, int count) {

    if ( ( pipe < NRF24L01P_PIPE_P0 ) || ( pipe > NRF24L01P_PIPE_P5 ) ) 
{

        error( "nRF24L01P: Invalid read pipe number %d\r\n", pipe );
        return -1;

    }

    if ( count <= 0 ) return 0;

    if ( count > _NRF24L01P_RX_FIFO_SIZE ) count = 
_NRF24L01P_RX_FIFO_SIZE;

    if ( readable(pipe) ) {

        nCS_ = 0;

        int status = spi_.write(_NRF24L01P_SPI_CMD_R_RX_PL_WID);

        int rxPayloadWidth = spi_.write(_NRF24L01P_SPI_CMD_NOP);

        nCS_ = 1;

        if ( ( rxPayloadWidth < 0 ) || ( rxPayloadWidth > 
_NRF24L01P_RX_FIFO_SIZE ) ) {

            // Received payload error: need to flush the FIFO

            nCS_ = 0;

            int status = spi_.write(_NRF24L01P_SPI_CMD_FLUSH_RX);

            int rxPayloadWidth = spi_.write(_NRF24L01P_SPI_CMD_NOP);

            nCS_ = 1;

            //
            // At this point, we should retry the reception,
            //  but for now we'll just fall through...
            //

        } else {

            if ( rxPayloadWidth < count ) count = rxPayloadWidth;

            nCS_ = 0;

            int status = spi_.write(_NRF24L01P_SPI_CMD_RD_RX_PAYLOAD);

            for ( int i = 0; i < count; i++ ) {

                *data++ = spi_.write(_NRF24L01P_SPI_CMD_NOP);

            }

            nCS_ = 1;

            // Clear the Status bit
            setRegister(_NRF24L01P_REG_STATUS, _NRF24L01P_STATUS_RX_DR);

            return count;

        }

    } else {

        //
        // What should we do if there is no 'readable' data?
        //  We could wait for data to arrive, but for now, we'll
        //  just return with no data.
        //
        return 0;

    }

    //
    // We get here because an error condition occured;
    //  We could wait for data to arrive, but for now, we'll
    //  just return with no data.
    //
    return -1;

}

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.