Modified version of the official mbed lib providing a RTOS enabled i2c-driver based on the official i2c-C-api.

Dependencies:   mbed-rtos mbed-src

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers I2CDriver.cpp Source File

I2CDriver.cpp

00001 #include "I2CDriver.h"
00002 #include "i2c_api.h"
00003 #include "error.h"
00004 
00005 using namespace mbed;
00006 using namespace rtos;
00007 
00008 extern "C"{
00009 osSemaphoreId i2cIsrDrvSem_1;
00010 osSemaphoreDef(i2cIsrDrvSem_1); 
00011 osSemaphoreId i2cIsrDrvSem_2;
00012 osSemaphoreDef(i2cIsrDrvSem_2); 
00013 }
00014 
00015 #define DRV_USR_SIG (1<<6)
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 #if defined(TARGET_LPC1768)
00023 void I2CDriver::channel_0_ISR()
00024 {
00025     osSemaphoreRelease(i2cIsrDrvSem_1);
00026     NVIC_DisableIRQ(I2C1_IRQn);
00027 }
00028 #endif
00029 
00030 void I2CDriver::channel_1_ISR()
00031 {
00032     osSemaphoreRelease(i2cIsrDrvSem_2);
00033 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
00034     NVIC_DisableIRQ(I2C2_IRQn);
00035 #elif defined(TARGET_LPC11U24)
00036     NVIC_DisableIRQ(I2C_IRQn);
00037 #endif
00038 }
00039 
00040 
00041 I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr)
00042 {
00043     // check pins and determine i2c channel
00044     int channel=0;
00045 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
00046     if(sda==c_sdas[0] && scl==c_scls[0]) channel=0; // I2C_1
00047     else
00048 #endif
00049         if (sda==c_sdas[1] && scl==c_scls[1]) channel=1; //I2C_2 or I2C
00050         else error("I2CDriver: Invalid I2C pinns selected");
00051 
00052     if(s_channels[channel]==0){
00053         new Thread(threadFun,(void *)channel,osPriorityRealtime,256);
00054         if(channel==0){
00055             i2cIsrDrvSem_1 = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_1), 1);
00056             osSemaphoreWait(i2cIsrDrvSem_1,osWaitForever);
00057         }else{
00058             i2cIsrDrvSem_2 = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_2), 1);
00059             osSemaphoreWait(i2cIsrDrvSem_2,osWaitForever);
00060         }
00061     }
00062     m_channel = s_channels[channel];
00063 }
00064 
00065 
00066 void I2CDriver::threadFun(void const *args)
00067 {
00068     int channelIdx = (int)args;
00069     Channel channel;
00070     s_channels[channelIdx] = &channel;
00071     channel.driver = Thread::gettid();
00072 
00073 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
00074     if(channelIdx==0)NVIC_SetVector(I2C1_IRQn, (uint32_t)I2CDriver::channel_0_ISR);
00075     if(channelIdx==1)NVIC_SetVector(I2C2_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
00076 #elif defined(TARGET_LPC11U24)
00077     NVIC_SetVector(I2C_IRQn, (uint32_t)I2CDriver::channel_1_ISR);
00078 #endif
00079 
00080     int freq = 0;
00081     int adrSlave = 0;
00082     int modeSlave = 0;
00083     i2c_t i2c;
00084     i2c_init(&i2c, c_sdas[channelIdx], c_scls[channelIdx]);
00085 
00086     volatile Transfer& tr = channel.transfer;
00087     while(1) {
00088         // wait for requests
00089         osSignalWait(DRV_USR_SIG,osWaitForever);
00090 
00091         // check and adapt frequency
00092         if(freq != tr.freq) {
00093             freq = tr.freq;
00094             i2c_frequency(&i2c, tr.freq);
00095         }
00096 
00097         // check and adapt slave/master mode
00098         if(modeSlave != tr.slv) {
00099             modeSlave = tr.slv;
00100             i2c_slave_mode(&i2c, tr.slv);
00101         }
00102 
00103         // check and adapt slave address
00104         int adr = (tr.adr & 0xFF) | 1;
00105         if(tr.slv && adrSlave != adr) {
00106             adrSlave = adr;
00107             i2c_slave_address(&i2c, 0, adr, 0);
00108         }
00109 
00110         // just doit
00111         switch(tr.cmd) {
00112             case START:
00113                 i2c_start(&i2c);
00114                 break;
00115             case STOP:
00116                 i2c_stop(&i2c);
00117                 break;
00118             case READ_MST:
00119                 tr.ret = i2c_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
00120                 break;
00121             case READ_MST_REG:
00122                 //printf("Disco\n");
00123                 tr.ret = i2c_write(&i2c, tr.adr,(const char*)&(tr.reg), 1, 0);
00124                 if(tr.ret)break; // error => bail out
00125                 tr.ret = i2c_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1));
00126                 break;
00127             case READ_SLV:
00128                 tr.ret = i2c_slave_read(&i2c, tr.dta, tr.len);
00129                 break;
00130             case READ_BYTE:
00131                 tr.ret = i2c_byte_read(&i2c, (tr.ack?0:1));
00132                 break;
00133             case WRITE_MST:
00134                 tr.ret = i2c_write(&i2c, tr.adr, tr.wdta, tr.len, (tr.rep?0:1));
00135                 break;
00136             case WRITE_SLV:
00137                 tr.ret = i2c_slave_write(&i2c, tr.wdta, tr.len);
00138                 break;
00139             case WRITE_BYTE:
00140                 tr.ret = i2c_byte_write(&i2c, tr.ack);
00141                 break;
00142             case RECEIVE:
00143                 tr.ret = i2c_slave_receive_rtos(&i2c, tr.tmout);
00144                 break;
00145             default:
00146                 error("call 911\n");
00147         }
00148         // inform the caller
00149         osSignalSet( channel.transfer.caller, DRV_USR_SIG);
00150     }
00151 }
00152 
00153 void I2CDriver::lock()
00154 {
00155     // One and the same thread can lock twice, but then it needs also to unlock twice.
00156     // exactly what we need here
00157     m_callerID = osThreadGetId();
00158     m_callerPrio = osThreadGetPriority(m_callerID);
00159     m_channel->mutex.lock(osWaitForever);
00160     osThreadSetPriority(m_callerID, c_drvPrio); // hopefully not interrupted since the lock
00161 }
00162 
00163 void I2CDriver::unlock()
00164 {
00165     // free the mtex and restore original prio
00166     m_channel->mutex.unlock();
00167     osThreadSetPriority(m_callerID, m_callerPrio);
00168 }
00169 
00170 int I2CDriver::sendNwait()
00171 {
00172     m_channel->transfer.freq = m_freq;
00173     m_channel->transfer.caller = Thread::gettid();
00174     osSignalSet( m_channel->driver, DRV_USR_SIG);
00175     osSignalWait(DRV_USR_SIG,osWaitForever);
00176     int ret = m_channel->transfer.ret;
00177     unlock();
00178     return ret;
00179 }
00180 
00181 int I2CDriver::readMaster(int address, char *data, int length, bool repeated)
00182 {
00183     lock();
00184     m_channel->transfer.cmd = READ_MST;
00185     m_channel->transfer.slv = false;
00186     m_channel->transfer.adr = address;
00187     m_channel->transfer.dta = data;
00188     m_channel->transfer.len = length;
00189     m_channel->transfer.rep = repeated;
00190     return sendNwait();
00191 }
00192 
00193 int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated)
00194 {
00195     lock();
00196     m_channel->transfer.cmd = READ_MST_REG;
00197     m_channel->transfer.slv = false;
00198     m_channel->transfer.adr = address;
00199     m_channel->transfer.reg = _register;
00200     m_channel->transfer.dta = data;
00201     m_channel->transfer.len = length;
00202     m_channel->transfer.rep = repeated;
00203     return sendNwait();
00204 }
00205 
00206 int I2CDriver::readMaster(int ack)
00207 {
00208     lock();
00209     m_channel->transfer.cmd = READ_BYTE;
00210     m_channel->transfer.slv = false;
00211     m_channel->transfer.ack = ack;
00212     return sendNwait();
00213 }
00214 
00215 int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated)
00216 {
00217     lock();
00218     m_channel->transfer.cmd = WRITE_MST;
00219     m_channel->transfer.slv = false;
00220     m_channel->transfer.adr = address;
00221     m_channel->transfer.wdta = data;
00222     m_channel->transfer.len = length;
00223     m_channel->transfer.rep = repeated;
00224     return sendNwait();
00225 }
00226 
00227 int I2CDriver::writeMaster(int data)
00228 {
00229     lock();
00230     m_channel->transfer.cmd = WRITE_BYTE;
00231     m_channel->transfer.slv = false;
00232     m_channel->transfer.ack = data;
00233     return sendNwait();
00234 }
00235 
00236 void I2CDriver::startMaster(void)
00237 {
00238     lock();
00239     m_channel->transfer.cmd = START;
00240     m_channel->transfer.slv = false;
00241     sendNwait();
00242 }
00243 
00244 void I2CDriver::stopMaster(void)
00245 {
00246     lock();
00247     m_channel->transfer.cmd = STOP;
00248     m_channel->transfer.slv = false;
00249     sendNwait();
00250 }
00251 
00252 void I2CDriver::stopSlave(void)
00253 {
00254     lock();
00255     m_channel->transfer.cmd = STOP;
00256     m_channel->transfer.slv = true;
00257     m_channel->transfer.adr = m_slaveAdr;
00258     sendNwait();
00259 }
00260 
00261 int I2CDriver::receiveSlave(uint32_t timeout_ms)
00262 {
00263     lock();
00264     m_channel->transfer.cmd = RECEIVE;
00265     m_channel->transfer.slv = true;
00266     m_channel->transfer.adr = m_slaveAdr;
00267     m_channel->transfer.tmout = timeout_ms;
00268     return sendNwait();
00269 }
00270 
00271 int I2CDriver::readSlave(char* data, int length)
00272 {
00273     lock();
00274     m_channel->transfer.cmd = READ_SLV;
00275     m_channel->transfer.slv = true;
00276     m_channel->transfer.adr = m_slaveAdr;
00277     m_channel->transfer.dta = data;
00278     m_channel->transfer.len = length;
00279     return sendNwait();
00280 }
00281 
00282 int I2CDriver::readSlave(void)
00283 {
00284     lock();
00285     m_channel->transfer.cmd = READ_BYTE;
00286     m_channel->transfer.slv = true;
00287     m_channel->transfer.adr = m_slaveAdr;
00288     m_channel->transfer.ack = 1;
00289     return sendNwait();
00290 }
00291 
00292 int I2CDriver::writeSlave(const char *data, int length)
00293 {
00294     lock();
00295     m_channel->transfer.cmd = WRITE_SLV;
00296     m_channel->transfer.slv = true;
00297     m_channel->transfer.adr = m_slaveAdr;
00298     m_channel->transfer.wdta = data;
00299     m_channel->transfer.len = length;
00300     return sendNwait();
00301 }
00302 
00303 int I2CDriver::writeSlave(int data)
00304 {
00305     lock();
00306     m_channel->transfer.cmd = WRITE_BYTE;
00307     m_channel->transfer.slv = true;
00308     m_channel->transfer.adr = m_slaveAdr;
00309     m_channel->transfer.ack = data;
00310     return sendNwait();
00311 }
00312 
00313 
00314 
00315