Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-RtosI2cDriver by
Diff: I2CDriver.cpp
- Revision:
- 13:530968937ccb
- Parent:
- 11:8c1d44595620
- Child:
- 14:352609d395c1
diff -r 6ddadcbbdca2 -r 530968937ccb I2CDriver.cpp --- a/I2CDriver.cpp Fri May 10 07:34:24 2013 +0000 +++ b/I2CDriver.cpp Fri May 10 20:38:35 2013 +0000 @@ -5,7 +5,10 @@ using namespace mbed; using namespace rtos; -#define DRV_USR_SIG (1<<6) +#define PREFIX i2c +#define PASTER(x,y) x ## _ ## y +#define EVALUATOR(x,y) PASTER(x,y) +#define FUNCTION(fun) EVALUATOR(PREFIX, fun) const PinName I2CDriver::c_sdas[] = {p9,p28}; const PinName I2CDriver::c_scls[] = {p10,p27}; @@ -14,6 +17,8 @@ I2CDriver::I2CDriver(PinName sda, PinName scl, int hz, int slaveAdr):m_freq(hz),m_slaveAdr(slaveAdr) { + static Mutex mutex; + mutex.lock(); // check pins and determine i2c channel int channel=0; #if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) @@ -24,89 +29,15 @@ else error("I2CDriver: Invalid I2C pins selected\n"); if(s_channels[channel]==0) { - new Thread(threadFun,(void *)channel,osPriorityRealtime,1024); // evillive + 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 = s_channels[channel]; -} - - -void I2CDriver::threadFun(void const *args) -{ - int channelIdx = (int)args; - Channel channel; - s_channels[channelIdx] = &channel; - channel.driver = Thread::gettid(); - - int freq = 0; - int adrSlave = 0; - int modeSlave = 0; - i2c_t i2c; - i2cRtos_init(&i2c, c_sdas[channelIdx], c_scls[channelIdx]); - - volatile Transfer& tr = channel.transfer; - while(1) { - // wait for requests - osSignalWait(DRV_USR_SIG,osWaitForever); - - // check and adapt frequency - if(freq != tr.freq) { - freq = tr.freq; - i2c_frequency(&i2c, tr.freq); - } - - // check and adapt slave/master mode - if(modeSlave != tr.slv) { - modeSlave = tr.slv; - i2c_slave_mode(&i2c, tr.slv); - } - - // check and adapt slave address - int adr = (tr.adr & 0xFF) | 1; - if(tr.slv && adrSlave != adr) { - adrSlave = adr; - i2c_slave_address(&i2c, 0, adr, 0); - } - - // just doit - switch(tr.cmd) { - case START: - i2c_start(&i2c); - break; - case STOP: - i2c_stop(&i2c); - break; - case READ_MST: - tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1)); - break; - case READ_MST_REG: - tr.ret = i2cRtos_write(&i2c, tr.adr,(const char*)&(tr.reg), 1, 0); - if(tr.ret)break; // error => bail out - tr.ret = i2cRtos_read(&i2c, tr.adr, tr.dta, tr.len, (tr.rep?0:1)); - break; - case READ_SLV: - tr.ret = i2cRtos_slave_read(&i2c, tr.dta, tr.len); - break; - case READ_BYTE: - tr.ret = i2cRtos_byte_read(&i2c, (tr.ack?0:1)); - break; - case WRITE_MST: - tr.ret = i2cRtos_write(&i2c, tr.adr, tr.wdta, tr.len, (tr.rep?0:1)); - break; - case WRITE_SLV: - tr.ret = i2cRtos_slave_write(&i2c, tr.wdta, tr.len); - break; - case WRITE_BYTE: - tr.ret = i2cRtos_byte_write(&i2c, tr.ack); - break; - case RECEIVE: - tr.ret = i2cRtos_slave_receive(&i2c, tr.tmout); - break; - default: - error("call 911\n"); - } - // inform the caller - osSignalSet( channel.transfer.caller, DRV_USR_SIG); - } + mutex.unlock(); } void I2CDriver::lock() @@ -116,157 +47,140 @@ m_callerID = osThreadGetId(); m_callerPrio = osThreadGetPriority(m_callerID); m_channel->mutex.lock(osWaitForever); - osThreadSetPriority(m_callerID, c_drvPrio); // evillive hopefully not interrupted since the lock + // maximize thread prio + osThreadSetPriority(m_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 } void I2CDriver::unlock() { - // free the mtex and restore original prio + // free the mutex and restore original prio m_channel->mutex.unlock(); osThreadSetPriority(m_callerID, m_callerPrio); } -int I2CDriver::sendNwait() +void I2CDriver::config() { - m_channel->transfer.freq = m_freq; - m_channel->transfer.caller = Thread::gettid(); - osSignalSet( m_channel->driver, DRV_USR_SIG); - osSignalWait(DRV_USR_SIG,osWaitForever); - int ret = m_channel->transfer.ret; - unlock(); - return ret; + // check and update frequency + if(m_freq != m_channel->freq) { + m_channel->freq = m_freq; + i2c_frequency(&m_channel->i2c, m_freq); + } + // check and update slave/master mode + if(m_modeSlave != m_channel->modeSlave) { + m_channel->modeSlave = m_modeSlave; + i2c_slave_mode(&m_channel->i2c, m_modeSlave); + } + // check and update slave address + if(m_modeSlave && m_slaveAdr != m_channel->slaveAdr) { + m_channel->slaveAdr = m_slaveAdr; + i2c_slave_address(&m_channel->i2c, 0, m_slaveAdr, 0); + } } int I2CDriver::readMaster(int address, char *data, int length, bool repeated) { - lock(); - m_channel->transfer.cmd = READ_MST; - m_channel->transfer.slv = false; - m_channel->transfer.adr = address; - m_channel->transfer.dta = data; - m_channel->transfer.len = length; - m_channel->transfer.rep = repeated; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1)); + unlock(); + return ret; } - int I2CDriver::readMaster(int address, uint8_t _register, char *data, int length, bool repeated) { - lock(); - m_channel->transfer.cmd = READ_MST_REG; - m_channel->transfer.slv = false; - m_channel->transfer.adr = address; - m_channel->transfer.reg = _register; - m_channel->transfer.dta = data; - m_channel->transfer.len = length; - m_channel->transfer.rep = repeated; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = FUNCTION(write)(&m_channel->i2c, address,(const char*)&_register, 1, 0); + if(!ret) ret = FUNCTION(read)(&m_channel->i2c, address, data, length, (repeated?0:1)); + unlock(); + return ret; } - int I2CDriver::readMaster(int ack) { - lock(); - m_channel->transfer.cmd = READ_BYTE; - m_channel->transfer.slv = false; - m_channel->transfer.ack = ack; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = i2cRtos_byte_read(&m_channel->i2c, (ack?0:1)); + unlock(); + return ret; } - int I2CDriver::writeMaster(int address, const char *data, int length, bool repeated) { - lock(); - m_channel->transfer.cmd = WRITE_MST; - m_channel->transfer.slv = false; - m_channel->transfer.adr = address; - m_channel->transfer.wdta = data; - m_channel->transfer.len = length; - m_channel->transfer.rep = repeated; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = FUNCTION(write)(&m_channel->i2c, address, data, length, (repeated?0:1)); + unlock(); + return ret; } - int I2CDriver::writeMaster(int data) { - lock(); - m_channel->transfer.cmd = WRITE_BYTE; - m_channel->transfer.slv = false; - m_channel->transfer.ack = data; - return sendNwait(); + m_modeSlave = false; + lockNconfig(); + int ret = i2cRtos_byte_write(&m_channel->i2c, data); + unlock(); + return ret; } - void I2CDriver::startMaster(void) { - lock(); - m_channel->transfer.cmd = START; - m_channel->transfer.slv = false; - sendNwait(); + m_modeSlave = false; + lockNconfig(); + i2c_start(&m_channel->i2c); + unlock(); } - -void I2CDriver::stopMaster(void) +bool I2CDriver::stopMaster(void) { - lock(); - m_channel->transfer.cmd = STOP; - m_channel->transfer.slv = false; - sendNwait(); + m_modeSlave = false; + lockNconfig(); + bool ret=i2cRtos_stop(&m_channel->i2c); + unlock(); + return ret; } - void I2CDriver::stopSlave(void) { - lock(); - m_channel->transfer.cmd = STOP; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - sendNwait(); + m_modeSlave = true; + lockNconfig(); + i2c_stop(&m_channel->i2c); + unlock(); } - int I2CDriver::receiveSlave(uint32_t timeout_ms) { - lock(); - m_channel->transfer.cmd = RECEIVE; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.tmout = timeout_ms; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_slave_receive(&m_channel->i2c, timeout_ms); + unlock(); + return ret; } - int I2CDriver::readSlave(char* data, int length) { - lock(); - m_channel->transfer.cmd = READ_SLV; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.dta = data; - m_channel->transfer.len = length; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_slave_read(&m_channel->i2c, data, length); + unlock(); + return ret; } - int I2CDriver::readSlave(void) { - lock(); - m_channel->transfer.cmd = READ_BYTE; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.ack = 1; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_byte_read(&m_channel->i2c, 0); + unlock(); + return ret; } - int I2CDriver::writeSlave(const char *data, int length) { - lock(); - m_channel->transfer.cmd = WRITE_SLV; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.wdta = data; - m_channel->transfer.len = length; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_slave_write(&m_channel->i2c, data, length); + unlock(); + return ret; } - int I2CDriver::writeSlave(int data) { - lock(); - m_channel->transfer.cmd = WRITE_BYTE; - m_channel->transfer.slv = true; - m_channel->transfer.adr = m_slaveAdr; - m_channel->transfer.ack = data; - return sendNwait(); + m_modeSlave = true; + lockNconfig(); + int ret = i2cRtos_byte_write(&m_channel->i2c, data); + unlock(); + return ret; }