Improvements to Olieman's MODI2C library. Supports calls from IRQ.

Dependencies:   FPointer

Dependents:   FreeIMU FreeIMU_external_magnetometer FreeIMU

Fork of MODI2C by Erik -

Revision:
5:fa0cca8e28b6
Parent:
1:eed116eb680a
--- a/MODI2C_IRQ.cpp	Sun Feb 09 14:05:04 2014 +0000
+++ b/MODI2C_IRQ.cpp	Wed Mar 28 21:48:20 2018 +0000
@@ -144,27 +144,33 @@
         Buffer = &Buffer2;
     }
 
-    //Start user interrupt
+    // Start user interrupt
     Buffer->curr->caller->runUserIRQ((I2CData*)Buffer->curr);
-    
+    // Free allocated data
     Buffer->pool.free((I2CData*)Buffer->curr);
     
+    // Don't attempt to call startBuffer if another
+    // thread is about to call it
     if (Buffer->crit_flag) return;
-    
+
+    // See if there is any other data to be written
     osEvent evt = Buffer->queue.get(0);
     if (evt.status == osEventMessage){
         Buffer->curr = (I2CData*)evt.value.p;
         startBuffer(I2CMODULE);
     }
     else{
+        // Set curr to NULL to indicate no data being written now
         Buffer->curr = NULL;
         _clearISR(I2CMODULE);
     }
 }
 
-//Returns true if succeeded, false if buffer is full
+// Returns true if succeeded, false if buffer is full
 bool MODI2C::addBuffer(I2CData *Data, LPC_I2C_TypeDef *I2CMODULE) {
-
+    // check if we are in an interrupt now
+    // __get_IPSR returns 0 when in Thread Mode,
+    // return value > 15 when in interrupt
     int interrupt = __get_IPSR();
 
     I2CBuffer *Buffer;
@@ -174,37 +180,49 @@
         Buffer = &Buffer2;
     }
     
+    // Hack to update status
     if(Data->status == NULL) {
         Data->status = &defaultStatus;
-        wait_us(1);     //I blame the compiler that this is needed
+        wait_us(1);     // I blame the compiler that this is needed
     }
     *(Data->status) = 0;
     
+    // Attempt to enqueue data to be written
     if (Buffer->queue.put(Data, 0)!=osOK){
-        if (interrupt!=0)
-            return false;   //no waiting in ISR
+        if (interrupt != 0)
+            return false;   // no waiting in ISR, and buffer is full.
+                            // no choice but to exit, return false for failure
         else
+            // wait for buffer to be available (should rarely happen!!)
+            // an interrupt will free Buffer when other write finishes
             while (Buffer->queue.put(Data, 0)!=osOK);
     }
     
-    if (interrupt!=0){
+    // Check for critical section in if in interrupt
+    if (interrupt != 0){
         if (Buffer->crit_flag_isr) return true;
-    }else Buffer->crit_flag_isr = true;
+    } else Buffer->crit_flag_isr = true;
     
+    // If no active writing
     if (Buffer->curr == NULL){
-        if (interrupt==0) Buffer->crit_flag = true;
+        // If we are not in an interrupt, we want to prevent
+        // bufferHandler interrupt code from messing with Buffer.
+        if (interrupt == 0) Buffer->crit_flag = true;
+        
+        // Get new data to be written
         osEvent evt = Buffer->queue.get(0);
         if (evt.status == osEventMessage){
             Buffer->curr = (volatile I2CData*)(evt.value.p);
-            if (interrupt==0) Buffer->crit_flag_isr = false;
-            if (interrupt==0) Buffer->crit_flag = false;
-            startBuffer(I2CMODULE);
-        }else{
-            if (interrupt==0) Buffer->crit_flag_isr = false;
-            if (interrupt==0) Buffer->crit_flag = false;
+            if (interrupt == 0) Buffer->crit_flag_isr = false;
+            if (interrupt == 0) Buffer->crit_flag = false;
+            startBuffer(I2CMODULE);     // start transfer
+        } else {    // No data
+            // "Leave" critical section
+            if (interrupt == 0) Buffer->crit_flag_isr = false;
+            if (interrupt == 0) Buffer->crit_flag = false;
         }
-    }else{
-        if (interrupt==0) Buffer->crit_flag_isr = false;
+    } else {
+        if (interrupt == 0) Buffer->crit_flag_isr = false;
     }