Handle interrupt outside actual ISR

### Commit adapted from 2793a5a909

Handling an interrupt from the RFM69 inside an actual ISR given the
complexity of the handler appears to conflict with I2C devices, blocking
the Arduino indefinitely after a few seconds of concurrent use. In
general, complex ISRs are to be avoided.
This commit is contained in:
Felix Rusu 2018-08-08 15:34:31 -04:00
parent c51a7c7b99
commit 3d4a8c99c4
2 changed files with 8 additions and 16 deletions

View File

@ -36,7 +36,7 @@ volatile uint8_t RFM69::PAYLOADLEN;
volatile uint8_t RFM69::ACK_REQUESTED;
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 bool RFM69::_inISR;
volatile bool RFM69::_haveData;
RFM69* RFM69::selfPointer;
RFM69::RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW)
@ -127,7 +127,6 @@ 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
if (millis()-start >= timeout)
return false;
_inISR = false;
attachInterrupt(_interruptNum, RFM69::isr0, RISING);
selfPointer = this;
@ -376,7 +375,7 @@ void RFM69::interruptHandler() {
}
// internal function
void RFM69::isr0() { _inISR = true; selfPointer->interruptHandler(); _inISR = false; }
void RFM69::isr0() { _haveData = true; }
// internal function
void RFM69::receiveBegin() {
@ -400,7 +399,10 @@ void RFM69::receiveBegin() {
bool RFM69::receiveDone() {
//ATOMIC_BLOCK(ATOMIC_FORCEON)
//{
noInterrupts(); // re-enabled in unselect() via setMode() or via receiveBegin()
if (_haveData) {
_haveData = false;
interruptHandler();
}
if (_mode == RF69_MODE_RX && PAYLOADLEN > 0)
{
setMode(RF69_MODE_STANDBY); // enables interrupts
@ -408,7 +410,6 @@ bool RFM69::receiveDone() {
}
else if (_mode == RF69_MODE_RX) // already in RX no payload yet
{
interrupts(); // explicitly re-enable interrupts
return false;
}
receiveBegin();
@ -471,7 +472,6 @@ void RFM69::writeReg(uint8_t addr, uint8_t value)
// select the RFM69 transceiver (save SPI settings, set CS low)
void RFM69::select() {
noInterrupts();
#if defined (SPCR) && defined (SPSR)
// save current SPI settings
_SPCR = SPCR;
@ -496,7 +496,6 @@ void RFM69::unselect() {
SPCR = _SPCR;
SPSR = _SPSR;
#endif
maybeInterrupts();
}
// true = disable filtering to capture all frames on network
@ -851,12 +850,6 @@ void RFM69::rcCalibration()
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();
}
//=============================================================================
// ListenMode specific functions
//=============================================================================

View File

@ -207,9 +207,9 @@ class RFM69 {
protected:
static void isr0();
void virtual interruptHandler();
void interruptHandler();
virtual void interruptHook(uint8_t CTLbyte) {};
static volatile bool _inISR;
static volatile bool _haveData;
virtual void sendFrame(uint8_t toAddress, const void* buffer, uint8_t size, bool requestACK=false, bool sendACK=false);
static RFM69* selfPointer;
@ -230,7 +230,6 @@ class RFM69 {
virtual void setHighPowerRegs(bool onOff);
virtual void select();
virtual void unselect();
inline void maybeInterrupts();
#if defined(RF69_LISTENMODE_ENABLE)
//=============================================================================