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.
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.
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
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?
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;
}