I2CRTOS Driver by Helmut Schmücker. Removed included mbed-rtos library to prevent multiple definition. Make sure to include mbed-rtos library in your program!

Fork of I2cRtosDriver by Helmut Schmücker

Revision:
14:352609d395c1
Parent:
13:530968937ccb
diff -r 530968937ccb -r 352609d395c1 I2CDriver.cpp
--- a/I2CDriver.cpp	Fri May 10 20:38:35 2013 +0000
+++ b/I2CDriver.cpp	Sun May 19 11:21:16 2013 +0000
@@ -1,11 +1,15 @@
 #include "I2CDriver.h"
 #include "i2cRtos_api.h"
+//#include "rt_System.h"
 #include "error.h"
 
 using namespace mbed;
 using namespace rtos;
 
-#define PREFIX i2c
+//DigitalOut I2CDriver::osci2(p7);
+
+#define PREFIX i2cRtos
+//#define PREFIX i2c // fallback to offical busy wait i2c c-api for performance testing 
 #define PASTER(x,y) x ## _ ## y
 #define EVALUATOR(x,y)  PASTER(x,y)
 #define FUNCTION(fun) EVALUATOR(PREFIX, fun)
@@ -17,8 +21,14 @@
 
 I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr)
 {
-    static Mutex mutex;
-    mutex.lock();
+    // ensure exclusive access for initialization 
+    static Mutex mtx;
+    bool locked = false;
+    if(osKernelRunning()) {  // but don't try to lock if rtos kernel is not running yet. (global/static definition) 
+        mtx.lock();
+        locked = true;
+    }
+
     // check pins and determine i2c channel
     int channel=0;
 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
@@ -27,41 +37,55 @@
 #endif
         if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
         else error("I2CDriver: Invalid I2C pins selected\n");
-
+    
+    // initialize the selected i2c channel 
     if(s_channels[channel]==0) {
         s_channels[channel] = new I2CDriver::Channel;
         m_channel = s_channels[channel];
         m_channel->freq = 0;
         m_channel->slaveAdr = 0;
         m_channel->modeSlave = 0;
-        FUNCTION(init)(&m_channel->i2c, c_sdas[channel], c_scls[channel]);
+        m_channel->initialized=false; // defer i2c initialization util we are sure the rtos kernel is running (config() function)
     }
     m_channel = s_channels[channel];
-    mutex.unlock();
+    if(locked) mtx.unlock();
 }
 
 void I2CDriver::lock()
 {
+    //osci2.write(1);
     // One and the same thread can lock twice, but then it needs also to unlock twice.
     // exactly what we need here
-    m_callerID = osThreadGetId();
-    m_callerPrio = osThreadGetPriority(m_callerID);
     m_channel->mutex.lock(osWaitForever);
+    m_channel->callerID = osThreadGetId();
+    m_channel->callerPrio = osThreadGetPriority(m_channel->callerID);
     // maximize thread prio
-    osThreadSetPriority(m_callerID, c_drvPrio); // hopefully not interrupted since the lock in the line above
+    osThreadSetPriority(m_channel->callerID, c_drvPrio); // hopefully not interrupted since the lock in the line above
     // mutex code looks like that waiting threads are priority ordered
     // also priority inheritance seems to be provided
+    //osci2.write(0);
 }
 
 void I2CDriver::unlock()
 {
+    //osci2.write(1);
     // free the mutex and restore original prio
-    m_channel->mutex.unlock();
-    osThreadSetPriority(m_callerID, m_callerPrio);
+    //rt_tsk_lock();  // just prevent beeing preempted after restoring prio before freeing the mutex 
+    osThreadSetPriority(m_channel->callerID, m_channel->callerPrio);
+    m_channel->mutex.unlock();   
+    //rt_tsk_unlock();
+    //osci2.write(0);
 }
 
 void I2CDriver::config()
 {
+    //osci2.write(1);
+    // check and initialize driver
+    if(!m_channel->initialized) {
+        int channel = m_channel==s_channels[0] ? 0 : 1; // ...ugly
+        FUNCTION(init)(&m_channel->i2c, c_sdas[channel], c_scls[channel]);
+        m_channel->initialized=true;
+    }
     // check and update frequency
     if(m_freq != m_channel->freq) {
         m_channel->freq = m_freq;
@@ -77,6 +101,7 @@
         m_channel->slaveAdr = m_slaveAdr;
         i2c_slave_address(&m_channel->i2c, 0, m_slaveAdr, 0);
     }
+    //osci2.write(0);
 }
 
 int I2CDriver::readMaster(int address, char *data, int length, bool repeated)