Don't reenable interrupts in the ISR
The unselect() method, liberally called directly and indirectly from the interrupt handler, always reenables interrupts after it's done. In ISRs, interrupts are disabled by default, and although reenabling is allowed, the interrupt handler doesn't seem to have reentrant code. Therefore, only reenable when not in an ISR. This was causing problems in certain circumstances, e.g. with an Arduino Ethernet shield, most packet receptions would cause resets.
This commit is contained in:
parent
ca93c49b22
commit
2133bbfe79
12
RFM69.cpp
12
RFM69.cpp
|
|
@ -41,6 +41,7 @@ volatile uint8_t RFM69::PAYLOADLEN;
|
||||||
volatile uint8_t RFM69::ACK_REQUESTED;
|
volatile uint8_t RFM69::ACK_REQUESTED;
|
||||||
volatile uint8_t RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request
|
volatile uint8_t RFM69::ACK_RECEIVED; // should be polled immediately after sending a packet with ACK request
|
||||||
volatile int16_t RFM69::RSSI; // most accurate RSSI during reception (closest to the reception)
|
volatile int16_t RFM69::RSSI; // most accurate RSSI during reception (closest to the reception)
|
||||||
|
volatile bool RFM69::_inISR;
|
||||||
RFM69* RFM69::selfPointer;
|
RFM69* RFM69::selfPointer;
|
||||||
|
|
||||||
bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
|
bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
|
||||||
|
|
@ -109,6 +110,7 @@ bool RFM69::initialize(uint8_t freqBand, uint8_t nodeID, uint8_t networkID)
|
||||||
while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout); // wait for ModeReady
|
while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout); // wait for ModeReady
|
||||||
if (millis()-start >= timeout)
|
if (millis()-start >= timeout)
|
||||||
return false;
|
return false;
|
||||||
|
_inISR = false;
|
||||||
attachInterrupt(_interruptNum, RFM69::isr0, RISING);
|
attachInterrupt(_interruptNum, RFM69::isr0, RISING);
|
||||||
|
|
||||||
selfPointer = this;
|
selfPointer = this;
|
||||||
|
|
@ -353,7 +355,7 @@ void RFM69::interruptHandler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// internal function
|
// internal function
|
||||||
void RFM69::isr0() { selfPointer->interruptHandler(); }
|
void RFM69::isr0() { _inISR = true; selfPointer->interruptHandler(); _inISR = false; }
|
||||||
|
|
||||||
// internal function
|
// internal function
|
||||||
void RFM69::receiveBegin() {
|
void RFM69::receiveBegin() {
|
||||||
|
|
@ -460,7 +462,7 @@ void RFM69::unselect() {
|
||||||
SPCR = _SPCR;
|
SPCR = _SPCR;
|
||||||
SPSR = _SPSR;
|
SPSR = _SPSR;
|
||||||
#endif
|
#endif
|
||||||
interrupts();
|
maybeInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
// true = disable filtering to capture all frames on network
|
// true = disable filtering to capture all frames on network
|
||||||
|
|
@ -788,3 +790,9 @@ void RFM69::rcCalibration()
|
||||||
writeReg(REG_OSC1, RF_OSC1_RCCAL_START);
|
writeReg(REG_OSC1, RF_OSC1_RCCAL_START);
|
||||||
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
|
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void RFM69::maybeInterrupts()
|
||||||
|
{
|
||||||
|
// Only reenable interrupts if we're not being called from the ISR
|
||||||
|
if (!_inISR) interrupts();
|
||||||
|
}
|
||||||
|
|
|
||||||
2
RFM69.h
2
RFM69.h
|
|
@ -131,6 +131,7 @@ class RFM69 {
|
||||||
static void isr0();
|
static void isr0();
|
||||||
void virtual interruptHandler();
|
void virtual interruptHandler();
|
||||||
virtual void interruptHook(uint8_t CTLbyte) {};
|
virtual void interruptHook(uint8_t CTLbyte) {};
|
||||||
|
static volatile bool _inISR;
|
||||||
virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false);
|
virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false);
|
||||||
|
|
||||||
static RFM69* selfPointer;
|
static RFM69* selfPointer;
|
||||||
|
|
@ -151,6 +152,7 @@ class RFM69 {
|
||||||
virtual void setHighPowerRegs(bool onOff);
|
virtual void setHighPowerRegs(bool onOff);
|
||||||
virtual void select();
|
virtual void select();
|
||||||
virtual void unselect();
|
virtual void unselect();
|
||||||
|
inline void maybeInterrupts();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue