SX1272Lib updated in order to be RTOS aware

Fork of SX1272Lib by Semtech

Since Semtech original SX1272 library used InterruptIn and Timout mbed-os classes, whose ISRs are not allowed to lock RTOS mutexes, any SPI-related operation was doomed to fail. Indeed, SPI transactions functions are always nested inside a spi-level mutex lock/unlock pair in order to provide for thread access safety. A typical case occurs for example when radio is set to sleep state after a RX timeout.

This fork solves such problems by mean of a EventQueue/Thread pair, where any InterruptIn and Timeout ISRs actually enqueue callback calls.

Take a look at usage example at https://github.com/maiorfi/mbedos_lablet_lora_1

Revision:
8:1002d3025eaa
Parent:
7:b988b60083a1
Child:
10:bd29cdff8f3e
--- a/sx1272/sx1272.cpp	Mon Apr 24 09:26:08 2017 +0000
+++ b/sx1272/sx1272.cpp	Sat Feb 10 08:58:42 2018 +0100
@@ -58,12 +58,12 @@
 
     this->dioIrq = new DioIrqHandler[6];
 
-    this->dioIrq[0] = &SX1272::OnDio0Irq;
-    this->dioIrq[1] = &SX1272::OnDio1Irq;
-    this->dioIrq[2] = &SX1272::OnDio2Irq;
-    this->dioIrq[3] = &SX1272::OnDio3Irq;
-    this->dioIrq[4] = &SX1272::OnDio4Irq;
-    this->dioIrq[5] = NULL;
+    this->dioIrq[0] = &SX1272::enqueueOnDio0Irq; /*&SX1272::OnDio0Irq;*/
+    this->dioIrq[1] = &SX1272::enqueueOnDio1Irq; /*&SX1272::OnDio1Irq;*/
+    this->dioIrq[2] = &SX1272::enqueueOnDio2Irq; /*&SX1272::OnDio2Irq;*/
+    this->dioIrq[3] = &SX1272::enqueueOnDio3Irq; /*&SX1272::OnDio3Irq;*/
+    this->dioIrq[4] = &SX1272::enqueueOnDio4Irq; /*&SX1272::OnDio4Irq;*/
+    this->dioIrq[5] = &SX1272::enqueueOnDio5Irq; /*NULL;*/
 
     this->settings.State = RF_IDLE;
 }
@@ -77,6 +77,10 @@
 void SX1272::Init( RadioEvents_t *events )
 {
     this->RadioEvents = events;
+
+    // <RTOS>
+    _thread_events_queue.start(callback(&_eq_events, &EventQueue::dispatch_forever));
+    // </RTOS>
 }
 
 RadioState SX1272::GetStatus( void )
@@ -682,7 +686,7 @@
     this->settings.State = RF_RX_RUNNING;
     if( timeout != 0 )
     {
-        rxTimeoutTimer.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), timeout * 1e3 );
+        rxTimeoutTimer.attach_us(mbed::callback( this, &SX1272::enqueueOnTimeoutIrq /*&SX1272::OnTimeoutIrq*/ ), timeout * 1e3 );
     }
 
     if( this->settings.Modem == MODEM_FSK )
@@ -691,7 +695,7 @@
 
         if( rxContinuous == false )
         {
-            rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ),
+            rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::enqueueOnTimeoutIrq /*&SX1272::OnTimeoutIrq*/ ),
                                          this->settings.Fsk.RxSingleTimeout * 1e3 );
         }
     }
@@ -766,7 +770,7 @@
     }
 
     this->settings.State = RF_TX_RUNNING;
-    txTimeoutTimer.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), timeout * 1e3 );
+    txTimeoutTimer.attach_us( mbed::callback( this, &SX1272::enqueueOnTimeoutIrq /*&SX1272::OnTimeoutIrq*/ ), timeout * 1e3 );
     SetOpMode( RF_OPMODE_TRANSMITTER );
 }
 
@@ -817,7 +821,7 @@
     Write( REG_DIOMAPPING2, RF_DIOMAPPING2_DIO4_10 | RF_DIOMAPPING2_DIO5_10 );
 
     this->settings.State = RF_TX_RUNNING;
-    txTimeoutTimer.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), timeout );
+    txTimeoutTimer.attach_us( mbed::callback( this, &SX1272::enqueueOnTimeoutIrq /*&SX1272::OnTimeoutIrq*/ ), timeout );
     SetOpMode( RF_OPMODE_TRANSMITTER );
 }
 
@@ -947,7 +951,7 @@
             {
                 // Continuous mode restart Rx chain
                 Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
-                rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ),
+                rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::enqueueOnTimeoutIrq /*&SX1272::OnTimeoutIrq*/ ),
                                              this->settings.Fsk.RxSingleTimeout * 1e3 );
             }
             else
@@ -958,7 +962,8 @@
         }
         if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxTimeout != NULL ) )
         {
-            this->RadioEvents->RxTimeout( );
+            /*this->RadioEvents->RxTimeout( );*/
+            enqueueRadioEvent_RxTimeout();
         }
         break;
     case RF_TX_RUNNING:
@@ -987,7 +992,8 @@
         this->settings.State = RF_IDLE;
         if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->TxTimeout != NULL ) )
         {
-            this->RadioEvents->TxTimeout( );
+            /*this->RadioEvents->TxTimeout( );*/
+            enqueueRadioEvent_TxTimeout();
         }
         break;
     default:
@@ -1029,13 +1035,14 @@
                         {
                             // Continuous mode restart Rx chain
                             Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
-                            rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ),
+                            rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::enqueueOnTimeoutIrq /*&SX1272::OnTimeoutIrq*/ ),
                                                          this->settings.Fsk.RxSingleTimeout * 1e3 );
                         }
 
                         if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxError != NULL ) )
                         {
-                            this->RadioEvents->RxError( );
+                            /*this->RadioEvents->RxError( );*/
+                            enqueueRadioEvent_RxError();
                         }
                         this->settings.FskPacketHandler.PreambleDetected = false;
                         this->settings.FskPacketHandler.SyncWordDetected = false;
@@ -1076,13 +1083,14 @@
                 {
                     // Continuous mode restart Rx chain
                     Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK );
-                    rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ),
+                    rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::enqueueOnTimeoutIrq /*&SX1272::OnTimeoutIrq*/ ),
                                                  this->settings.Fsk.RxSingleTimeout * 1e3 );
                 }
 
                 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxDone != NULL ) )
                 {
-                    this->RadioEvents->RxDone( rxtxBuffer, this->settings.FskPacketHandler.Size, this->settings.FskPacketHandler.RssiValue, 0 );
+                    /*this->RadioEvents->RxDone( rxtxBuffer, this->settings.FskPacketHandler.Size, this->settings.FskPacketHandler.RssiValue, 0 );*/
+                    enqueueRadioEvent_RxDone(rxtxBuffer, this->settings.FskPacketHandler.Size, this->settings.FskPacketHandler.RssiValue, 0);
                 }
                 this->settings.FskPacketHandler.PreambleDetected = false;
                 this->settings.FskPacketHandler.SyncWordDetected = false;
@@ -1110,7 +1118,8 @@
 
                         if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxError != NULL ) )
                         {
-                            this->RadioEvents->RxError( );
+                            /*this->RadioEvents->RxError( );*/
+                            enqueueRadioEvent_RxError();
                         }
                         break;
                     }
@@ -1150,7 +1159,8 @@
 
                     if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxDone != NULL ) )
                     {
-                        this->RadioEvents->RxDone( rxtxBuffer, this->settings.LoRaPacketHandler.Size, this->settings.LoRaPacketHandler.RssiValue, this->settings.LoRaPacketHandler.SnrValue );
+                        /*this->RadioEvents->RxDone( rxtxBuffer, this->settings.LoRaPacketHandler.Size, this->settings.LoRaPacketHandler.RssiValue, this->settings.LoRaPacketHandler.SnrValue );*/
+                        enqueueRadioEvent_RxDone(rxtxBuffer, this->settings.LoRaPacketHandler.Size, this->settings.LoRaPacketHandler.RssiValue, this->settings.LoRaPacketHandler.SnrValue);
                     }
                 }
                 break;
@@ -1172,7 +1182,8 @@
                 this->settings.State = RF_IDLE;
                 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->TxDone != NULL ) )
                 {
-                    this->RadioEvents->TxDone( );
+                    /*this->RadioEvents->TxDone( );*/
+                    enqueueRadioEvent_TxDone();
                 }
                 break;
             }
@@ -1224,7 +1235,8 @@
                 this->settings.State = RF_IDLE;
                 if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxTimeout != NULL ) )
                 {
-                    this->RadioEvents->RxTimeout( );
+                    /*this->RadioEvents->RxTimeout( );*/
+                    enqueueRadioEvent_RxTimeout();
                 }
                 break;
             default:
@@ -1295,7 +1307,8 @@
 
                     if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->FhssChangeChannel != NULL ) )
                     {
-                        this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) );
+                        /*this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) );*/
+                        enqueueRadioEvent_FhssChangeChannel(( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) );
                     }
                 }
                 break;
@@ -1316,7 +1329,8 @@
 
                     if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->FhssChangeChannel != NULL ) )
                     {
-                        this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) );
+                        /*this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) );*/
+                        enqueueRadioEvent_FhssChangeChannel(( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ));
                     }
                 }
                 break;
@@ -1342,7 +1356,8 @@
             Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE );
             if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->CadDone != NULL ) )
             {
-                this->RadioEvents->CadDone( true );
+                /*this->RadioEvents->CadDone( true );*/
+                enqueueRadioEvent_CadDone(true);
             }
         }
         else
@@ -1351,7 +1366,8 @@
             Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE );
             if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->CadDone != NULL ) )
             {
-                this->RadioEvents->CadDone( false );
+                /*this->RadioEvents->CadDone( false );*/
+                enqueueRadioEvent_CadDone(false);
             }
         }
         break;
@@ -1391,3 +1407,112 @@
         break;
     }
 }
+
+// Inizio nuova parte per RTOS
+
+void SX1272::enqueueOnTimeoutIrq()
+{
+    _eq_events.call(this, &SX1272::OnTimeoutIrq);
+}
+
+void SX1272::radioEvent_RxTimeout()
+{
+    this->RadioEvents->RxTimeout( );
+}
+
+void SX1272::enqueueRadioEvent_RxTimeout()
+{
+     _eq_events.call(this, &SX1272::radioEvent_RxTimeout);
+}
+
+void SX1272::radioEvent_TxTimeout()
+{
+    this->RadioEvents->TxTimeout( );
+}
+
+void SX1272::enqueueRadioEvent_TxTimeout()
+{
+     _eq_events.call(this, &SX1272::radioEvent_TxTimeout);
+}
+
+void SX1272::radioEvent_RxError()
+{
+    this->RadioEvents->RxError( );
+}
+
+void SX1272::enqueueRadioEvent_RxError()
+{
+     _eq_events.call(this, &SX1272::radioEvent_RxError);
+}
+
+void SX1272::radioEvent_RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
+{
+    this->RadioEvents->RxDone(payload, size, rssi, snr);
+}
+
+void SX1272::enqueueRadioEvent_RxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
+{
+     _eq_events.call(this, &SX1272::radioEvent_RxDone, payload, size, rssi, snr);
+}
+
+void SX1272::radioEvent_TxDone()
+{
+    this->RadioEvents->TxDone();
+}
+
+void SX1272::enqueueRadioEvent_TxDone()
+{
+     _eq_events.call(this, &SX1272::radioEvent_TxDone);
+}
+
+void SX1272::radioEvent_FhssChangeChannel(uint8_t currentChannel)
+{
+    this->RadioEvents->FhssChangeChannel(currentChannel);
+}
+
+void SX1272::enqueueRadioEvent_FhssChangeChannel(uint8_t currentChannel)
+{
+    _eq_events.call(this, &SX1272::radioEvent_FhssChangeChannel, currentChannel);
+}
+
+void SX1272::radioEvent_CadDone(bool channelActivityDetected)
+{
+    this->RadioEvents->CadDone(channelActivityDetected);
+}
+
+void SX1272::enqueueRadioEvent_CadDone(bool channelActivityDetected)
+{
+    _eq_events.call(this, &SX1272::radioEvent_CadDone, channelActivityDetected);
+}
+
+void SX1272::enqueueOnDio0Irq()
+{
+    _eq_events.call(this, &SX1272::OnDio0Irq);
+}
+
+void SX1272::enqueueOnDio1Irq()
+{
+    _eq_events.call(this, &SX1272::OnDio1Irq);
+}
+
+void SX1272::enqueueOnDio2Irq()
+{
+    _eq_events.call(this, &SX1272::OnDio2Irq);
+}
+
+void SX1272::enqueueOnDio3Irq()
+{
+    _eq_events.call(this, &SX1272::OnDio3Irq);
+}
+
+void SX1272::enqueueOnDio4Irq()
+{
+    _eq_events.call(this, &SX1272::OnDio4Irq);
+}
+
+void SX1272::enqueueOnDio5Irq()
+{
+    /* NULL */
+}
+
+// Fine nuova parte per RTOS
\ No newline at end of file