RTOS enabled i2c-driver based on the official i2c-C-api.

Dependencies:   mbed-rtos

Fork of mbed-RtosI2cDriver by Helmut Schmücker

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers I2CDriver.cpp Source File

I2CDriver.cpp

00001 #include "I2CDriver.h"
00002 #include "i2cRtos_api.h"
00003 //#include "rt_System.h"
00004 #include "error.h"
00005 
00006 using namespace mbed;
00007 using namespace rtos;
00008 
00009 //DigitalOut I2CDriver::osci2(p7);
00010 
00011 #define PREFIX i2cRtos
00012 //#define PREFIX i2c // fallback to offical busy wait i2c c-api for performance testing 
00013 #define PASTER(x,y) x ## _ ## y
00014 #define EVALUATOR(x,y)  PASTER(x,y)
00015 #define FUNCTION(fun) EVALUATOR(PREFIX, fun)
00016 
00017 const PinName I2CDriver::c_sdas[] = {p9,p28};
00018 const PinName I2CDriver::c_scls[] = {p10,p27};
00019 
00020 I2CDriver::Channel* I2CDriver::s_channels[2] = {0,0};
00021 
00022 I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr)
00023 {
00024     // ensure exclusive access for initialization 
00025     static Mutex mtx;
00026     bool locked = false;
00027     if(osKernelRunning()) {  // but don't try to lock if rtos kernel is not running yet. (global/static definition) 
00028         mtx.lock();
00029         locked = true;
00030     }
00031 
00032     // check pins and determine i2c channel
00033     int channel=0;
00034 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
00035     if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
00036     else
00037 #endif
00038         if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
00039         else error("I2CDriver: Invalid I2C pins selected\n");
00040     
00041     // initialize the selected i2c channel 
00042     if(s_channels[channel]==0) {
00043         s_channels[channel] = new I2CDriver::Channel;
00044         m_channel = s_channels[channel];
00045         m_channel->freq = 0;
00046         m_channel->slaveAdr = 0;
00047         m_channel->modeSlave = 0;
00048         m_channel->initialized=false; // defer i2c initialization util we are sure the rtos kernel is running (config() function)
00049     }
00050     m_channel = s_channels[channel];
00051     if(locked) mtx.unlock();
00052 }
00053 
00054 void I2CDriver::lock()
00055 {
00056     //osci2.write(1);
00057     // One and the same thread can lock twice, but then it needs also to unlock twice.
00058     // exactly what we need here
00059     m_channel->mutex.lock(osWaitForever);
00060     m_channel->callerID = osThreadGetId();
00061     m_channel->callerPrio = osThreadGetPriority(m_channel->callerID);
00062     // maximize thread prio
00063     osThreadSetPriority(m_channel->callerID, c_drvPrio); // hopefully not interrupted since the lock in the line above
00064     // mutex code looks like that waiting threads are priority ordered
00065     // also priority inheritance seems to be provided
00066     //osci2.write(0);
00067 }
00068 
00069 void I2CDriver::unlock()
00070 {
00071     //osci2.write(1);
00072     // free the mutex and restore original prio
00073     //rt_tsk_lock();  // just prevent beeing preempted after restoring prio before freeing the mutex 
00074     osThreadSetPriority(m_channel->callerID, m_channel->callerPrio);
00075     m_channel->mutex.unlock();   
00076     //rt_tsk_unlock();
00077     //osci2.write(0);
00078 }
00079 
00080 void I2CDriver::config()
00081 {
00082     //osci2.write(1);
00083     // check and initialize driver
00084     if(!m_channel->initialized) {
00085         int channel = m_channel==s_channels[0] ? 0 : 1; // ...ugly
00086         FUNCTION(init)(&m_channel->i2c, c_sdas[channel], c_scls[channel]);
00087         m_channel->initialized=true;
00088     }
00089     // check and update frequency
00090     if(m_freq != m_channel->freq) {
00091         m_channel->freq = m_freq;
00092         i2c_frequency(&m_channel->i2c, m_freq);
00093     }
00094     // check and update slave/master mode
00095     if(m_modeSlave != m_channel->modeSlave) {
00096         m_channel->modeSlave = m_modeSlave;
00097         i2c_slave_mode(&m_channel->i2c, m_modeSlave);
00098     }
00099     // check and update slave address
00100     if(m_modeSlave && m_slaveAdr != m_channel->slaveAdr) {
00101         m_channel->slaveAdr = m_slaveAdr;
00102         i2c_slave_address(&m_channel->i2c, 0, m_slaveAdr, 0);
00103     }
00104     //osci2.write(0);
00105 }
00106 
00107 int I2CDriver::readMaster(int address, char *data, int length, bool repeated)
00108 {
00109     m_modeSlave = false;
00110     lockNconfig();
00111     int ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1));
00112     unlock();
00113     return ret;
00114 }
00115 int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated)
00116 {
00117     m_modeSlave = false;
00118     lockNconfig();
00119     int ret = FUNCTION(write)(&m_channel->i2c, address,(const char*)&_register, 1, 0);
00120     if(!ret) ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1));
00121     unlock();
00122     return ret;
00123 }
00124 int I2CDriver::readMaster(int ack)
00125 {
00126     m_modeSlave = false;
00127     lockNconfig();
00128     int ret = i2cRtos_byte_read(&m_channel->i2c, (ack?0:1));
00129     unlock();
00130     return ret;
00131 }
00132 int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated)
00133 {
00134     m_modeSlave = false;
00135     lockNconfig();
00136     int ret = FUNCTION(write)(&m_channel->i2c, address, data, length, (repeated?0:1));
00137     unlock();
00138     return ret;
00139 }
00140 int I2CDriver::writeMaster(int data)
00141 {
00142     m_modeSlave = false;
00143     lockNconfig();
00144     int ret = i2cRtos_byte_write(&m_channel->i2c, data);
00145     unlock();
00146     return ret;
00147 }
00148 void I2CDriver::startMaster(void)
00149 {
00150     m_modeSlave = false;
00151     lockNconfig();
00152     i2c_start(&m_channel->i2c);
00153     unlock();
00154 }
00155 bool I2CDriver::stopMaster(void)
00156 {
00157     m_modeSlave = false;
00158     lockNconfig();
00159     bool ret=i2cRtos_stop(&m_channel->i2c);
00160     unlock();
00161     return ret;
00162 }
00163 void I2CDriver::stopSlave(void)
00164 {
00165     m_modeSlave = true;
00166     lockNconfig();
00167     i2c_stop(&m_channel->i2c);
00168     unlock();
00169 }
00170 int I2CDriver::receiveSlave(uint32_t timeout_ms)
00171 {
00172     m_modeSlave = true;
00173     lockNconfig();
00174     int ret = i2cRtos_slave_receive(&m_channel->i2c, timeout_ms);
00175     unlock();
00176     return ret;
00177 }
00178 int I2CDriver::readSlave(char* data, int length)
00179 {
00180     m_modeSlave = true;
00181     lockNconfig();
00182     int ret = i2cRtos_slave_read(&m_channel->i2c, data, length);
00183     unlock();
00184     return ret;
00185 }
00186 int I2CDriver::readSlave(void)
00187 {
00188     m_modeSlave = true;
00189     lockNconfig();
00190     int ret = i2cRtos_byte_read(&m_channel->i2c, 0);
00191     unlock();
00192     return ret;
00193 }
00194 int I2CDriver::writeSlave(const char *data, int length)
00195 {
00196     m_modeSlave = true;
00197     lockNconfig();
00198     int ret = i2cRtos_slave_write(&m_channel->i2c, data, length);
00199     unlock();
00200     return ret;
00201 }
00202 int I2CDriver::writeSlave(int data)
00203 {
00204     m_modeSlave = true;
00205     lockNconfig();
00206     int ret = i2cRtos_byte_write(&m_channel->i2c, data);
00207     unlock();
00208     return ret;
00209 }
00210 
00211 
00212 
00213